diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..d26e34a --- /dev/null +++ b/Android.mk @@ -0,0 +1,279 @@ +ifeq ($(BOARD_USES_DVP),true) + +# Define our own prebuilt macro since the default one doesn't have a tag. +define add-prebuilt-object + include $$(CLEAR_VARS) + LOCAL_SRC_FILES := $(1) + LOCAL_MODULE_STEM := $(notdir $(basename $(1))) + LOCAL_MODULE_SUFFIX := $(suffix $(1)) + LOCAL_MODULE := $(notdir $(basename $(1))) + LOCAL_MODULE_CLASS := $(2) + LOCAL_MODULE_TAGS := $(3) + include $$(BUILD_PREBUILT) +endef + +TI_HW_ROOT ?= hardware/ti + +PLAT_NUMBERS := $(subst ., ,$(PLATFORM_VERSION)) +PLAT_MAJOR := $(word 1,$(PLAT_NUMBERS)) +PLAT_MINOR := $(word 2,$(PLAT_NUMBERS)) +ifeq ($(PLAT_MAJOR),2) + ifeq ($(PLAT_MINOR),2) + TARGET_ANDROID_VERSION := FROYO + else ifeq ($(PLAT_MINOR),3) + TARGET_ANDROID_VERSION := GINGERBREAD + endif +else ifeq ($(PLAT_MAJOR),3) + TARGET_ANDROID_VERSION := HONEYCOMB +else ifeq ($(PLAT_MAJOR),4) + ifeq ($(PLAT_MINOR),0) + TARGET_ANDROID_VERSION := ICS + else ifeq ($(PLAT_MINOR),1) + TARGET_ANDROID_VERSION := JELLYBEAN + endif +endif + +$(info Android Version $(TARGET_ANDROID_VERSION)) + +DVP_TOP := $(call my-dir) +SOSAL_TOP := $(call my-dir) + +#COMMIT_ID := $(shell cd $(DVP_TOP) && git show | grep commit | awk '{print $$2}') +COMMIT_ID := $(shell cd $(DVP_TOP) && git describe --tags --dirty) +$(info COMMIT_ID = $(COMMIT_ID)) + +ifeq ($(TARGET_ANDROID_VERSION), FROYO) + IPC_TYPE := syslink +else ifeq ($(TARGET_ANDROID_VERSION), GINGERBREAD) + IPC_TYPE := syslink +else ifeq ($(TARGET_ANDROID_VERSION), ICS) + IPC_TYPE := rpmsg +else ifeq ($(TARGET_ANDROID_VERSION), JELLYBEAN) + IPC_TYPE := rpmsg +endif + +$(info IPC_TYPE is $(IPC_TYPE)) + +ifeq ($(IPC_TYPE),syslink) + RCM_INC := $(TI_HW_ROOT)/syslink/syslink/api/include + IPC_INC := $(TI_HW_ROOT)/syslink/syslink/api/include + OMX_INC := $(TI_HW_ROOT)/omx/ducati/domx/system/omx_core/inc + OLD_MEMMGR := $(realpath $(TI_HW_ROOT)/tiler/memmgr ) + ifeq ($(OLD_MEMMGR),) + TILER_INC := $(TI_HW_ROOT)/tiler + TILER_LIB := libtimemmgr + else + TILER_INC := $(TI_HW_ROOT)/tiler/memmgr + TILER_LIB := libmemmgr + endif + DVP_SYSINCS := $(RCM_INC) $(IPC_INC) $(TILER_INC) $(OMX_INC) + DVP_SYSLIBS := librcm libsysmgr libipc $(TILER_LIB) + ifeq ($(TARGET_ANDROID_VERSION),HONEYCOMB) + DUCATI_VERSION := DUCATI_1_5 + endif +else ifeq ($(IPC_TYPE), rpmsg) + ifeq ($(TARGET_PLATFORM),TUNA) + OMX_INC := $(TI_HW_ROOT)/omap4xxx/domx/omx_core/inc + else + OMX_INC := $(TI_HW_ROOT)/domx/omx_core/inc + endif + DVP_SYSINCS := $(OMX_INC) \ + $(TI_HW_ROOT)/omap4xxx/ \ + hardware/libhardware/include + DVP_SYSLIBS := libion + DUCATI_VERSION := DUCATI_2_0 +endif + +DVP_INCLUDES := $(SOSAL_TOP)/include \ + $(DVP_TOP)/include \ + $(DVP_TOP)/source/dvp/dvp_kgraph/include \ + $(DVP_TOP)/source/dvp/dvp_display/include \ + $(DVP_SYSINCS) + +TARGET_CPU ?= ARM + +TARGET_PLATFORM ?= BLAZE +_T := $(TARGET_PLATFORM) +# Make sure to remove illegal C macro characters like '-' +TARGET_PLATFORM := $(subst -,_,$(_T)) + +TARGET_NUM_CORES := 2 + +# convert the product to a platform +ifeq ($(TARGET_PRODUCT),blaze_tablet) + TARGET_PLATFORM := BLAZE_TABLET +else ifeq ($(TARGET_PRODUCT),full_blaze) + TARGET_PLATFORM := BLAZE +else ifeq ($(TARGET_PRODUCT),full_panda) + TARGET_PLATFORM := PANDA +else ifeq ($(TARGET_PRODUCT),full_maguro) + TARGET_PLATFORM := TUNA +else ifeq ($(TARGET_PRODUCT),full_toro) + TARGET_PLATFORM := TUNA +else ifeq ($(TARGET_PRODUCT),full_torospr) + TARGET_PLATFORM := TUNA +else ifeq ($(TARGET_PRODUCT),full_tuna) + TARGET_PLATFORM := TUNA +else ifeq ($(TARGET_PRODUCT),full_omap5sevm) + TARGET_PLATFORM := OMAP5SEVM +endif + +ifeq ($(TARGET_PLATFORM),BLAZE) # OMAP4 Blaze Developer Board + SCREEN_DIM_X=864 + SCREEN_DIM_Y=480 +else ifeq ($(TARGET_PLATFORM),OMAP5SEVM) # OMAP5 SEVM Board + SCREEN_DIM_X=720 + SCREEN_DIM_Y=1280 +else ifeq ($(TARGET_PLATFORM),BLAZE_TABLET) # OMAP4 Blaze Developer Tablet 1 or 2 + SCREEN_DIM_X=1280 + SCREEN_DIM_Y=720 +else ifeq ($(TARGET_PLATFORM),PANDA) # OMAP4 Panda (HDMI Display) + SCREEN_DIM_X=1280 + SCREEN_DIM_Y=720 +else ifeq ($(TARGET_PLATFORM),SDP) # OMAP SDP Dev Board + SCREEN_DIM_X=864 + SCREEN_DIM_Y=480 +else ifeq ($(TARGET_PLATFORM),p920) # LG Optimus 3D + SCREEN_DIM_X=480 + SCREEN_DIM_Y=800 + DUCATI_VERSION=DUCATI_1_2 +else ifeq ($(TARGET_PLATFORM),p925) # LG Optimus 3D + SCREEN_DIM_X=480 + SCREEN_DIM_Y=800 + DUCATI_VERSION=DUCATI_1_2 +else ifeq ($(TARGET_PLATFORM),GT_I9100G) # Samsung Galaxy S II (OMAP variant) + SCREEN_DIM_X=480 + SCREEN_DIM_Y=800 + DUCATI_VERSION=DUCATI_1_2 +else ifeq ($(TARGET_PLATFORM),TUNA) # Samsung Galaxy Nexus ; Samsung Proxima + SCREEN_DIM_X=720 + SCREEN_DIM_Y=1280 + DUCATI_VERSION=DUCATI_2_0 +else ifeq ($(TARGET_PLATFORM),BLADE) # Toshiba AT200 + SCREEN_DIM_X=1280 + SCREEN_DIM_Y=800 + DUCATI_VERSION=DUCATI_2_0 +else +$(error "Unknown TARGET_PLATFORM!") +endif + +# Default to 2.0 if it's not set +DUCATI_VERSION ?= DUCATI_2_0 + +LOCAL_FLAGS := -pipe -Wall -Wno-trigraphs -fno-short-enums -Wno-psabi \ + -fno-strict-aliasing -mapcs -mno-sched-prolog -mabi=aapcs-linux \ + -mno-thumb-interwork -fno-common -fpic -Wno-write-strings \ + -DLINUX -DARCH_32 -D$(BUILD_ID) -DCOMMIT_ID="\"$(COMMIT_ID)\"" \ + -D$(TARGET_PLATFORM) -D$(TARGET_ANDROID_VERSION) -D$(TARGET_CPU) \ + -DSCREEN_DIM_X=$(SCREEN_DIM_X) -DSCREEN_DIM_Y=$(SCREEN_DIM_Y) \ + -DTARGET_NUM_CORES=$(TARGET_NUM_CORES) + +ifeq ($(PLATFORM_VERSION_CODENAME),AOSP) +LOCAL_FLAGS += -D$(PLATFORM_VERSION_CODENAME) +endif + +ifeq ($(TARGET_BOARD_PLATFORM),omap4) +LOCAL_FLAGS += -DTARGET_DVP_OMAP4 +endif +ifeq ($(TARGET_BOARD_PLATFORM),omap5) +LOCAL_FLAGS += -DTARGET_DVP_OMAP5 +endif +ifeq ($(TARGET_BOARD_PLATFORM),omap6) +LOCAL_FLAGS += -DTARGET_DVP_OMAP6 +endif + +DVP_FLAGS := -DDVP_TARGET_ARM -D$(DUCATI_VERSION) -DDVP_FLICKER=60 + +ifeq ($(IPC_TYPE),syslink) + +DVP_FLAGS += -DDVP_USE_IPC -DDVP_USE_RCM \ + -DDVP_USE_TILER -DSOSAL_USE_TILER \ + -DDVP_USE_SHARED_T -DSOSAL_USE_SHARED_T + +SOSAL_FLAGS := -DSOSAL_USE_TILER -DSOSAL_USE_SHARED_T + +else ifeq ($(IPC_TYPE),rpmsg) + +DVP_FLAGS += -DDVP_USE_IPC -DDVP_USE_OMAPRPC -DOMAPRPC_USE_ION \ + -DDVP_USE_ION -DSOSAL_USE_ION \ + -DDVP_USE_GRALLOC -DSOSAL_USE_GRALLOC \ + -DDVP_USE_SHARED_T -DSOSAL_USE_SHARED_T + +SOSAL_FLAGS := -DSOSAL_USE_ION -DSOSAL_USE_ION_TILER -DSOSAL_USE_GRALLOC -DSOSAL_USE_SHARED_T + +EXPORTED_3A := $(strip $(EXPORTED_3A)) + +ifdef EXPORTED_3A +$(info 3A Export Supported!) +DVP_FLAGS += -DEXPORTED_3A +endif + +ifdef CPCAM +$(info CPCAM Build Used!) +DVP_FLAGS += -DCPCAM +endif + +ifdef OMX_EXTENSIONS +$(info OMX Extensions used!) +DVP_FLAGS += -DCPCAM -DOMX_CAMERA_SUPPORTS_FD_RAW -DOMX_CAMERA_SUPPORTS_IMAGE_PYRAMID +endif + +endif # rpmsg + +# Android always has FS usage turned on +DVP_FLAGS += -DDVP_USE_FS + +DVP_CFLAGS := $(DVP_FLAGS) $(LOCAL_FLAGS) -Werror-implicit-function-declaration +DVP_CPPFLAGS := $(DVP_FLAGS) $(LOCAL_FLAGS) -fuse-cxa-atexit + +SOSAL_CFLAGS := $(SOSAL_FLAGS) $(LOCAL_FLAGS) -Werror-implicit-function-declaration +SOSAL_CPPFLAGS := $(SOSAL_FLAGS) $(LOCAL_FLAGS) -fuse-cxa-atexit + +ifdef DVP_NO_OPTIMIZE +DVP_CFLAGS += -ggdb -O0 +DVP_CPPFLAGS += -ggdb -O0 +else +DVP_CFLAGS += -O2 -fomit-frame-pointer +DVP_CPPFLAGS += -O2 -fomit-frame-pointer +endif + +ifdef SOSAL_NO_OPTIMIZE +SOSAL_CFLAGS += -ggdb -O0 +SOSAL_CPPFLAGS += -ggdb -O0 +else +SOSAL_CFLAGS += -O2 -fomit-frame-pointer +SOSAL_CPPFLAGS += -O2 -fomit-frame-pointer +endif + +ifdef DVP_DEBUG +DVP_DEBUGGING := -DDVP_DEBUG=$(DVP_DEBUG) +ifdef DVP_ZONE_MASK +DVP_DEBUGGING += -DDVP_ZONE_MASK=$(DVP_ZONE_MASK) +endif +endif + +ifdef SOSAL_DEBUG +SOSAL_DEBUGGING := -DSOSAL_DEBUG=$(SOSAL_DEBUG) +ifdef SOSAL_ZONE_MASK +SOSAL_DEBUGGING += -DSOSAL_ZONE_MASK=$(SOSAL_ZONE_MASK) +endif +endif + +ifdef OMAPRPC_DEBUG +OMAPRPC_DEBUGGING := -DOMAPRPC_DEBUG=$(OMAPRPC_DEBUG) +ifdef OMAPRPC_ZONE_MASK +OMAPRPC_DEBUGGING += -DOMAPRPC_ZONE_MASK=$(OMAPRPC_ZONE_MASK) +endif +endif + +DVP_LIBRARIES := +DVP_LOCAL_BUILD := true +# Each library which is present must enable itself in DVP via the DVP_LIBRARIES variable +include $(DVP_TOP)/libraries/Android.mk +include $(DVP_TOP)/source/Android.mk +DVP_LOCAL_BUILD := +DVP_TOP := +DVP_INC := +SOSAL_TOP := +SOSAL_INC := +endif diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..cfb1b52 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,188 @@ +Copyright (C) 2009-2011 Texas Instruments, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9e4d9e8 --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +# Clear out the values +DVP_INC := +DVP_FEATURES := +VISION_LIBRARIES := + +DVP_LOCAL_BUILD:=true +DIRECTORIES:=libraries source packages docs + +ifdef DVP_NO_OPTIMIZE +NO_OPTIMIZE:=$(DVP_NO_OPTIMIZE) +endif + +include concerto/rules.mak + +$(info DVP_FEATURES=$(DVP_FEATURES)) +$(info DVP_INC=$(DVP_INC)) +$(info VISION_LIBRARIES=$(VISION_LIBRARIES)) + diff --git a/NOTICE.txt b/NOTICE.txt new file mode 100644 index 0000000..6b2cb19 --- /dev/null +++ b/NOTICE.txt @@ -0,0 +1,3 @@ +This project contains no 3rd party source code. All code is the product of +Texas Instruments, Inc and is licensed under the licenses provided in the +header of each file. diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..17d3c90 --- /dev/null +++ b/README.txt @@ -0,0 +1,57 @@ +Distributred Vision Processing (DVP) for OMAP Devices +============================================== + +This repository is composed of +1.) DVP Kernel Graph API is composed of + a.) DVP Kernel Graph Boss - which divies up work to the + 1.) DVP Kernel Graph Managers (A9/DSP/M3) - which call the algorithms of + a.) VLIB, RVM, YUV, etc... +2.) SOSAL - Simple Operating System Abstraction - simple wrapper for Win32/POSIX APIs (just what is needed) + +Build Instructions (under Linux/Cygwin but not for Android) for PC: +=============================================================================== +$ export TARGET_PLATFORM=PC +# To enable debugging statements +$ export DVP_DEBUG=1 +$ export SOSAL_DEBUG=1 +# To enable certain zones, set the hexidecimal number for each zone (bit) 0xFFFF is all zones +$ export DVP_ZONE_MASK=0xFFFFFFFF +$ export SOSAL_ZONE_MASK=0xFFFFFFFF +or you can run the +$ ./env.sh + +then + +$ make clean +$ make +$ make test + +If you are building in Windows in a DOS prompt, use the MinGW's make.exe with the +same targets as above. (replace export with SET or run the env.bat) + +Build Instructions (under Android): +=============================================================================== +$ cd $(MYDROID) +$ hardware/ti/dvp/scripts/dvp.sh clean mm + +Build Instructions (for QNX): +=============================================================================== +Install the QNX Build System and Configure your environment, then: +$ export IPC_ROOT= +$ export TILER_ROOT= +$ export DVP_ROOT= +$ export SOSAL_ROOT=$DVP_ROOT +$ export TARGET_PLATFORM=PLAYBOOK +$ make clean +$ make + +DESCRIPTION: +=============================================================================== +dvp.sh - build script for android +dvp.bat - Install script for Android phones which can only connect on Windows. +env.sh - Bash script for development build environment +env.bat - Batch script for development build environment +Android.mk - Android Top Level Build Makefile +Makefile - makefiles for non-Android builds + + diff --git a/bin/bitimg2img b/bin/bitimg2img new file mode 100755 index 0000000..470827a Binary files /dev/null and b/bin/bitimg2img differ diff --git a/bin/extra_data_parser b/bin/extra_data_parser new file mode 100755 index 0000000..de35722 Binary files /dev/null and b/bin/extra_data_parser differ diff --git a/bin/imgDiff b/bin/imgDiff new file mode 100755 index 0000000..c7ffeb9 Binary files /dev/null and b/bin/imgDiff differ diff --git a/concerto/cgt6x.mak b/concerto/cgt6x.mak new file mode 100644 index 0000000..08c5eff --- /dev/null +++ b/concerto/cgt6x.mak @@ -0,0 +1,223 @@ +# Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifndef CGT6X_ROOT +$(error You must define CGT6X_ROOT!) +endif + +ifndef XDC_ROOT +$(error You must define XDC_ROOT!) +endif + +CC=$(CGT6X_ROOT)/bin/cl6x +CP=$(CGT6X_ROOT)/bin/cl6x +AS=$(CGT6X_ROOT)/bin/asm6x +AR=$(CGT6X_ROOT)/bin/ar6x +LD=$(CGT6X_ROOT)/bin/lnk6x + +ifdef LOGFILE +LOGGING:=&>$(LOGFILE) +else +LOGGING:= +endif + +ifeq ($(strip $($(_MODULE)_TYPE)),library) + BIN_PRE=WTSD_TESLAMMSW.alg. + BIN_EXT=.ae64T +else ifeq ($(strip $($(_MODULE)_TYPE)),dsmo) + BIN_PRE=WTSD_TESLAMMSW.alg. + BIN_EXT=.ae64T +else + BIN_PRE=WTSD_TESLAMMSW.alg. + BIN_EXT=.xe64T +endif + +$(_MODULE)_BIN := $($(_MODULE)_TDIR)/$(BIN_PRE)$(TARGET)$(BIN_EXT) +$(_MODULE)_OBJS := $(ASSEMBLY:%.asm=$($(_MODULE)_ODIR)/%.obj) $(CPPSOURCES:%.cpp=$($(_MODULE)_ODIR)/%.obj) $(CSOURCES:%.c=$($(_MODULE)_ODIR)/%.obj) +$(_MODULE)_ASM := $(ASSEMBLY:%.asm=$($(_MODULE)_ODIR)/%.asm) $(CPPSOURCES:%.cpp=$($(_MODULE)_ODIR)/%.asm) $(CSOURCES:%.c=$($(_MODULE)_ODIR)/%.asm) +$(_MODULE)_NFO := $(ASSEMBLY:%.nfo=$($(_MODULE)_ODIR)/%.nfo) $(CPPSOURCES:%.cpp=$($(_MODULE)_ODIR)/%.nfo) $(CSOURCES:%.c=$($(_MODULE)_ODIR)/%.nfo) +# Redefine the local static libs and shared libs with REAL paths and pre/post-fixes +$(_MODULE)_STATIC_LIBS := $(foreach lib,$(STATIC_LIBS),$($(_MODULE)_TDIR)/WTSD_TESLAMMSW.alg.$(lib).ae64T) +$(_MODULE)_SHARED_LIBS := $(foreach lib,$(SHARED_LIBS),$($(_MODULE)_TDIR)/WTSD_TESLAMMSW.alg.$(lib).ae64T) + +$(_MODULE)_COPT := -pdr -k -mw -pdsw225 --mem_model:data=far +# -pdr = Issues remarks (nonserious warnings) +# -k = Keeps the assembly language (.asm) file +# -mw = Produce verbose software pipelining report +# -pdsw225 = + +ifeq ($(TARGET_BUILD),debug) +$(_MODULE)_COPT += --opt_level=0 -g +else ifeq ($(TARGET_BUILD),release) +$(_MODULE)_COPT += --opt_level=3 --gen_opt_info=2 +endif + +ifeq ($(TARGET_CPU),C64T) +$(_MODULE)_COPT +=-mvtesla -D=xdc_target_name__=C64T +else ifeq ($(TARGET_CPU),C64P) +$(_MODULE)_COPT +=-mv6400+ -D=xdc_target_name__=C64P +else ifeq ($(TARGET_CPU),C64X) +$(_MODULE)_COPT +=-mv6400 +endif + +$(_MODULE)_COPT +=-D=xdc_target_types__=ti/targets/elf/std.h -D=___DSPBIOS___ + +$(_MODULE)_MAP := -m=$($(_MODULE)_BIN).map +$(_MODULE)_INCLUDES := $(foreach inc,$($(_MODULE)_IDIRS),-I=$(inc)) +$(_MODULE)_DEFINES := $(foreach def,$($(_MODULE)_DEFS),-D=$(def)) +$(_MODULE)_LIBRARIES:= $(foreach ldir,$($(_MODULE)_LDIRS),--search_path=$(ldir)) $(foreach lib,$(STATIC_LIBS),--library=WTSD_TESLAMMSW.alg.$(lib).ae64T) $(foreach lib,$(SYS_STATIC_LIBS),--library=WTSD_TESLAMMSW.alg.$(lib).ae64T) +$(_MODULE)_AFLAGS := $($(_MODULE)_INCLUDES) +$(_MODULE)_LDFLAGS := -z --warn_sections --search_path="$(CGT6X_ROOT)/lib" -I="$(CGT6X_ROOT)/include" --reread_libs --rom_model +$(_MODULE)_CPLDFLAGS := $(foreach ldf,$($(_MODULE)_LDFLAGS), $(ldf)) +$(_MODULE)_CFLAGS := $($(_MODULE)_INCLUDES) $($(_MODULE)_DEFINES) $($(_MODULE)_COPT) -fs=$($(_MODULE)_ODIR) -I="$(CGT6X_ROOT)/include/" -I="$(XDC_ROOT)/packages/" + + +################################################### +# COMMANDS +################################################### + +LINK := ln -s +CLEAN := rm -f +CLEANDIR := rm -rf +COPY := cp -f + +$(_MODULE)_CLEAN_OBJ := $(CLEAN) $($(_MODULE)_OBJS) $($(_MODULE)_ASM) $($(_MODULE)_NFO) +$(_MODULE)_CLEAN_BIN := $(CLEAN) $($(_MODULE)_BIN) +$(_MODULE)_LINK_LIB := $(AR) ru2 $($(_MODULE)_BIN) $($(_MODULE)_OBJS) #$($(_MODULE)_STATIC_LIBS) +$(_MODULE)_LINK_EXE := $(CP) $($(_MODULE)_CPLDFLAGS) -o $($(_MODULE)_BIN) $($(_MODULE)_OBJS) $($(_MODULE)_LIBRARIES) $($(_MODULE)_MAP) $($(_MODULE)_SDIR)/$(LCMD) + +################################################### +# MACROS FOR COMPILING +################################################### + +define $(_MODULE)_DEPEND_CC + +#$($(_MODULE)_ODIR)/$(1).d: $($(_MODULE)_SDIR)/$(1).c $($(_MODULE)_SDIR)/$(SUBMAKEFILE) $($(_MODULE)_ODIR)/.gitignore +# @echo Generating Dependency Info from $$(notdir $$<) +# $(Q)$(CC) $($(_MODULE)_INCLUDES) -i"$(CGT6X_ROOT)/include" $($(_MODULE)_DEFINES) -ppd=$($(_MODULE)_ODIR)/$(1).d -fd=$($(_MODULE)_ODIR) $$< $(LOGGING) +# +#depend:: $($(_MODULE)_ODIR)/$(1).d +# +#-include $($(_MODULE)_ODIR)/$(1).d + +endef + +define $(_MODULE)_DEPEND_CP + +#$($(_MODULE)_ODIR)/$(1).d: $($(_MODULE)_SDIR)/$(1).cpp $($(_MODULE)_SDIR)/$(SUBMAKEFILE) $($(_MODULE)_ODIR)/.gitignore +# @echo Generating Dependency Info from $$(notdir $$<) +# $(Q)$(CC) $($(_MODULE)_INCLUDES) -i"$(CGT6X_ROOT)/include" $($(_MODULE)_DEFINES) -ppd=$($(_MODULE)_ODIR)/$(1).d -fd=$($(_MODULE)_ODIR) $$< $(LOGGING) +# +#depend:: $($(_MODULE)_ODIR)/$(1).d +# +#-include $($(_MODULE)_ODIR)/$(1).d + +endef + +define $(_MODULE)_DEPEND_AS +# Do nothing... +endef + +ifeq ($(strip $($(_MODULE)_TYPE)),prebuilt) + +define $(_MODULE)_PREBUILT + +$($(_MODULE)_SDIR)/$(1): + +build:: $($(_MODULE)_SDIR)/$(1) + +install:: $($(_MODULE)_TDIR)/$(notdir $(1)) + +$($(_MODULE)_TDIR)/$(notdir $(1)): $($(_MODULE)_SDIR)/$(1) $($(_MODULE)_ODIR)/.gitignore + @echo Copying Prebuilt binary $($(_MODULE)_SDIR)/$(1) to $($(_MODULE)_TDIR)/$(notdir $(1)) + -$(Q)$(COPY) $($(_MODULE)_SDIR)/$(1) $($(_MODULE)_TDIR)/$(notdir $(1)) +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),library) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo No uninstall step for static libraries +endef + +define $(_MODULE)_INSTALL +install:: + @echo No install step for static libraries +endef + +define $(_MODULE)_BUILD +build:: $($(_MODULE)_BIN) +endef + +define $(_MODULE)_CLEAN_LNK +clean:: +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),dsmo) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo No dynamic objects are supported ! +endef + +define $(_MODULE)_INSTALL +install:: + @echo No dynamic objects are supported ! +endef + +define $(_MODULE)_BUILD +build:: @echo No dynamic objects are supported ! +endef + +define $(_MODULE)_CLEAN_LNK +clean:: + @echo No dynamic objects are supported ! +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),exe) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo No uninstall step for $(TARGET_CPU) +endef + +define $(_MODULE)_INSTALL +install:: + @echo No install step for $(TARGET_CPU) +endef + +define $(_MODULE)_BUILD +build:: $($(_MODULE)_BIN) + @echo Building for $($(_MODULE)_BIN) +endef + +define $(_MODULE)_CLEAN_LNK +clean:: +endef + +endif + +define $(_MODULE)_COMPILE_TOOLS +$($(_MODULE)_ODIR)/%.obj: $($(_MODULE)_SDIR)/%.c $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Compiling C99 $$(notdir $$<) + $(Q)$(CC) -c $($(_MODULE)_CFLAGS) -fr=$$(dir $$@) $$< $(LOGGING) + +$($(_MODULE)_ODIR)/%.obj: $($(_MODULE)_SDIR)/%.cpp $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Compiling C++ $$(notdir $$<) + $(Q)$(CP) -c $($(_MODULE)_CFLAGS) -fr=$$(dir $$@) $$< $(LOGGING) + +$($(_MODULE)_ODIR)/%.obj: $($(_MODULE)_SDIR)/%.asm $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Assembling $$(notdir $$<) + $(Q)$(AS) -c $($(_MODULE)_AFLAGS) -fr=$$(dir $$@) $$< $(LOGGING) +endef diff --git a/concerto/cl.mak b/concerto/cl.mak new file mode 100644 index 0000000..034f906 --- /dev/null +++ b/concerto/cl.mak @@ -0,0 +1,209 @@ +# Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +CC = CL +CP = CL +AS = $(TARGET_CPU)ASM +AR = LIB +LD = LINK + +ifdef LOGFILE +LOGGING=>$(LOGFILE) +endif + +ifeq ($(strip $(TARGETTYPE)),library) + BIN_PRE= + BIN_EXT=.lib +else ifeq ($(strip $(TARGETTYPE)),dsmo) + BIN_PRE= + BIN_EXT=.dll +else ifeq ($(strip $(TARGETTYPE)),exe) + BIN_PRE= + BIN_EXT=.exe +endif + +$(_MODULE)_SYS_SHARED_LIBS += user32 + +$(_MODULE)_BIN := $($(_MODULE)_TDIR)/$(BIN_PRE)$(TARGET)$(BIN_EXT) +$(_MODULE)_OBJS := $(ASSEMBLY:%.S=$($(_MODULE)_ODIR)/%.obj) $(CPPSOURCES:%.cpp=$($(_MODULE)_ODIR)/%.obj) $(CSOURCES:%.c=$($(_MODULE)_ODIR)/%.obj) +$(_MODULE)_STATIC_LIBS := $(foreach lib,$(STATIC_LIBS),$($(_MODULE)_TDIR)/$(lib).lib) +$(_MODULE)_SHARED_LIBS := $(foreach lib,$(SHARED_LIBS),$($(_MODULE)_TDIR)/$(lib).dll) +$(_MODULE)_PDB := $($(_MODULE)_ODIR)/$(TARGET).pdb + +$(_MODULE)_COPT+=/EHsc /W3 +ifeq ($(TARGET_CPU),X64) +$(_MODULE)_COPT+=/Wp64 +endif +ifeq ($(TARGET_BUILD),debug) +$(_MODULE)_COPT+=/Od /MDd /Gm /Zi /RTC1 +else ifeq ($(TARGET_BUILD),release) +$(_MODULE)_COPT+=/Ox /MD +endif + +$(_MODULE)_INCLUDES := $(foreach inc,$(call PATH_CONV,$($(_MODULE)_IDIRS)),/I$(inc)) +$(_MODULE)_DEFINES := $(foreach def,$($(_MODULE)_DEFS),/D$(def)) +$(_MODULE)_LIBRARIES:= $(foreach ldir,$(call PATH_CONV,$($(_MODULE)_LDIRS)),/LIBPATH:$(ldir)) $(foreach lib,$(STATIC_LIBS),$(lib).lib) $(foreach lib,$(SHARED_LIBS),$(lib).lib) $(foreach lib,$(SYS_STATIC_LIBS),$(lib).lib) $(foreach lib,$(SYS_SHARED_LIBS),$(lib).lib) +$(_MODULE)_ARFLAGS := /nologo /MACHINE:$(TARGET_CPU) +$(_MODULE)_AFLAGS := $($(_MODULE)_INCLUDES) +$(_MODULE)_LDFLAGS := /nologo /MACHINE:$(TARGET_CPU) +$(_MODULE)_CFLAGS := /c /nologo $($(_MODULE)_INCLUDES) $($(_MODULE)_DEFINES) $($(_MODULE)_COPT) + +ifdef ENTRY +$(_MODULE)_ENTRY := $(ENTRY) +$(_MODULE)_LDFLAGS += /ENTRY:$($(_MODULE)_ENTRY) /SUBSYSTEM:WINDOWS +endif + +ifdef DEFFILE +$(_MODULE)_DEF:=/DEF:$(call PATH_CONV,$($(_MODULE)_SDIR)/$(DEFFILE)) +else +$(_MODULE)_DEF:= +endif + +ifeq ($(TARGET_BUILD),debug) +$(_MODULE)_LDFLAGS += /DEBUG +endif + +################################################### +# COMMANDS +################################################### + +$(_MODULE)_CLEAN_OBJ := $(CLEAN) $(call PATH_CONV,$($(_MODULE)_OBJS)) +$(_MODULE)_CLEAN_BIN := $(CLEAN) $(call PATH_CONV,$($(_MODULE)_BIN)) +$(_MODULE)_ATTRIB_EXE := $(ATTRIB) $(call PATH_CONV,$($(_MODULE)_BIN)) +$(_MODULE)_LN_DS0 := $(SET_RW) $(call PATH_CONV,$($(_MODULE)_BIN)) +$(_MODULE)_UNLN_DSO := $(SET_RW) $(call PATH_CONV,$($(_MODULE)_BIN)) +$(_MODULE)_INSTALL_DSO := $(COPY) $(call PATH_CONV,$($(_MODULE)_TDIR)\\$($(_MODULE)_BIN)) $(call PATH_CONV,$($(_MODULE)_INSTALL_LIB)) +$(_MODULE)_UNINSTALL_DSO := $(CLEAN) $(call PATH_CONV,$($(_MODULE)_INSTALL_LIB)\\$($(_MODULE)_BIN)) +$(_MODULE)_INSTALL_EXE := $(COPY) $(call PATH_CONV,$($(_MODULE)_TDIR)\\$($(_MODULE)_BIN)) $(call PATH_CONV,$($(_MODULE)_INSTALL_BIN)) +$(_MODULE)_UNINSTALL_EXE := $(CLEAN) $(call PATH_CONV,$($(_MODULE)_INSTALL_BIN)\\$($(_MODULE)_BIN)) +$(_MODULE)_LINK_LIB := $(AR) $($(_MODULE)_ARFLAGS) /OUT:$(call PATH_CONV,$($(_MODULE)_BIN)) $(call PATH_CONV,$($(_MODULE)_OBJS)) $(call PATH_CONV,$($(_MODULE)_LIBS)) +$(_MODULE)_LINK_EXE := $(LD) $($(_MODULE)_LDFLAGS) $(call PATH_CONV,$($(_MODULE)_OBJS)) $($(_MODULE)_LIBRARIES) /OUT:$(call PATH_CONV,$($(_MODULE)_BIN)) +$(_MODULE)_LINK_DSO := $(LD) $($(_MODULE)_LDFLAGS) $(call PATH_CONV,$($(_MODULE)_OBJS)) $($(_MODULE)_LIBRARIES) /DLL $($(_MODULE)_DEF) /OUT:$(call PATH_CONV,$($(_MODULE)_BIN)) + +################################################### +# MACROS FOR COMPILING +################################################### + +define $(_MODULE)_DEPEND_CC +endef + +define $(_MODULE)_DEPEND_CP +endef + +define $(_MODULE)_DEPEND_AS +endef + +ifeq ($(strip $($(_MODULE)_TYPE)),prebuilt) + +define $(_MODULE)_PREBUILT +$(info PREBUILT=$(1)) +$(info target=$(call PATH_CONV,$($(_MODULE)_TDIR)/$(1))) + +$($(_MODULE)_SDIR)/$(1): + +build:: $($(_MODULE)_TDIR)/$(notdir $(1)) + +install:: $($(_MODULE)_TDIR)/$(1)) + +$($(_MODULE)_TDIR)/$(notdir $(1)): $($(_MODULE)_SDIR)/$(1) $($(_MODULE)_ODIR)/.gitignore + @echo Copying Prebuilt binary to $($(_MODULE)_TDIR) + -$(Q)$(COPY) $(call PATH_CONV,$($(_MODULE)_SDIR)/$(1)) $(call PATH_CONV,$($(_MODULE)_TDIR)/$(notdir $(1))) +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),library) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo No uninstall step for static libraries +endef + +define $(_MODULE)_INSTALL +install:: + @echo No install step for static libraries +endef + +define $(_MODULE)_BUILD +build:: $($(_MODULE)_BIN) +endef + +define $(_MODULE)_CLEAN_LNK +clean:: + @echo No clean link step for static libraries +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),dsmo) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo Uninstalling $$@ + -$(Q)$(call $(_MODULE)_UNLN_DSO) + -$(Q)$(call $(_MODULE)_UNINSTALL_DSO) +endef + +define $(_MODULE)_INSTALL +install:: + @echo Installing $($(_MODULE)_BIN) + -$(Q)$(call $(_MODULE)_INSTALL_DSO) + -$(Q)$(call $(_MODULE)_LN_DSO) +endef + +define $(_MODULE)_BUILD +build:: $($(_MODULE)_BIN) +endef + +define $(_MODULE)_CLEAN_LNK +clean:: + @echo Removing Link for Shared Object $($(_MODULE)_BIN).1.0 + -$(Q)$(CLEAN) $(call PATH_CONV,$($(_MODULE)_BIN).1.0) +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),exe) + +define $(_MODULE)_UNINSTALL +uninstall:: + -$(Q)$(call $(_MODULE)_UNINSTALL_EXE) +endef + +define $(_MODULE)_INSTALL +install:: + @echo Installing $($(_MODULE)_BIN) + -$(Q)$(call $(_MODULE)_INSTALL_EXE) + -$(Q)$(call $(_MODULE)_ATTRIB_EXE) +endef + +define $(_MODULE)_BUILD +build:: $($(_MODULE)_BIN) + @echo Building for $($(_MODULE)_BIN) +endef + +define $(_MODULE)_CLEAN_LNK +clean:: + @echo No clean link step for exes +endef + +endif + +define $(_MODULE)_COMPILE_TOOLS +$($(_MODULE)_ODIR)/%.obj: $($(_MODULE)_SDIR)/%.c $($(_MODULE)_ODIR)/.gitignore +# @echo [PURE] Compiling C99 $$(notdir $$<) + $(Q)$(CC) $($(_MODULE)_CFLAGS) $$(call PATH_CONV,$$<) /Fo$$(call PATH_CONV,$$@) /Fd$$(call PATH_CONV,$($(_MODULE)_ODIR)/$$(notdir $$(basename $$<)).pdb) $(LOGGING) + +$($(_MODULE)_ODIR)/%.obj: $($(_MODULE)_SDIR)/%.cpp $($(_MODULE)_ODIR)/.gitignore +# @echo [PURE] Compiling C++ $$(notdir $$<) + $(Q)$(CP) $($(_MODULE)_CFLAGS) $$(call PATH_CONV,$$<) /Fo$$(call PATH_CONV,$$@) /Fd$$(call PATH_CONV,$($(_MODULE)_ODIR)/$$(notdir $$(basename $$<)).pdb) $(LOGGING) + +$($(_MODULE)_ODIR)/%.obj: $($(_MODULE)_SDIR)/%.S $($(_MODULE)_ODIR)/.gitignore +# @echo [PURE] Assembling $$(notdir $$<) + $(Q)$(AS) $($(_MODULE)_AFLAGS) $$(call PATH_CONV,$$<) /Fo$$(call PATH_CONV,$$@) /Fd$$(call PATH_CONV,$($(_MODULE)_ODIR)/$$(notdir $$(basename $$<)).pdb) $(LOGGING) +endef diff --git a/concerto/clang.mak b/concerto/clang.mak new file mode 100644 index 0000000..d99f429 --- /dev/null +++ b/concerto/clang.mak @@ -0,0 +1,249 @@ +# Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_CPU),$(HOST_CPU)) + CROSS_COMPILE= +endif + +CC = $(CROSS_COMPILE)clang +CP = $(CROSS_COMPILE)clang++ +AS = $(CROSS_COMPILE)as +AR = $(CROSS_COMPILE)ar +LD = $(CROSS_COMPILE)gcc + +ifdef LOGFILE +LOGGING:=&>$(LOGFILE) +else +LOGGING:= +endif + +ifeq ($(TARGET_OS),DARWIN) +DSO_EXT := .dylib +else ifeq ($(TARGET_OS),CYGWIN) +DSO_EXT := .dll.a +else +DSO_EXT := .so +endif + +ifeq ($(strip $($(_MODULE)_TYPE)),library) + BIN_PRE=lib + BIN_EXT=.a +else ifeq ($(strip $($(_MODULE)_TYPE)),dsmo) + BIN_PRE=lib + BIN_EXT=$(DSO_EXT) +else + BIN_PRE= + BIN_EXT= +endif + +ifneq ($($(_MODULE)_TYPE),prebuilt) +$(_MODULE)_OUT := $(BIN_PRE)$(TARGET)$(BIN_EXT) +else +$(_MODULE)_OUT := $(notdir $(PREBUILT)) +endif +$(_MODULE)_BIN := $($(_MODULE)_TDIR)/$($(_MODULE)_OUT) +$(_MODULE)_OBJS := $(ASSEMBLY:%.S=$($(_MODULE)_ODIR)/%.o) $(CPPSOURCES:%.cpp=$($(_MODULE)_ODIR)/%.o) $(CSOURCES:%.c=$($(_MODULE)_ODIR)/%.o) +# Redefine the local static libs and shared libs with REAL paths and pre/post-fixes +$(_MODULE)_STATIC_LIBS := $(foreach lib,$(STATIC_LIBS),$($(_MODULE)_TDIR)/lib$(lib).a) +$(_MODULE)_SHARED_LIBS := $(foreach lib,$(SHARED_LIBS),$($(_MODULE)_TDIR)/lib$(lib)$(DSO_EXT)) +$(_MODULE)_DEP_HEADERS := $(foreach inc,$($(_MODULE)_HEADERS),$($(_MODULE)_SDIR)/$(inc).h) + +$(_MODULE)_COPT := $(CFLAGS) +$(_MODULE)_LOPT := $(LDFLAGS) +ifneq ($(TARGET_OS),CYGWIN) +$(_MODULE)_COPT += -fPIC +endif +$(_MODULE)_COPT += -Wno-deprecated + +ifeq ($(TARGET_BUILD),debug) +$(_MODULE)_COPT += -O0 -ggdb3 +$(_MODULE)_LOPT += -g +else ifeq ($(TARGET_BUILD),release) +$(_MODULE)_COPT += -O3 +endif + +ifeq ($(TARGET_CPU),ARM) +$(_MODULE)_COPT += -mapcs -mno-sched-prolog -mno-thumb-interwork +ifeq ($(TARGET_OS),LINUX) +$(_MODULE)_COPT += -mabi=aapcs-linux +endif +endif + +ifeq ($(TARGET_ARCH),32) +ifneq ($(TARGET_CPU),ARM) +$(_MODULE)_COPT += -m32 -fno-stack-protector +endif +endif + +$(_MODULE)_DEPHDR := $(foreach hdr,$($(_MODULE)_HEADERS),$($(_MODULE)_SDIR)/$(hdr).h) +$(_MODULE)_MAP := -Map=$($(_MODULE)_BIN).map +$(_MODULE)_INCLUDES := $(foreach inc,$($(_MODULE)_IDIRS),-I$(inc)) +$(_MODULE)_DEFINES := $(foreach def,$($(_MODULE)_DEFS),-D$(def)) +$(_MODULE)_LIBRARIES:= $(foreach ldir,$($(_MODULE)_LDIRS),-L$(ldir)) $(foreach lib,$(STATIC_LIBS),-l$(lib)) $(foreach lib,$(SYS_STATIC_LIBS),-l$(lib)) $(foreach lib,$(SHARED_LIBS),-l$(lib)) $(foreach lib,$(SYS_SHARED_LIBS),-l$(lib)) +$(_MODULE)_AFLAGS := $($(_MODULE)_INCLUDES) +ifeq ($(HOST_OS),DARWIN) +$(_MODULE)_LDFLAGS := -arch $(TARGET_CPU) +endif +$(_MODULE)_LDFLAGS += $($(_MODULE)_LOPT) +$(_MODULE)_CPLDFLAGS := $(foreach ldf,$($(_MODULE)_LDFLAGS),-Wl,$(ldf)) $($(_MODULE)_COPT) +$(_MODULE)_CFLAGS := -c $($(_MODULE)_INCLUDES) $($(_MODULE)_DEFINES) $($(_MODULE)_COPT) + +ifdef DEBUG +$(_MODULE)_AFLAGS += --gdwarf-2 +endif + +################################################### +# COMMANDS +################################################### + +ifneq ($(TARGET_OS),CYGWIN) +EXPORT_FLAG:=--export-dynamic +else +#EXPORT_FLAG:=--export-all-symbols +endif + +$(_MODULE)_CLEAN_OBJ := $(CLEAN) $($(_MODULE)_OBJS) +$(_MODULE)_CLEAN_BIN := $(CLEAN) $($(_MODULE)_BIN) +$(_MODULE)_ATTRIB_EXE := $(SET_EXEC) $($(_MODULE)_BIN) +$(_MODULE)_LN_DSO := $(LINK) $($(_MODULE)_BIN).1.0 $($(_MODULE)_BIN) +$(_MODULE)_LN_INST_DSO:= $(LINK) $($(_MODULE)_INSTALL_LIB)/$($(_MODULE)_OUT).1.0 $($(_MODULE)_INSTALL_LIB)/$($(_MODULE)_OUT) +$(_MODULE)_UNLN_DSO := $(CLEAN) $($(_MODULE)_BIN).1.0 +$(_MODULE)_UNLN_INST_DSO:= $(CLEAN) $($(_MODULE)_INSTALL_LIB)/$($(_MODULE)_OUT).1.0 +$(_MODULE)_INSTALL_DSO:= $(INSTALL) $($(_MODULE)_BIN).1.0 $($(_MODULE)_INSTALL_LIB) +$(_MODULE)_UNINSTALL_DSO:=$(CLEAN) $($(_MODULE)_INSTALL_LIB)/$($(_MODULE)_OUT) +$(_MODULE)_INSTALL_EXE:= $(INSTALL) $($(_MODULE)_BIN) $($(_MODULE)_INSTALL_BIN) +$(_MODULE)_UNINSTALL_EXE:=$(CLEAN) $($(_MODULE)_INSTALL_BIN)/$($(_MODULE)_OUT) +$(_MODULE)_LINK_LIB := $(AR) -rscu $($(_MODULE)_BIN) $($(_MODULE)_OBJS) #$($(_MODULE)_STATIC_LIBS) +ifeq ($(TARGET_OS),DARWIN) +$(_MODULE)_LINK_DSO := $(LD) -dylib $($(_MODULE)_LDFLAGS) -all_load $($(_MODULE)_LIBRARIES) -lm -o $($(_MODULE)_BIN).1.0 $($(_MODULE)_OBJS) +$(_MODULE)_LINK_EXE := $(CP) -rdynamic $($(_MODULE)_CPLDFLAGS) $($(_MODULE)_OBJS) $($(_MODULE)_LIBRARIES) -o $($(_MODULE)_BIN) +else +$(_MODULE)_LINK_DSO := $(LD) $($(_MODULE)_LDFLAGS) -shared -Wl,$(EXPORT_FLAG) -Wl,-soname,$($(_MODULE)_BIN).1.0 -Wl,--whole-archive $($(_MODULE)_LIBRARIES) -lm -Wl,--no-whole-archive -o $($(_MODULE)_BIN).1.0 $($(_MODULE)_OBJS) $($(_MODULE)_MAP) +$(_MODULE)_LINK_EXE := $(CP) -rdynamic -Wl,--cref $($(_MODULE)_CPLDFLAGS) $($(_MODULE)_OBJS) $($(_MODULE)_LIBRARIES) -o $($(_MODULE)_BIN) -Wl,$($(_MODULE)_MAP) +endif + +################################################### +# MACROS FOR COMPILING +################################################### + +define $(_MODULE)_DEPEND_CC +endef + +define $(_MODULE)_DEPEND_CP +endef + +define $(_MODULE)_DEPEND_AS +# Do nothing... +endef + +ifeq ($(strip $($(_MODULE)_TYPE)),prebuilt) + +define $(_MODULE)_PREBUILT + +$($(_MODULE)_SDIR)/$(1): + +build:: $($(_MODULE)_SDIR)/$(1) + +install:: $($(_MODULE)_TDIR)/$(notdir $(1)) + +$($(_MODULE)_TDIR)/$(notdir $(1)): $($(_MODULE)_SDIR)/$(1) $($(_MODULE)_ODIR)/.gitignore + @echo Copying Prebuilt binary $($(_MODULE)_SDIR)/$(1) to $($(_MODULE)_TDIR)/$(notdir $(1)) + -$(Q)$(COPY) $($(_MODULE)_SDIR)/$(1) $($(_MODULE)_TDIR)/$(notdir $(1)) +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),library) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo No uninstall step for static libraries +endef + +define $(_MODULE)_INSTALL +install:: $($(_MODULE)_BIN) + @echo No install step for static libraries +endef + +define $(_MODULE)_BUILD +build:: $($(_MODULE)_BIN) +endef + +define $(_MODULE)_CLEAN_LNK +clean:: +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),dsmo) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo Uninstalling $($(_MODULE)_BIN) from $($(_MODULE)_INSTALL_LIB) + -$(Q)$(call $(_MODULE)_UNLN_INST_DSO) + -$(Q)$(call $(_MODULE)_UNINSTALL_DSO) +endef + +define $(_MODULE)_INSTALL +install:: $($(_MODULE)_BIN) + @echo Installing $($(_MODULE)_BIN) to $($(_MODULE)_INSTALL_LIB) + -$(Q)$(call $(_MODULE)_INSTALL_DSO) + -$(Q)$(call $(_MODULE)_LN_INST_DSO) +endef + +define $(_MODULE)_BUILD +build:: $($(_MODULE)_BIN) +endef + +define $(_MODULE)_CLEAN_LNK +clean:: + @echo Removing Link for Shared Object $($(_MODULE)_BIN).1.0 + -$(Q)$(CLEAN) $($(_MODULE)_BIN).1.0 +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),exe) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo Uninstalling $($(_MODULE)_BIN) from $($(_MODULE)_INSTALL_BIN) + -$(Q)$(call $(_MODULE)_UNINSTALL_EXE) +endef + +define $(_MODULE)_INSTALL +install:: $($(_MODULE)_BIN) + @echo Installing $($(_MODULE)_BIN) to $($(_MODULE)_INSTALL_BIN) + -$(Q)$(call $(_MODULE)_INSTALL_EXE) + -$(Q)$(call $(_MODULE)_ATTRIB_EXE) +endef + +define $(_MODULE)_BUILD +build:: $($(_MODULE)_BIN) + @echo Building for $($(_MODULE)_BIN) +endef + +define $(_MODULE)_CLEAN_LNK +clean:: +endef + +endif + +define $(_MODULE)_COMPILE_TOOLS +$($(_MODULE)_ODIR)/%.o: $($(_MODULE)_SDIR)/%.c $($(_MODULE)_DEPHDR) $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Compiling C99 $$(notdir $$<) + $(Q)$(CC) -std=c99 $($(_MODULE)_CFLAGS) $$< -o $$@ $(LOGGING) + +$($(_MODULE)_ODIR)/%.o: $($(_MODULE)_SDIR)/%.cpp $($(_MODULE)_DEPHDR) $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Compiling C++ $$(notdir $$<) + $(Q)$(CP) $($(_MODULE)_CFLAGS) $$< -o $$@ $(LOGGING) + +$($(_MODULE)_ODIR)/%.o: $($(_MODULE)_SDIR)/%.S $($(_MODULE)_DEPHDR) $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Assembling $$(notdir $$<) + $(Q)$(AS) $($(_MODULE)_AFLAGS) $$< -o $$@ $(LOGGING) +endef diff --git a/concerto/definitions.mak b/concerto/definitions.mak new file mode 100644 index 0000000..f8babaf --- /dev/null +++ b/concerto/definitions.mak @@ -0,0 +1,21 @@ +# Copyright (C) 2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#$(info Including Definitions) +all-type-files = $(notdir $(wildcard $($(_MODULE)_SDIR)/$(1))) +all-java-files = $(call all-type-files,*.java) +all-c-files = $(call all-type-files,*.c) +all-cpp-files = $(call all-type-files,*.cpp) +all-h-files = $(call all-type-files,*.h) +all-S-files = $(call all-type-files,*.S) diff --git a/concerto/doxygen.mak b/concerto/doxygen.mak new file mode 100644 index 0000000..2975c19 --- /dev/null +++ b/concerto/doxygen.mak @@ -0,0 +1,50 @@ +# Copyright (C) 2012 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($($(_MODULE)_TYPE),doxygen) + +DOXYGEN := doxygen +DOXYFILE ?= Doxyfile + +$(_MODULE)_TARGET := $(TARGET) +$(_MODULE)_DOXYFILE := $($(_MODULE)_SDIR)/$(DOXYFILE) +$(_MODULE)_BIN := $($(_MODULE)_TDIR)/$($(_MODULE)_TARGET).tar.gz + +$(_MODULE)_HTML := docs/$(_MODULE)/html/index.html +$(_MODULE)_TEX := docs/$(_MODULE)/latex/refman.tex +$(_MODULE)_PDF := docs/$(_MODULE)/latex/refman.pdf + +define $(_MODULE)_DOCUMENTS + +$($(_MODULE)_HTML): $($(_MODULE)_DOXYFILE) + $(Q)rm -rf docs/$(_MODULE)/html + $(Q)$(DOXYGEN) $($(_MODULE)_DOXYFILE) + +$($(_MODULE)_TEX): $($(_MODULE)_DOXYFILE) + $(Q)rm -rf docs/$(_MODULE)/latex + $(Q)$(DOXYGEN) $($(_MODULE)_DOXYFILE) + +$($(_MODULE)_PDF): $($(_MODULE)_TEX) + $(Q)cd docs/$(_MODULE)/latex; make pdf + +$(_MODULE)_docs: $($(_MODULE)_HTML) $($(_MODULE)_PDF) + $(Q)tar zcvf $($(_MODULE)_BIN) docs/$(_MODULE)/html/ $($(_MODULE)_PDF) + +docs:: $(_MODULE)_docs + $(Q)echo Building docs for $(_MODULE) + +endef + +endif + diff --git a/concerto/dpkg.mak b/concerto/dpkg.mak new file mode 100644 index 0000000..1b7984e --- /dev/null +++ b/concerto/dpkg.mak @@ -0,0 +1,104 @@ +# Copyright (C) 2012 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +ifeq ($($(_MODULE)_TYPE),deb) +ifeq ($(TARGET_OS),LINUX) + +PKG_EXT := .deb + +VARS=$(shell "dpkg-architecture") +$(foreach var,$(VARS),$(if $(findstring DEB_BUILD_ARCH,$(var)),$(eval $(var)))) +$(info DEB_BUILD_ARCH=$(DEB_BUILD_ARCH)) + +#$(info OUT=$($(_MODULE)_ODIR)) + +$(_MODULE)_CFG ?= control +$(_MODULE)_PKG_NAME := $(subst _,-,$(TARGET)) +$(_MODULE)_PKG_FLDR := $($(_MODULE)_TDIR)/$($(_MODULE)_PKG_NAME) +$(_MODULE)_PKG := $($(_MODULE)_PKG_NAME)$(PKG_EXT) +$(_MODULE)_BIN := $($(_MODULE)_TDIR)/$($(_MODULE)_PKG) + +#$(info OUT=$($(_MODULE)_PKG_FLDR)) + +# Remember that the INSTALL variable tend to be based in / +$(_MODULE)_PKG_LIB := $($(_MODULE)_PKG_FLDR)$($(_MODULE)_INSTALL_LIB) +$(_MODULE)_PKG_INC := $($(_MODULE)_PKG_FLDR)$($(_MODULE)_INSTALL_INC)/$($(_MODULE)_INC_SUBPATH) +$(_MODULE)_PKG_BIN := $($(_MODULE)_PKG_FLDR)$($(_MODULE)_INSTALL_BIN) +$(_MODULE)_PKG_CFG := $($(_MODULE)_PKG_FLDR)/DEBIAN + +#$(info LIB=$($(_MODULE)_PKG_LIB)) + + +$(_MODULE)_PKG_DEPS:= $(foreach lib,$($(_MODULE)_SHARED_LIBS),$($(_MODULE)_PKG_LIB)/lib$(lib).so) \ + $(foreach lib,$($(_MODULE)_STATIC_LIBS),$($(_MODULE)_PKG_LIB)/lib$(lib).a) \ + $(foreach bin,$($(_MODULE)_BINS),$($(_MODULE)_PKG_BIN)/$(bin)) \ + $(foreach inc,$($(_MODULE)_INCS),$($(_MODULE)_PKG_INC)/$(notdir $(inc))) + +#$(info $(_MODULE)_PKG_DEPS=$($(_MODULE)_PKG_DEPS)) + +$(_MODULE)_OBJS := $($(_MODULE)_PKG_CFG)/$($(_MODULE)_CFG) $($(_MODULE)_PKG_DEPS) + +#$(info $(_MODULE)_OBJS=$($(_MODULE)_OBJS)) + +$(_MODULE)_CLEAN_BIN = rm -f $($(_MODULE)_BIN) +$(_MODULE)_CLEAN_OBJ = rm -f $($(_MODULE)_OBJS) + +define $(_MODULE)_PACKAGE + +$(foreach lib,$($(_MODULE)_STATIC_LIBS), +$($(_MODULE)_PKG_LIB)/lib$(lib).a: $($(_MODULE)_TDIR)/lib$(lib).a + $(Q)mkdir -p $$(dir $$@) + $(Q)cp $$^ $$@ +) + +$(foreach lib,$($(_MODULE)_SHARED_LIBS), +$($(_MODULE)_PKG_LIB)/lib$(lib).so: $($(_MODULE)_TDIR)/lib$(lib).so + $(Q)mkdir -p $$(dir $$@) + $(Q)cp $$^ $$@ +) + +$(foreach bin,$($(_MODULE)_BINS), +$($(_MODULE)_PKG_BIN)/$(bin): $($(_MODULE)_TDIR)/$(bin) + $(Q)mkdir -p $$(dir $$@) + $(Q)cp $$^ $$@ +) + +$(foreach inc,$($(_MODULE)_INCS), +$($(_MODULE)_PKG_INC)/$(notdir $(inc)): $(inc) + $(Q)mkdir -p $$(dir $$@) + $(Q)cp $$^ $$@ +) + +$($(_MODULE)_PKG_CFG)/$($(_MODULE)_CFG) : $($(_MODULE)_SDIR)/$($(_MODULE)_CFG) $($(_MODULE)_ODIR)/.gitignore + $(Q)mkdir -p $($(_MODULE)_PKG_LIB) + $(Q)mkdir -p $($(_MODULE)_PKG_INC) + $(Q)mkdir -p $($(_MODULE)_PKG_BIN) + $(Q)mkdir -p $($(_MODULE)_PKG_CFG) + $(Q)echo "Package: $($(_MODULE)_PKG_NAME)" > $$@ + $(Q)cat $($(_MODULE)_SDIR)/$($(_MODULE)_CFG) >> $$@ + $(Q)echo "Architecture: $(DEB_BUILD_ARCH)" >> $$@ + +build:: $($(_MODULE)_BIN) + +$($(_MODULE)_BIN): $($(_MODULE)_OBJS) + $(Q)dpkg --build $$(basename $$@) +endef + +else +# This prevents non-linux system from worrying about packages +$(_MODULE)_BIN := +endif +endif + diff --git a/concerto/finale.mak b/concerto/finale.mak new file mode 100644 index 0000000..99bf4e6 --- /dev/null +++ b/concerto/finale.mak @@ -0,0 +1,206 @@ +# Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Add the paths from the makefile +$(_MODULE)_IDIRS += $(SYSIDIRS) $(IDIRS) +$(_MODULE)_LDIRS += $(SYSLDIRS) $(LDIRS) + +# Add any additional libraries which are in this build system +$(_MODULE)_STATIC_LIBS += $(STATIC_LIBS) +$(_MODULE)_SHARED_LIBS += $(SHARED_LIBS) +$(_MODULE)_SYS_STATIC_LIBS += $(SYS_STATIC_LIBS) +$(_MODULE)_SYS_SHARED_LIBS += $(SYS_SHARED_LIBS) +$(_MODULE)_BINS += $(BINS) +$(_MODULE)_INCS += $(INCS) +ifdef INC_SUBPATH +$(_MODULE)_INC_SUBPATH := $(INC_SUBPATH) +else +$(_MODULE)_INC_SUBPATH := $(TARGET) +endif +$(_MODULE)_HEADERS := $(HEADERS) + +# Copy over the rest of the variables +$(_MODULE)_TYPE := $(TARGETTYPE) +$(_MODULE)_DEFS := $(SYSDEFS) $(DEFS) +$(_MODULE)_TEST := $(TESTCASE) + +# Set the Install Path +$(_MODULE)_INSTALL_PATH = $(INSTALL_PATH) + +# For debugging the build system +$(_MODULE)_SRCS := $(CSOURCES) $(CPPSOURCES) $(ASSEMBLY) $(JSOURCES) + +ifndef SKIPBUILD + +NEEDS_COMPILER:= +ifeq ($($(_MODULE)_TYPE),library) + NEEDS_COMPILER=1 +else ifeq ($($(_MODULE)_TYPE),dsmo) + NEEDS_COMPILER=1 +else ifeq ($($(_MODULE)_TYPE),exe) + NEEDS_COMPILER=1 +endif + +include $(HOST_ROOT)/$(BUILD_FOLDER)/opencl.mak + +ifeq ($(NEEDS_COMPILER),1) + +ifeq ($(HOST_COMPILER),GCC) + include $(HOST_ROOT)/$(BUILD_FOLDER)/gcc.mak +else ifeq ($(HOST_COMPILER),CLANG) + include $(HOST_ROOT)/$(BUILD_FOLDER)/clang.mak +else ifeq ($(HOST_COMPILER),CL) + include $(HOST_ROOT)/$(BUILD_FOLDER)/cl.mak +else ifeq ($(HOST_COMPILER),CGT6X) + include $(HOST_ROOT)/$(BUILD_FOLDER)/cgt6x.mak +else ifeq ($(HOST_COMPILER),QCC) + include $(HOST_ROOT)/$(BUILD_FOLDER)/qcc.mak +else ifeq ($(HOST_COMPILER),TMS470) + include $(HOST_ROOT)/$(BUILD_FOLDER)/tms470.mak +endif + +include $(HOST_ROOT)/$(BUILD_FOLDER)/java.mak + +endif + +include $(HOST_ROOT)/$(BUILD_FOLDER)/dpkg.mak +include $(HOST_ROOT)/$(BUILD_FOLDER)/doxygen.mak + +else + +$(info Build Skipped for $(_MODULE)) + +all %:: + +endif # ifndef SKIPBUILD + + +################################################### +# RULES +################################################### + +$(_MODULE): $($(_MODULE)_BIN) + +.PHONY: $(_MODULE)_test +$(_MODULE)_test: install + $($(_MODULE)_TEST) + +ifeq ($(strip $($(_MODULE)_TYPE)),library) + +define $(_MODULE)_BUILD_LIB +$($(_MODULE)_BIN): $($(_MODULE)_OBJS) $($(_MODULE)_STATIC_LIBS) + @echo Linking $$@ + -$(Q)$(call $(_MODULE)_LINK_LIB) $(LOGGING) +endef + +$(eval $(call $(_MODULE)_BUILD_LIB)) +$(eval $(call $(_MODULE)_INSTALL)) +$(eval $(call $(_MODULE)_BUILD)) +$(eval $(call $(_MODULE)_UNINSTALL)) + +else ifeq ($(strip $($(_MODULE)_TYPE)),exe) + +define $(_MODULE)_BUILD_EXE +$($(_MODULE)_BIN): $($(_MODULE)_OBJS) $($(_MODULE)_STATIC_LIBS) $($(_MODULE)_SHARED_LIBS) + @echo Linking $$@ + -$(Q)$(call $(_MODULE)_LINK_EXE) $(LOGGING) +endef + +$(eval $(call $(_MODULE)_BUILD_EXE)) +$(eval $(call $(_MODULE)_INSTALL)) +$(eval $(call $(_MODULE)_BUILD)) +$(eval $(call $(_MODULE)_UNINSTALL)) + +else ifeq ($(strip $($(_MODULE)_TYPE)),dsmo) + +define $(_MODULE)_BUILD_DSO +$($(_MODULE)_BIN): $($(_MODULE)_OBJS) $($(_MODULE)_STATIC_LIBS) $($(_MODULE)_SHARED_LIBS) + @echo Linking $$@ + $(Q)$(call $(_MODULE)_LINK_DSO) $(LOGGING) + -$(Q)$(call $(_MODULE)_LN_DSO) +endef + +$(eval $(call $(_MODULE)_BUILD_DSO)) +$(eval $(call $(_MODULE)_INSTALL)) +$(eval $(call $(_MODULE)_BUILD)) +$(eval $(call $(_MODULE)_UNINSTALL)) + +else ifeq ($(strip $($(_MODULE)_TYPE)),objects) + +$($(_MODULE)_BIN): $($(_MODULE)_OBJS) + +else ifeq ($(strip $($(_MODULE)_TYPE)),prebuilt) + +$(eval $(call $(_MODULE)_PREBUILT,$(PREBUILT))) + +else ifeq ($(strip $($(_MODULE)_TYPE)),jar) + +$(eval $(call $(_MODULE)_DEPEND_JAR)) + +else ifeq ($(strip $($(_MODULE)_TYPE)),deb) + +$(eval $(call $(_MODULE)_PACKAGE)) + +else ifeq ($(strip $($(_MODULE)_TYPE)),doxygen) + +$(info Creating doxygen rules!) +$(eval $(call $(_MODULE)_DOCUMENTS)) + +endif + +define $(_MODULE)_CLEAN +.PHONY: clean_bin clean +clean_target:: + @echo Cleaning $(_MODULE) target $($(_MODULE)_BIN) + -$(Q)$(call $(_MODULE)_CLEAN_BIN) + +clean:: clean_target +ifneq ($($(_MODULE)_OBJS),) + @echo Cleaning objects $($(_MODULE)_OBJS) + -$(Q)$(call $(_MODULE)_CLEAN_OBJ) +endif +endef + +$(eval $(call $(_MODULE)_CLEAN)) +$(eval $(call $(_MODULE)_CLEAN_LNK)) +$(foreach obj,$(CSOURCES), $(eval $(call $(_MODULE)_DEPEND_CC,$(basename $(obj))))) +$(foreach obj,$(CPPSOURCES),$(eval $(call $(_MODULE)_DEPEND_CP,$(basename $(obj))))) +$(foreach obj,$(ASSEMBLY), $(eval $(call $(_MODULE)_DEPEND_AS,$(basename $(obj))))) +$(foreach cls,$(JSOURCES), $(eval $(call $(_MODULE)_DEPEND_CLS,$(basename $(cls))))) + +$(eval $(call $(_MODULE)_COMPILE_TOOLS)) + +define $(_MODULE)_VARDEF +$(_MODULE)_vars:: + @echo ============================================= + @echo _MODULE=$(_MODULE) + @echo $(_MODULE)_BIN =$($(_MODULE)_BIN) + @echo $(_MODULE)_TYPE=$($(_MODULE)_TYPE) + @echo $(_MODULE)_OBJS=$($(_MODULE)_OBJS) + @echo $(_MODULE)_SDIR=$($(_MODULE)_SDIR) + @echo $(_MODULE)_ODIR=$($(_MODULE)_ODIR) + @echo $(_MODULE)_TDIR=$($(_MODULE)_TDIR) + @echo $(_MODULE)_SRCS=$($(_MODULE)_SRCS) + @echo $(_MODULE)_STATIC_LIBS=$($(_MODULE)_STATIC_LIBS) + @echo $(_MODULE)_SHARED_LIBS=$($(_MODULE)_SHARED_LIBS) + @echo $(_MODULE)_SYS_SHARED_LIBS=$($(_MODULE)_SYS_SHARED_LIBS) + @echo $(_MODULE)_CLASSES=$($(_MODULES)_CLASSES) + @echo ============================================= +endef + +$(eval $(call $(_MODULE)_VARDEF)) + +# Now clear out the module variable for repeat definitions +_MODULE := + diff --git a/concerto/gcc.mak b/concerto/gcc.mak new file mode 100644 index 0000000..764e720 --- /dev/null +++ b/concerto/gcc.mak @@ -0,0 +1,273 @@ +# Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_CPU),$(HOST_CPU)) + CROSS_COMPILE= +endif + +ifeq ($(TARGET_CPU),X86) + CROSS_COMPILE= +endif + +CC = $(CROSS_COMPILE)gcc +CP = $(CROSS_COMPILE)g++ +AS = $(CROSS_COMPILE)as +AR = $(CROSS_COMPILE)ar +LD = $(CROSS_COMPILE)gcc + +ifdef LOGFILE +LOGGING:=&>$(LOGFILE) +else +LOGGING:= +endif + +ifeq ($(TARGET_OS),DARWIN) +DSO_EXT := .dylib +else ifeq ($(TARGET_OS),CYGWIN) +DSO_EXT := .dll.a +else +DSO_EXT := .so +endif + +ifeq ($(strip $($(_MODULE)_TYPE)),library) + BIN_PRE=lib + BIN_EXT=.a +else ifeq ($(strip $($(_MODULE)_TYPE)),dsmo) + BIN_PRE=lib + BIN_EXT=$(DSO_EXT) +else + BIN_PRE= + BIN_EXT= +endif + +ifneq ($($(_MODULE)_TYPE),prebuilt) +$(_MODULE)_OUT := $(BIN_PRE)$(TARGET)$(BIN_EXT) +else +$(_MODULE)_OUT := $(notdir $(PREBUILT)) +endif +$(_MODULE)_BIN := $($(_MODULE)_TDIR)/$($(_MODULE)_OUT) +$(_MODULE)_OBJS := $(ASSEMBLY:%.S=$($(_MODULE)_ODIR)/%.o) $(CPPSOURCES:%.cpp=$($(_MODULE)_ODIR)/%.o) $(CSOURCES:%.c=$($(_MODULE)_ODIR)/%.o) +# Redefine the local static libs and shared libs with REAL paths and pre/post-fixes +$(_MODULE)_STATIC_LIBS := $(foreach lib,$(STATIC_LIBS),$($(_MODULE)_TDIR)/lib$(lib).a) +$(_MODULE)_SHARED_LIBS := $(foreach lib,$(SHARED_LIBS),$($(_MODULE)_TDIR)/lib$(lib)$(DSO_EXT)) + +#$(_MODULE)_COPT := $(CFLAGS) +#$(_MODULE)_LOPT := $(LDFLAGS) +ifneq ($(TARGET_OS),CYGWIN) +$(_MODULE)_COPT += -fPIC +endif +$(_MODULE)_COPT += -fms-extensions -Wno-write-strings + +ifeq ($(TARGET_BUILD),debug) +$(_MODULE)_COPT += -O0 -ggdb -ggdb3 -Q +$(_MODULE)_LOPT += -g +else ifeq ($(TARGET_BUILD),release) +$(_MODULE)_COPT += -O3 +endif + +ifeq ($(TARGET_CPU),ARM) +$(_MODULE)_COPT += -marm -mapcs -mno-sched-prolog -mno-thumb-interwork +ifeq ($(TARGET_OS),LINUX) +$(_MODULE)_COPT += -mabi=aapcs-linux +endif +endif + +ifeq ($(TARGET_ARCH),32) +ifneq ($(TARGET_CPU),ARM) +$(_MODULE)_COPT += -m32 -fno-stack-protector +endif +endif + +$(_MODULE)_DEPHDR := $(foreach hdr,$($(_MODULE)_HEADERS),$($(_MODULE)_SDIR)/$(hdr).h) +$(_MODULE)_MAP := -Map=$($(_MODULE)_BIN).map +$(_MODULE)_INCLUDES := $(foreach inc,$($(_MODULE)_IDIRS),-I$(inc)) +$(_MODULE)_DEFINES := $(foreach def,$($(_MODULE)_DEFS),-D$(def)) +$(_MODULE)_LIBRARIES:= $(foreach ldir,$($(_MODULE)_LDIRS),-L$(ldir)) $(foreach lib,$(STATIC_LIBS),-l$(lib)) $(foreach lib,$(SYS_STATIC_LIBS),-l$(lib)) $(foreach lib,$(SHARED_LIBS),-l$(lib)) $(foreach lib,$(SYS_SHARED_LIBS),-l$(lib)) +$(_MODULE)_AFLAGS := $($(_MODULE)_INCLUDES) +ifeq ($(HOST_OS),DARWIN) +$(_MODULE)_LDFLAGS := -arch $(TARGET_CPU) $(LDFLAGS) +endif +$(_MODULE)_LDFLAGS += $($(_MODULE)_LOPT) +$(_MODULE)_CPLDFLAGS := $(foreach ldf,$($(_MODULE)_LDFLAGS),-Wl,$(ldf)) $($(_MODULE)_COPT) +$(_MODULE)_CFLAGS := -c $($(_MODULE)_INCLUDES) $($(_MODULE)_DEFINES) $($(_MODULE)_COPT) + +ifdef DEBUG +$(_MODULE)_AFLAGS += --gdwarf-2 +endif + +################################################### +# COMMANDS +################################################### +ifneq ($(TARGET_OS),CYGWIN) +EXPORT_FLAG:=--export-dynamic +else +#EXPORT_FLAG:=--export-all-symbols +endif + +$(_MODULE)_CLEAN_OBJ := $(CLEAN) $($(_MODULE)_OBJS) +$(_MODULE)_CLEAN_BIN := $(CLEAN) $($(_MODULE)_BIN) +$(_MODULE)_ATTRIB_EXE := $(SET_EXEC) $($(_MODULE)_BIN) +$(_MODULE)_LN_DSO := $(LINK) $($(_MODULE)_BIN).1.0 $($(_MODULE)_BIN) +$(_MODULE)_LN_INST_DSO:= $(LINK) $($(_MODULE)_INSTALL_LIB)/$($(_MODULE)_OUT).1.0 $($(_MODULE)_INSTALL_LIB)/$($(_MODULE)_OUT) +$(_MODULE)_UNLN_DSO := $(CLEAN) $($(_MODULE)_BIN).1.0 +$(_MODULE)_UNLN_INST_DSO:= $(CLEAN) $($(_MODULE)_INSTALL_LIB)/$($(_MODULE)_OUT).1.0 +$(_MODULE)_INSTALL_DSO:= $(INSTALL) $($(_MODULE)_BIN).1.0 $($(_MODULE)_INSTALL_LIB) +$(_MODULE)_UNINSTALL_DSO:=$(CLEAN) $($(_MODULE)_INSTALL_LIB)/$($(_MODULE)_OUT) +$(_MODULE)_INSTALL_EXE:= $(INSTALL) $($(_MODULE)_BIN) $($(_MODULE)_INSTALL_BIN) +$(_MODULE)_UNINSTALL_EXE:=$(CLEAN) $($(_MODULE)_INSTALL_BIN)/$($(_MODULE)_OUT) +$(_MODULE)_LINK_LIB := $(AR) -rscu $($(_MODULE)_BIN) $($(_MODULE)_OBJS) #$($(_MODULE)_STATIC_LIBS) +ifeq ($(TARGET_OS),DARWIN) +$(_MODULE)_LINK_DSO := $(LD) -dynamiclib $($(_MODULE)_LDFLAGS) -all_load $($(_MODULE)_LIBRARIES) -lm -o $($(_MODULE)_BIN).1.0 $($(_MODULE)_OBJS) +$(_MODULE)_LINK_EXE := $(CP) -rdynamic $($(_MODULE)_CPLDFLAGS) $($(_MODULE)_OBJS) $($(_MODULE)_LIBRARIES) -o $($(_MODULE)_BIN) +else +ifeq ($(TARGET_PLATFORM), PANDA) +$(_MODULE)_LINK_DSO := $(LD) $($(_MODULE)_LDFLAGS) -shared -Wl,$(EXPORT_FLAG) -soname,$($(_MODULE)_BIN).1.0 -Wl,--whole-archive $($(_MODULE)_LIBRARIES) -lm -Wl,--no-whole-archive -o $($(_MODULE)_BIN).1.0 $($(_MODULE)_OBJS) $($(_MODULE)_MAP) +else +$(_MODULE)_LINK_DSO := $(LD) $($(_MODULE)_LDFLAGS) -shared -Wl,$(EXPORT_FLAG) -Wl,-soname,$($(_MODULE)_BIN).1.0 -Wl,--whole-archive $($(_MODULE)_LIBRARIES) -lm -Wl,--no-whole-archive -o $($(_MODULE)_BIN).1.0 $($(_MODULE)_OBJS) $($(_MODULE)_MAP) +endif +$(_MODULE)_LINK_EXE := $(CP) -rdynamic -Wl,--cref $($(_MODULE)_CPLDFLAGS) $($(_MODULE)_OBJS) $($(_MODULE)_LIBRARIES) -o $($(_MODULE)_BIN) -Wl,$($(_MODULE)_MAP) +endif + +################################################### +# MACROS FOR COMPILING +################################################### + +define $(_MODULE)_DEPEND_CC + +$($(_MODULE)_ODIR)/$(1).d: $($(_MODULE)_SDIR)/$(1).c $($(_MODULE)_SDIR)/$(SUBMAKEFILE) $($(_MODULE)_ODIR)/.gitignore + @echo Generating Dependency Info from $$(notdir $$<) + $(Q)$(CC) $($(_MODULE)_INCLUDES) $($(_MODULE)_DEFINES) $$< -MM -MF $($(_MODULE)_ODIR)/$(1).d -MT '$($(_MODULE)_ODIR)/$(1).o:' $(LOGGING) + +depend:: $($(_MODULE)_ODIR)/$(1).d + +-include $($(_MODULE)_ODIR)/$(1).d + +endef + +define $(_MODULE)_DEPEND_CP + +$($(_MODULE)_ODIR)/$(1).d: $($(_MODULE)_SDIR)/$(1).cpp $($(_MODULE)_SDIR)/$(SUBMAKEFILE) $($(_MODULE)_ODIR)/.gitignore + @echo Generating Dependency Info from $$(notdir $$<) + $(Q)$(CC) $($(_MODULE)_INCLUDES) $($(_MODULE)_DEFINES) $$< -MM -MF $($(_MODULE)_ODIR)/$(1).d -MT '$($(_MODULE)_ODIR)/$(1).o:' $(LOGGING) + +depend:: $($(_MODULE)_ODIR)/$(1).d + +-include $($(_MODULE)_ODIR)/$(1).d + +endef + +define $(_MODULE)_DEPEND_AS +# Do nothing... +endef + +ifeq ($(strip $($(_MODULE)_TYPE)),prebuilt) + +define $(_MODULE)_PREBUILT + +$($(_MODULE)_SDIR)/$(1): + +build:: $($(_MODULE)_SDIR)/$(1) + +install:: $($(_MODULE)_TDIR)/$(notdir $(1)) + +$($(_MODULE)_TDIR)/$(notdir $(1)): $($(_MODULE)_SDIR)/$(1) $($(_MODULE)_ODIR)/.gitignore + @echo Copying Prebuilt binary $($(_MODULE)_SDIR)/$(1) to $($(_MODULE)_TDIR)/$(notdir $(1)) + -$(Q)$(COPY) $($(_MODULE)_SDIR)/$(1) $($(_MODULE)_TDIR)/$(notdir $(1)) +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),library) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo No uninstall step for static libraries +endef + +define $(_MODULE)_INSTALL +install:: $($(_MODULE)_BIN) + @echo No install step for static libraries +endef + +define $(_MODULE)_BUILD +build:: $($(_MODULE)_BIN) +endef + +define $(_MODULE)_CLEAN_LNK +clean:: +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),dsmo) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo Uninstalling $($(_MODULE)_BIN) from $($(_MODULE)_INSTALL_LIB) + -$(Q)$(call $(_MODULE)_UNLN_INST_DSO) + -$(Q)$(call $(_MODULE)_UNINSTALL_DSO) +endef + +define $(_MODULE)_INSTALL +install:: $($(_MODULE)_BIN) + @echo Installing $($(_MODULE)_BIN) to $($(_MODULE)_INSTALL_LIB) + -$(Q)$(call $(_MODULE)_INSTALL_DSO) + -$(Q)$(call $(_MODULE)_LN_INST_DSO) +endef + +define $(_MODULE)_BUILD +build:: $($(_MODULE)_BIN) +endef + +define $(_MODULE)_CLEAN_LNK +clean:: + @echo Removing Link for Shared Object $($(_MODULE)_BIN).1.0 + -$(Q)$(CLEAN) $($(_MODULE)_BIN).1.0 +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),exe) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo Uninstalling $($(_MODULE)_BIN) from $($(_MODULE)_INSTALL_BIN) + -$(Q)$(call $(_MODULE)_UNINSTALL_EXE) +endef + +define $(_MODULE)_INSTALL +install:: $($(_MODULE)_BIN) + @echo Installing $($(_MODULE)_BIN) to $($(_MODULE)_INSTALL_BIN) + -$(Q)$(call $(_MODULE)_INSTALL_EXE) + -$(Q)$(call $(_MODULE)_ATTRIB_EXE) +endef + +define $(_MODULE)_BUILD +build:: $($(_MODULE)_BIN) + @echo Building for $($(_MODULE)_BIN) +endef + +define $(_MODULE)_CLEAN_LNK +clean:: +endef + +endif + +define $(_MODULE)_COMPILE_TOOLS +$($(_MODULE)_ODIR)/%.o: $($(_MODULE)_SDIR)/%.c $($(_MODULE)_DEPHDR) $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Compiling C99 $$(notdir $$<) + $(Q)$(CC) -std=c99 $($(_MODULE)_CFLAGS) $$< -o $$@ $(LOGGING) + +$($(_MODULE)_ODIR)/%.o: $($(_MODULE)_SDIR)/%.cpp $($(_MODULE)_DEPHDR) $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Compiling C++ $$(notdir $$<) + $(Q)$(CP) $($(_MODULE)_CFLAGS) $$< -o $$@ $(LOGGING) + +$($(_MODULE)_ODIR)/%.o: $($(_MODULE)_SDIR)/%.S $($(_MODULE)_DEPHDR) $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Assembling $$(notdir $$<) + $(Q)$(AS) $($(_MODULE)_AFLAGS) $$< -o $$@ $(LOGGING) +endef diff --git a/concerto/java.mak b/concerto/java.mak new file mode 100644 index 0000000..b757e3e --- /dev/null +++ b/concerto/java.mak @@ -0,0 +1,71 @@ +# Copyright (C) 2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($($(_MODULE)_TYPE),jar) + +JAR := jar +JC := javac + +############################################################################### + +$(_MODULE)_BIN := $($(_MODULE)_TDIR)/$(TARGET).jar +$(_MODULE)_CLASSES := $(patsubst %.java,%.class,$(JSOURCES)) +$(_MODULE)_OBJS := $(foreach cls,$($(_MODULE)_CLASSES),$($(_MODULE)_ODIR)/$(cls)) +ifdef CLASSPATH +$(_MODULE)_CLASSPATH := -classpath $(CLASSPATH) +CLASSPATH := +else +$(_MODULE)_CLASSPATH := +endif +$(_MODULE)_CLEAN_OBJ := $(CLEAN) $($(_MODULE)_OBJS) +$(_MODULE)_CLEAN_BIN := $(CLEAN) $($(_MODULE)_BIN) +JC_OPTS := -deprecation -verbose $($(_MODULE)_CLASSPATH) -sourcepath $($(_MODULE)_SDIR) -d $($(_MODULE)_ODIR) +ifdef DEBUG +JC_OPTS += -g +endif +ifdef MANIFEST +$(_MODULE)_MANIFEST := -m $(MANIFEST) +MANIFEST := +else +$(_MODULE)_MANIFEST := +endif +ifdef ENTRY +$(_MODULE)_ENTRY := $(ENTRY) +ENTRY := +else +$(_MODULE)_ENTRY := Main +endif +JAR_OPTS := cvfe $($(_MODULE)_BIN) $($(_MODULE)_MANIFEST) $($(_MODULE)_ENTRY) $(foreach cls,$($(_MODULE)_CLASSES),-C $($(_MODULE)_ODIR) $(cls)) + +############################################################################### + + +define $(_MODULE)_DEPEND_CLS +$($(_MODULE)_ODIR)/$(1).class: $($(_MODULE)_SDIR)/$(1).java $($(_MODULE)_SDIR)/$(SUBMAKEFILE) $($(_MODULE)_ODIR)/.gitignore + @echo Compiling Java $(1).java + $(Q)$(JC) $(JC_OPTS) $($(_MODULE)_SDIR)/$(1).java +endef + +define $(_MODULE)_DEPEND_JAR +uninstall:: + +install:: $($(_MODULE)_BIN) + +$($(_MODULE)_BIN): $($(_MODULE)_OBJS) + @echo Jar-ing Classes $($(_MODULE)_CLASSES) + $(Q)$(JAR) $(JAR_OPTS) +endef + +endif + diff --git a/concerto/machine.mak b/concerto/machine.mak new file mode 100644 index 0000000..378fbf3 --- /dev/null +++ b/concerto/machine.mak @@ -0,0 +1,59 @@ +# Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(HOST_OS),Windows_NT) + $(info Windows Processor Architecture $(PROCESSOR_ARCHITECTURE)) + $(info Windows Processor Identification $(word 1, $(PROCESSOR_IDENTIFIER))) + TYPE=$(word 1, $(PROCESSOR_IDENTIFIER)) + ifeq ($(TYPE),x86) + HOST_CPU=X86 + HOST_ARCH=32 + else ifeq ($(TYPE),Intel64) + HOST_CPU=X64 + HOST_ARCH=64 + else + $(error Unknown Processor Architecture on Windows!) + endif +else + HOST_CPU=$(shell uname -m) + ifeq ($(HOST_CPU),Power Macintosh) + HOST_CPU=PPC + HOST_ARCH=32 + else ifeq ($(HOST_CPU),x86_64) + HOST_CPU=x86_64 + HOST_ARCH=64 + else ifeq ($(HOST_CPU),i686) + HOST_CPU=X86 + HOST_ARCH=32 + else ifeq ($(HOST_CPU),i586) + HOST_CPU=X86 + HOST_ARCH=32 + else ifeq ($(HOST_CPU),i486) + HOST_CPU=X86 + HOST_ARCH=32 + else ifeq ($(HOST_CPU),i386) + HOST_CPU=X86 + HOST_ARCH=32 + else ifeq ($(HOST_CPU),ARM) + HOST_CPU=ARM + HOST_ARCH=32 + else ifeq ($(HOST_CPU),armv7l) + HOST_CPU=ARM + HOST_ARCH=32 + endif +endif + +$(info HOST_CPU=$(HOST_CPU)) +$(info HOST_ARCH=$(HOST_ARCH)) + diff --git a/concerto/opencl.mak b/concerto/opencl.mak new file mode 100644 index 0000000..911f12f --- /dev/null +++ b/concerto/opencl.mak @@ -0,0 +1,66 @@ +# Copyright (C) 2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +ifeq ($($(_MODULE)_TYPE),opencl_kernel) + +$(_MODULE)_TARGET := $(TARGET).h +$(_MODULE)_BIN := $($(_MODULE)_SDIR)/$($(_MODULE)_TARGET) +$(_MODULE)_OBJS := $($(_MODULE)_BIN) + +$(_MODULE)_CLEAN_BIN := -$(Q)$(CLEAN) $($(_MODULE)_BIN) +$(_MODULE)_CLEAN_OBJS := -$(Q)$(CLEAN) $($(_MODULE)_OBJS) + +ifeq ($(CL_BUILD_RUNTIME),) + +# OpenCL-Environment Compiler Support +ifeq ($(HOST_OS),Windows_NT) +CL:=$($(_MODULE)_TDIR)/clcompiler.exe +else ifeq ($(HOST_OS),CYGWIN) +CL:=$($(_MODULE)_TDIR)/clcompiler.exe +else +CL:=$($(_MODULE)_TDIR)/clcompiler +endif + +# OpenCL-Environment Defines +ifeq ($(HOST_OS),CYGWIN) +DEFS+=KDIR="\"$(KDIR)\"" CL_USER_DEVICE_COUNT=$(CL_USER_DEVICE_COUNT) CL_USER_DEVICE_TYPE="\"$(CL_USER_DEVICE_TYPE)\"" +else ifeq ($(HOST_OS),Windows_NT) +DEFS+=KDIR="$(call PATH_CONV,$(KDIR))\\" CL_USER_DEVICE_COUNT=$(CL_USER_DEVICE_COUNT) CL_USER_DEVICE_TYPE="$(CL_USER_DEVICE_TYPE)" +else +DEFS+=KDIR="$(KDIR)" CL_USER_DEVICE_COUNT=$(CL_USER_DEVICE_COUNT) CL_USER_DEVICE_TYPE="$(CL_USER_DEVICE_TYPE)" +endif + +ifeq ($(HOST_OS),CYGWIN) +# The Clang/LLVM is a Windows Path Compiler +$(_MODULE)_KFLAGS+=$(foreach inc,$($(_MODULE)_IDIRS),-I$(call P2W_CONV,$(inc))) $(foreach def,$($(_MODULE)_DEFS),-D$(def)) +else +$(_MODULE)_KFLAGS+=$(foreach inc,$($(_MODULE)_IDIRS),-I$(inc)) $(foreach def,$($(_MODULE)_DEFS),-D$(def)) +endif + +define $(_MODULE)_COMPILE_TOOLS +$($(_MODULE)_SDIR)/%.h: $($(_MODULE)_SDIR)/%.cl $(CL) + @echo [PURE] Compiling OpenCL Kernel $$(notdir $$<) + $(Q)$$(call PATH_CONV,$(CL)) -n -f $$(call PATH_CONV,$$<) -d $(CL_USER_DEVICE_COUNT) -t $(CL_USER_DEVICE_TYPE) -h $$(call PATH_CONV,$$@) -W "$($(_MODULE)_KFLAGS)" +endef + +else +define $(_MODULE)_COMPILE_TOOLS +$($(_MODULE)_SDIR)/%.h: + @echo Touching $$@ + $(Q)$$(call $(TOUCH),$$@) +endef +endif +endif + diff --git a/concerto/os.mak b/concerto/os.mak new file mode 100644 index 0000000..5370a98 --- /dev/null +++ b/concerto/os.mak @@ -0,0 +1,61 @@ +# Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(OS),Windows_NT) + ifeq ($(TERM),cygwin) + HOST_OS=CYGWIN + HOST_COMPILER=GCC + else ifeq ($(TERM),xterm) + HOST_OS=CYGWIN + HOST_COMPILER=GCC + P2W_CONV=$(patsubst \cygdrive\c\%,c:\%,$(subst /,\,$(1))) + W2P_CONV=$(subst \,/,$(patsubst C:\%,\cygdrive\c\% $(1))) + else + HOST_OS=Windows_NT + HOST_COMPILER=CL + CL_ROOT?=$(VCINSTALLDIR) + endif +else + OS=$(shell uname -s) + ifeq ($(OS),Linux) + HOST_OS=LINUX + ifeq ($(TARGET_CPU),C64T) + HOST_COMPILER=CGT6X + else ifeq ($(TARGET_CPU),C64P) + HOST_COMPILER=CGT6X + else + HOST_COMPILER?=GCC + endif + else ifeq ($(OS),Darwin) + HOST_OS=DARWIN + HOST_COMPILER=GCC + else ifeq ($(OS),CYGWIN_NT-5.1) + HOST_OS=CYGWIN + HOST_COMPILER=GCC + P2W_CONV=$(patsubst \cygdrive\c\%,c:\%,$(subst /,\,$(1))) + W2P_CONV=$(subst \,/,$(patsubst C:\%,\cygdrive\c\% $(1))) + else + HOST_OS=POSIX + HOST_COMPILER=GCC + endif +endif + +ifeq ($(HOST_OS),Windows_NT) + PATH_CONV=$(subst /,\,$(1)) +else + PATH_CONV=$(subst _,_,$(1)) +endif + +$(info HOST_OS=$(HOST_OS)) +$(info HOST_COMPILER=$(HOST_COMPILER)) diff --git a/concerto/prelude.mak b/concerto/prelude.mak new file mode 100644 index 0000000..a6ee227 --- /dev/null +++ b/concerto/prelude.mak @@ -0,0 +1,164 @@ +# Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +EMPTY:= +SPACE:=$(EMPTY) $(EMPTY) + +# Take the Makefile list and remove prelude and finale includes +# @note MAKEFILE_LIST is an automatic variable! +ifeq ($(HOST_OS),Windows_NT) +ALL_MAKEFILES := $(filter %\$(SUBMAKEFILE),$(MAKEFILE_LIST)) +else +ALL_MAKEFILES := $(filter %/$(SUBMAKEFILE),$(MAKEFILE_LIST)) +endif +#$(info ALL_MAKEFILES=$(ALL_MAKEFILES)) + +# Take the resulting list and remove the pathing and Makefile each entry and +# then you have the modules list. + +# get this makefile +THIS_MAKEFILE := $(lastword $(ALL_MAKEFILES)) +#$(info THIS_MAKEFILE=$(THIS_MAKEFILE)) +#$(info HOST_ROOT=$(HOST_ROOT)) + +# Remove the $(SUBMAKEFILE) to get the path +ifeq ($(HOST_OS),Windows_NT) +# This is a bear on Windows! +_MAKEPATH := $(dir $(THIS_MAKEFILE)) +#$(info PATH=$(_MAKEPATH)) +_FULLPATH := $(lastword $(subst :,$(SPACE),$(_MAKEPATH))) +#$(info FULL=$(_FULLPATH)) +_BASEPATH := $(lastword $(subst :,$(SPACE),$(subst /,\,$(HOST_ROOT)))) +#$(info BASE=$(_BASEPATH)) +_MODPATH := $(subst $(_BASEPATH),,$(_FULLPATH)) +#$(info PATH=$(_MODPATH)) +# now in the form of \...\...\ remove the outer \'s +_PARTS := $(strip $(subst \,$(SPACE),$(_MODPATH))) +#$(info PARTS=$(_PARTS)) +_MODPATH := $(subst $(SPACE),\,$(_PARTS)) +#$(info STRIPPED PATH=$(_MODPATH)) +else +_MODPATH := $(subst /$(SUBMAKEFILE),,$(THIS_MAKEFILE)) +endif + +ifdef BUILD_DEBUG +$(info _MODPATH=$(_MODPATH)) +endif + +ifeq ($(_MODPATH),) +$(error $(THIS_MAKEFILE) failed to get module path) +endif + +ifeq ($(HOST_OS),Windows_NT) +_MODDIR := $(lastword $(subst \,$(SPACE),$(_MODPATH))) +else +_MODDIR := $(lastword $(subst /,$(SPACE),$(_MODPATH))) +endif + +# If we're calling this from our directory we need to figure out the path +ifeq ($(_MODDIR),./) +ifeq ($(HOST_OS),Windows_NT) +_MODDIR := $(lastword $(subst /, ,$(abspath .))) +else +_MODDIR := $(lastword $(subst /, ,$(abspath .))) +endif +endif + +#$(info _MODDIR=$(_MODDIR)) + +# if the makefile didn't define the module name, use the directory name +ifeq ($(_MODULE),) +_MODULE=$(_MODDIR) +endif + +# if there's no module name, this isn't going to work! +ifeq ($(_MODULE),) +$(error Failed to create module name!) +endif + +# Print some info to show that we're processing the makefiles +ifdef BUILD_DEBUG +$(info Adding Module $(_MODULE) to MODULES) +endif + +# Add the current module to the modules list +MODULES+=$(_MODULE) + +# Define the Path to the Source Files (always use the directory) and Header Files +$(_MODULE)_SDIR := $(HOST_ROOT)/$(_MODPATH) +$(_MODULE)_IDIRS:= $($(_MODULE)_SDIR) + +# Route the output for each module into it's own folder +$(_MODULE)_ODIR := $(HOST_ROOT)/out/$(TARGET_OS)/$(TARGET_CPU)/module_$(_MODULE) +$(_MODULE)_TDIR := $(HOST_ROOT)/out/$(TARGET_OS)/$(TARGET_CPU) + +# Set the initial linking directories to the target directory +$(_MODULE)_LDIRS := $($(_MODULE)_TDIR) + +# Set the install directory if it's not set already +ifndef INSTALL_LIB +$(_MODULE)_INSTALL_LIB := $($(_MODULE)_TDIR) +else +$(_MODULE)_INSTALL_LIB := $(INSTALL_LIB) +endif +ifndef INSTALL_BIN +$(_MODULE)_INSTALL_BIN := $($(_MODULE)_TDIR) +else +$(_MODULE)_INSTALL_BIN := $(INSTALL_BIN) +endif +ifndef INSTALL_INC +$(_MODULE)_INSTALL_INC := $($(_MODULE)_TDIR)/include +else +$(_MODULE)_INSTALL_INC := $(INSTALL_INC) +endif + +# Define a ".gitignore" file which will help in making sure the module's output folder always exists. +$($(_MODULE)_ODIR)/.gitignore: +ifeq ($(HOST_OS),Windows_NT) + -@echo Making $(call PATH_CONV,$(dir $@)) + -$(shell mkdir $(call PATH_CONV,$(dir $@))) + -$(TOUCH) $@ +else + -$(Q)mkdir -p $(patsubst %/.gitignore,%,$@) + -$(Q)$(TOUCH) $@ +endif + +dir:: $($(_MODULE)_ODIR)/.gitignore + +# Clean out common vars +ENTRY := +DEFS := +CFLAGS := +LDFLAGS := +STATIC_LIBS := +SHARED_LIBS := +SYS_STATIC_LIBS := +SYS_SHARED_LIBS := +IDIRS := +LDIRS := +CSOURCES := +CPPSOURCES := +ASSEMBLY := +TARGET := +TARGETTYPE := +BINS := +INCS := +INC_SUBPATH := +HEADERS := + +# Define a local path for this module's folder that we're processing... +THIS := $($(_MODULE)_SDIR) + +# Pull in the definitions which will be redefined for this makefile +include $(HOST_ROOT)/$(BUILD_FOLDER)/definitions.mak diff --git a/concerto/qcc.mak b/concerto/qcc.mak new file mode 100644 index 0000000..b351704 --- /dev/null +++ b/concerto/qcc.mak @@ -0,0 +1,240 @@ +# Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_CPU),$(HOST_CPU)) + CROSS_COMPILE= +endif + +CC = $(CROSS_COMPILE)gcc +CP = $(CROSS_COMPILE)g++ +AS = $(CROSS_COMPILE)as +AR = $(CROSS_COMPILE)ar +LD = $(CROSS_COMPILE)ld + +ifdef LOGFILE +LOGGING:=&>$(LOGFILE) +else +LOGGING:= +endif + +ifeq ($(strip $($(_MODULE)_TYPE)),library) + BIN_PRE=lib + BIN_EXT=.a +else ifeq ($(strip $($(_MODULE)_TYPE)),dsmo) + BIN_PRE=lib + BIN_EXT=.so +else + BIN_PRE= + BIN_EXT= +endif + +ifneq ($($(_MODULE)_TYPE),prebuilt) +$(_MODULE)_BIN := $($(_MODULE)_TDIR)/$(BIN_PRE)$(TARGET)$(BIN_EXT) +else +$(_MODULE)_BIN := $($(_MODULE)_TDIR)/$(notdir $(PREBUILT)) +endif +$(_MODULE)_OBJS := $(ASSEMBLY:%.S=$($(_MODULE)_ODIR)/%.o) $(CPPSOURCES:%.cpp=$($(_MODULE)_ODIR)/%.o) $(CSOURCES:%.c=$($(_MODULE)_ODIR)/%.o) +# Redefine the local static libs and shared libs with REAL paths and pre/post-fixes +$(_MODULE)_STATIC_LIBS := $(foreach lib,$(STATIC_LIBS),$($(_MODULE)_TDIR)/lib$(lib).a) +$(_MODULE)_SHARED_LIBS := $(foreach lib,$(SHARED_LIBS),$($(_MODULE)_TDIR)/lib$(lib).so) + +$(_MODULE)_COPT := +$(_MODULE)_LOPT := +$(_MODULE)_COPT := -fms-extensions -fPIC -Wno-write-strings +ifeq ($(TARGET_BUILD),debug) +$(_MODULE)_COPT += -O0 -ggdb -ggdb3 -Q +$(_MODULE)_LOPT += -g +else ifeq ($(TARGET_BUILD),release) +$(_MODULE)_COPT += -O3 +endif + +ifeq ($(TARGET_CPU),ARM) +$(_MODULE)_COPT += -mapcs -mno-sched-prolog -mno-thumb-interwork +endif + +ifeq ($(TARGET_ARCH),32) +ifneq ($(TARGET_CPU),ARM) +$(_MODULE)_COPT += -m32 -fno-stack-protector +endif +endif + +$(_MODULE)_MAP := -Map=$($(_MODULE)_BIN).map +$(_MODULE)_INCLUDES := $(foreach inc,$($(_MODULE)_IDIRS),-I$(inc)) +$(_MODULE)_DEFINES := $(foreach def,$($(_MODULE)_DEFS),-D$(def)) +$(_MODULE)_LIBRARIES:= $(foreach ldir,$($(_MODULE)_LDIRS),-L$(ldir)) $(foreach lib,$(STATIC_LIBS),-l$(lib)) $(foreach lib,$(SYS_STATIC_LIBS),-l$(lib)) $(foreach lib,$(SHARED_LIBS),-l$(lib)) $(foreach lib,$(SYS_SHARED_LIBS),-l$(lib)) +$(_MODULE)_AFLAGS := $($(_MODULE)_INCLUDES) -meabi=5 +$(_MODULE)_LDFLAGS := $($(_MODULE)_LOPT) +$(_MODULE)_CPLDFLAGS := $(foreach ldf,$($(_MODULE)_LDFLAGS),-Wl,$(ldf)) +$(_MODULE)_CFLAGS := -c $($(_MODULE)_INCLUDES) $($(_MODULE)_DEFINES) $($(_MODULE)_COPT) + +ifdef DEBUG +$(_MODULE)_AFLAGS += --gdwarf-2 +endif + +################################################### +# COMMANDS +################################################### + +LINK := ln -s +CLEAN := rm -f +CLEANDIR := rm -rf +COPY := cp -f + +EXPORT_FLAG:=--export-dynamic + +$(_MODULE)_CLEAN_OBJ := $(CLEAN) $($(_MODULE)_OBJS) +$(_MODULE)_CLEAN_BIN := $(CLEAN) $($(_MODULE)_BIN) +$(_MODULE)_ATTRIB_EXE := chmod a+x $($(_MODULE)_BIN) +$(_MODULE)_LN_DSO := $(LINK) $($(_MODULE)_BIN).1.0 $($(_MODULE)_BIN) +$(_MODULE)_UNLN_DSO := $(CLEAN) $($(_MODULE)_INSTALL_LIB)/$($(_MODULE)_BIN) +$(_MODULE)_INSTALL_DSO:= install -C -m 755 $($(_MODULE)_BIN) $($(_MODULE)_INSTALL_LIB) +$(_MODULE)_UNINSTALL_DSO:=$(CLEAN) $($(_MODULE)_INSTALL_LIB)/$($(_MODULE)_BIN) +$(_MODULE)_INSTALL_EXE:= install -C -m 755 $($(_MODULE)_BIN) $($(_MODULE)_INSTALL_BIN) +$(_MODULE)_UNINSTALL_EXE:=$(CLEAN) $($(_MODULE)_INSTALL_BIN)/$($(_MODULE)_BIN) +$(_MODULE)_LINK_LIB := $(AR) -rscu $($(_MODULE)_BIN) $($(_MODULE)_OBJS) #$($(_MODULE)_STATIC_LIBS) +$(_MODULE)_LINK_EXE := $(CP) -Wl,--cref $($(_MODULE)_CPLDFLAGS) $($(_MODULE)_OBJS) $($(_MODULE)_LIBRARIES) -o $($(_MODULE)_BIN) -Wl,$($(_MODULE)_MAP) +$(_MODULE)_LINK_DSO := $(LD) $($(_MODULE)_LDFLAGS) -shared $(EXPORT_FLAG) -soname,$($(_MODULE)_BIN).1 --whole-archive $($(_MODULE)_LIBRARIES) --no-whole-archive -o $($(_MODULE)_BIN).1.0 $($(_MODULE)_OBJS) $($(_MODULE)_MAP) + +################################################### +# MACROS FOR COMPILING +################################################### + +define $(_MODULE)_DEPEND_CC + +$($(_MODULE)_ODIR)/$(1).d: $($(_MODULE)_SDIR)/$(1).c $($(_MODULE)_SDIR)/$(SUBMAKEFILE) $($(_MODULE)_ODIR)/.gitignore + @echo Generating Dependency Info from $$(notdir $$<) + $(Q)$(CC) $($(_MODULE)_INCLUDES) $($(_MODULE)_DEFINES) $$< -MM -MF $($(_MODULE)_ODIR)/$(1).d -MT '$($(_MODULE)_ODIR)/$(1).o:' $(LOGGING) + +depend:: $($(_MODULE)_ODIR)/$(1).d + +-include $($(_MODULE)_ODIR)/$(1).d + +endef + +define $(_MODULE)_DEPEND_CP + +$($(_MODULE)_ODIR)/$(1).d: $($(_MODULE)_SDIR)/$(1).cpp $($(_MODULE)_SDIR)/$(SUBMAKEFILE) $($(_MODULE)_ODIR)/.gitignore + @echo Generating Dependency Info from $$(notdir $$<) + $(Q)$(CC) $($(_MODULE)_INCLUDES) $($(_MODULE)_DEFINES) $$< -MM -MF $($(_MODULE)_ODIR)/$(1).d -MT '$($(_MODULE)_ODIR)/$(1).o:' $(LOGGING) + +depend:: $($(_MODULE)_ODIR)/$(1).d + +-include $($(_MODULE)_ODIR)/$(1).d + +endef + +define $(_MODULE)_DEPEND_AS +# Do nothing... +endef + +ifeq ($(strip $($(_MODULE)_TYPE)),prebuilt) + +define $(_MODULE)_PREBUILT + +$($(_MODULE)_SDIR)/$(1): + +build:: $($(_MODULE)_SDIR)/$(1) + +install:: $($(_MODULE)_TDIR)/$(notdir $(1)) + +$($(_MODULE)_TDIR)/$(notdir $(1)): $($(_MODULE)_SDIR)/$(1) $($(_MODULE)_ODIR)/.gitignore + @echo Copying Prebuilt binary $($(_MODULE)_SDIR)/$(1) to $($(_MODULE)_TDIR)/$(notdir $(1)) + -$(Q)$(COPY) $($(_MODULE)_SDIR)/$(1) $($(_MODULE)_TDIR)/$(notdir $(1)) +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),library) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo No uninstall step for static libraries +endef + +define $(_MODULE)_INSTALL +install:: $($(_MODULE)_BIN) + @echo No install step for static libraries +endef + +define $(_MODULE)_BUILD +build:: $($(_MODULE)_BIN) +endef + +define $(_MODULE)_CLEAN_LNK +clean:: +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),dsmo) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo Uninstalling $($(_MODULE)_BIN) from $($(_MODULE)_INSTALL_LIB) + -$(Q)$(call $(_MODULE)_UNLN_DSO) + -$(Q)$(call $(_MODULE)_UNINSTALL_DSO) +endef + +define $(_MODULE)_INSTALL +install:: $($(_MODULE)_BIN) + @echo Installing $($(_MODULE)_BIN) to $($(_MODULE)_INSTALL_LIB) + -$(Q)$(call $(_MODULE)_INSTALL_DSO) + -$(Q)$(call $(_MODULE)_LN_DSO) +endef + +define $(_MODULE)_BUILD +build:: $($(_MODULE)_BIN) +endef + +define $(_MODULE)_CLEAN_LNK +clean:: + @echo Removing Link for Shared Object $($(_MODULE)_BIN).1.0 + -$(Q)$(CLEAN) $($(_MODULE)_BIN).1.0 +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),exe) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo Uninstalling $($(_MODULE)_BIN) from $($(_MODULE)_INSTALL_BIN) + -$(Q)$(call $(_MODULE)_UNINSTALL_EXE) +endef + +define $(_MODULE)_INSTALL +install:: $($(_MODULE)_BIN) + @echo Installing $($(_MODULE)_BIN) to $($(_MODULE)_INSTALL_BIN) + -$(Q)$(call $(_MODULE)_INSTALL_EXE) + -$(Q)$(call $(_MODULE)_ATTRIB_EXE) +endef + +define $(_MODULE)_BUILD +build:: $($(_MODULE)_BIN) + @echo Building for $($(_MODULE)_BIN) +endef + +define $(_MODULE)_CLEAN_LNK +clean:: +endef + +endif + +define $(_MODULE)_COMPILE_TOOLS +$($(_MODULE)_ODIR)/%.o: $($(_MODULE)_SDIR)/%.c $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Compiling C99 $$(notdir $$<) + $(Q)$(CC) -std=c99 $($(_MODULE)_CFLAGS) $$< -o $$@ $(LOGGING) + +$($(_MODULE)_ODIR)/%.o: $($(_MODULE)_SDIR)/%.cpp $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Compiling C++ $$(notdir $$<) + $(Q)$(CP) $($(_MODULE)_CFLAGS) $$< -o $$@ $(LOGGING) + +$($(_MODULE)_ODIR)/%.o: $($(_MODULE)_SDIR)/%.S $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Assembling $$(notdir $$<) + $(Q)$(AS) $($(_MODULE)_AFLAGS) $$< -o $$@ $(LOGGING) +endef diff --git a/concerto/rules.mak b/concerto/rules.mak new file mode 100644 index 0000000..99c3d49 --- /dev/null +++ b/concerto/rules.mak @@ -0,0 +1,110 @@ +# Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Define all but don't do anything with it yet. +.PHONY: all +all:: + +# Define our pathing +HOST_ROOT?=$(abspath .) +$(info HOST_ROOT=$(HOST_ROOT)) + +BUILD_FOLDER?=concerto + +include $(HOST_ROOT)/$(BUILD_FOLDER)/os.mak +include $(HOST_ROOT)/$(BUILD_FOLDER)/machine.mak +include $(HOST_ROOT)/$(BUILD_FOLDER)/target.mak +include $(HOST_ROOT)/$(BUILD_FOLDER)/shell.mak + +# Define the prelude and finale files so that SUBMAKEFILEs know what they are +# And if the users go and make -f concerto.mak then it will not work right. +PRELUDE := $(HOST_ROOT)/$(BUILD_FOLDER)/prelude.mak +FINALE := $(HOST_ROOT)/$(BUILD_FOLDER)/finale.mak +SUBMAKEFILE := concerto.mak + +# Remove the implicit rules for compiling. +.SUFFIXES: + +# Allows the commands to be printed out when invoked +ifeq ($(BUILD_DEBUG),1) +Q= +else +Q=@ +endif + +# Initialize Build Variables +SKIPBUILD:= + +ifeq ($(NO_OPTIMIZE),1) +TARGET_BUILD:=debug +else +TARGET_BUILD:=release +endif +$(info TARGET_BUILD=$(TARGET_BUILD)) + +# If no directories were specified, then assume "source" +DIRECTORIES?=source + +# Find all the Makfiles in the subfolders, these will be pulled in to make +ifeq ($(HOST_OS),Windows_NT) +TARGET_MAKEFILES:=$(foreach d,$(DIRECTORIES),$(shell cd $(d) && cmd.exe /C dir /b /s $(SUBMAKEFILE))) +else +TARGET_MAKEFILES:=$(foreach d,$(DIRECTORIES),$(shell find $(d)/ -name $(SUBMAKEFILE))) +endif +ifdef BUILD_DEBUG +$(info TARGET_MAKEFILES=$(TARGET_MAKEFILES)) +endif + +# Create the MODULES list by parsing the makefiles. +MODULES:= +include $(TARGET_MAKEFILES) +$(info MODULES=$(MODULES)) + +ifndef NO_TARGETS +.PHONY: all dir depend build install uninstall clean clean_target targets scrub vars test + +depend:: + +all:: build + +build:: dir depend + +install:: build + +uninstall:: + +targets:: + @echo TARGETS=$(MODULES) + +scrub:: +ifeq ($(HOST_OS),Windows_NT) + @echo [ROOT] Deleting $(HOST_ROOT)\out\$(TARGET_OS)\$(TARGET_CPU) + -$(Q)$(CLEANDIR) $(call PATH_CONV,$(HOST_ROOT)/out/$(TARGET_OS)/$(TARGET_CPU)) +else + @echo [ROOT] Deleting $(HOST_ROOT)/out/$(TARGET_OS)/$(TARGET_CPU) + -$(Q)$(CLEANDIR) $(HOST_ROOT)/out/$(TARGET_OS)/$(TARGET_CPU) +endif + +vars:: $(foreach mod,$(MODULES),$(mod)_vars) + @echo HOST_ROOT=$(HOST_ROOT) + @echo HOST_OS=$(HOST_OS) + @echo HOST_COMPILER=$(HOST_COMPILER) + @echo TARGET_CPU=$(TARGET_CPU) + @echo MAKEFILE_LIST=$(MAKEFILE_LIST) + @echo TARGET_MAKEFILES=$(TARGET_MAKEFILES) + +test:: $(foreach mod,$(MODULES),$(mod)_test) + @echo Executing Unit tests +endif + diff --git a/concerto/shell.mak b/concerto/shell.mak new file mode 100644 index 0000000..a29b668 --- /dev/null +++ b/concerto/shell.mak @@ -0,0 +1,36 @@ +# Copyright (C) 2012 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(HOST_OS),Windows_NT) # cmd.exe +CLEAN := cmd.exe /C del /Q +CLEANDIR := cmd.exe /C del /Q /S +COPY := cmd.exe /C copy /Y /Z /V +PRINT := cmd.exe /C echo +SET_RW := cmd.exe /C attrib -R +SET_EXEC := cmd.exe /C echo +LINK := cmd.exe /C junction +TOUCH := cmd.exe /C type NUL > +INSTALL := cmd.exe /C copy /Y /Z /V +else # Bash variants +CLEAN := rm -fv +CLEANDIR := rm -rfv +COPY := cp -f +PRINT := echo +SET_RW := chmod a+rw +SET_EXEC := chmod a+x +LINK := ln -s -f +TOUCH := touch +INSTALL := install -C -m 755 +endif + diff --git a/concerto/target.mak b/concerto/target.mak new file mode 100644 index 0000000..1a9d98e --- /dev/null +++ b/concerto/target.mak @@ -0,0 +1,261 @@ + # Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +TARGET_PLATFORM ?= PC + +ifdef QCONF_OVERRIDE + include $(QCONF_OVERRIDE) +endif +DVP_ROOT ?= $(HOST_ROOT) +SOSAL_ROOT ?= $(HOST_ROOT) + +DVP_INC += $(DVP_ROOT)/include +DVP_INT_INC:=$(DVP_ROOT)/source/dvp/dvp_kgraph/include \ + $(DVP_ROOT)/source/dvp/dvp_display/include +SOSAL_INC := $(SOSAL_ROOT)/include + +SYSDEFS := +SYSIDIRS := $(DVP_INC) $(SOSAL_INC) $(DVP_INT_INC) +SYSLDIRS := + +IPC_INCS := +IPC_LIBS := +MEM_INCS := +MEM_LIBS := +OMX_INCS := +OMX_LIBS := + +ifeq ($(TARGET_PLATFORM),PC) + TARGET_OS=$(HOST_OS) + TARGET_CPU?=$(HOST_CPU) + ifeq ($(TARGET_OS),LINUX) + INSTALL_LIB := /usr/lib + INSTALL_BIN := /usr/bin + INSTALL_INC := /usr/include + TARGET_NUM_CORES:=$(shell cat /proc/cpuinfo | grep processor | wc -l) + SYSIDIRS += /usr/include + SYSLDIRS += /usr/lib + SYSDEFS += SCREEN_DIM_X=1024 SCREEN_DIM_Y=768 \ + _XOPEN_SOURCE=700 _BSD_SOURCE=1 _GNU_SOURCE=1 DVP_USE_FS \ + DVP_USE_SHARED_T SOSAL_USE_SHARED_T + UVC_INC := /usr/include + GTK_PATH := $(realpath /usr/include/gtk-2.0) + ifneq ($(GTK_PATH),) + GTK_INC := $(subst -I,,$(shell pkg-config --cflags-only-I gtk+-2.0)) + GTK_LDIRS := $(shell pkg-config --variable=libdir gtk+-2.0) + GTK_LIBS := $(subst -l,,$(shell pkg-config --libs-only-l gtk+-2.0)) + SYSDEFS+=DVP_USE_GTK GTK_SUPPORT + endif + else ifeq ($(TARGET_OS),DARWIN) + INSTALL_LIB := /opt/local/lib + INSTALL_BIN := /opt/local/bin + INSTALL_INC := /opt/local/include + TARGET_NUM_CORES ?= 2 + SYSDEFS += SCREEN_DIM_X=1024 SCREEN_DIM_Y=768 + SYSDEFS += _XOPEN_SOURCE=700 _BSD_SOURCE=1 _GNU_SOURCE=1 + SYSDEFS += DVP_STATIC_MANAGERS DVP_USE_FS + else ifeq ($(TARGET_OS),CYGWIN) + INSTALL_LIB := /usr/lib + INSTALL_BIN := /usr/bin + INSTALL_INC := /usr/include + TARGET_NUM_CORES ?= 2 + SYSDEFS += SCREEN_DIM_X=1024 SCREEN_DIM_Y=768 + SYSDEFS += DVP_USE_FS DVP_USE_SHARED_T SOSAL_USE_SHARED_T \ + _XOPEN_SOURCE=700 _BSD_SOURCE=1 _GNU_SOURCE=1 WINVER=0x501 + else ifeq ($(TARGET_OS),Windows_NT) + INSTALL_LIB := "${windir}\\system32" + INSTALL_BIN := "${windir}\\system32" + INSTALL_INC := + TARGET_NUM_CORES := $(NUMBER_OF_PROCESSORS) + SYSIDIRS+=$(DVP_ROOT)/include/win32 + SYSDEFS+=DVP_USE_FS DVP_STATIC_MANAGERS WIN32_LEAN_AND_MEAN WIN32 \ + _WIN32 _CRT_SECURE_NO_DEPRECATE WINVER=0x0501 \ + _WIN32_WINNT=0x0501 SOSAL_USE_SHARED_T DVP_USE_SHARED_T + SYSDEFS+=SCREEN_DIM_X=1024 SCREEN_DIM_Y=768 + endif +else + ifeq ($(TARGET_PLATFORM),SDP) + SYSDEFS+=USE_PRIMARY_SENSOR + TARGET_NUM_CORES := 2 + TARGET_OS := LINUX + TARGET_CPU := ARM + else ifeq ($(TARGET_PLATFORM),BLAZE) + SYSDEFS+=SCREEN_DIM_X=864 SCREEN_DIM_Y=480 + TARGET_NUM_CORES := 2 + TARGET_OS := LINUX + TARGET_CPU := ARM + else ifeq ($(TARGET_PLATFORM),PANDA) + INSTALL_LIB := /usr/lib + INSTALL_BIN := /usr/bin + INSTALL_INC := /usr/include + SYSDEFS+=SCREEN_DIM_X=1920 SCREEN_DIM_Y=1080 # Panda can display 1080p + SYSDEFS+=USE_PRIMARY_SENSOR + SYSDEFS+=_XOPEN_SOURCE=700 _BSD_SOURCE=1 _GNU_SOURCE=1 + SYSDEFS+=TARGET_DVP_OMAP4 + SYSDEFS+=DVP_USE_FS DVP_USE_IPC DVP_USE_OMAPRPC DVP_USE_SHARED_T \ + SOSAL_USE_SHARED_T SOSAL_USE_BO DVP_USE_BO + UVC_INC := /usr/include + TARGET_NUM_CORES := 2 + TARGET_OS := LINUX + TARGET_CPU := ARM + DUCATI_VERSION := DUCATI_2_0 + ifndef KERNEL_ROOT + $(error "You must defined the path to the kernel in KERNEL_ROOT!") + else + KERNEL_INC := $(KERNEL_ROOT)/include + SYSIDIRS += $(KERNEL_INC) + endif + ifneq ($(HOST_CPU),$(TARGET_CPU)) + ifndef CROSS_COMPILE + $(error "CROSS_COMPILE not set! You won't be able to compile this!") + endif + endif + IPC_INCS := $(DVP_ROOT)/include/linux + IPC_LIBS := omaprpc + ifneq ($(findstring SOSAL_USE_BO,$(SYSDEFS)),) + # remove the -I and -l switches which assume GCC + MEM_INCS += $(subst -I,,$(shell pkg-config --cflags libdrm libdrm_omap)) + MEM_LIBS += $(subst -l,,$(shell pkg-config --libs libdrm libdrm_omap)) + endif + ifneq ($(findstring SOSAL_USE_ION,$(SYSDEFS)),) + MEM_INCS += $(DVP_ROOT)/include/ion + MEM_LIBS += ion + endif + ifdef OMX_ROOT + OMX_INCS := $(OMX_ROOT)/include + SYSLDIRS += $(OMX_ROOT)/omx_core $(OMX_ROOT)/mm_osal + OMX_LIBS := omx_core mm_osal + endif + else ifeq ($(TARGET_PLATFORM),PLAYBOOK) + HOST_COMPILER := QCC + TARGET_OS := __QNX__ + TARGET_CPU := ARM + TARGET_NUM_CORES := 2 + DUCATI_VERSION=DUCATI_1_2 + CROSS_COMPILE := ntoarmv7- + SYSDEFS += DVP_USE_FS TARGET_OMAP4 DVP_STATIC_MANAGERS \ + SCREEN_DIM_X=1080 SCREEN_DIM_Y=720 __QNXNTO__ \ + _POSIX_C_SOURCE=200112L _GNU_SOURCE=1 \ + SOSAL_USE_SHARED_T DVP_USE_SHARED_T + ifeq ($(USE_INSTALL_ROOT),) + INSTALL_PATH := $(QNX_TARGET)/armle-v7 + SYSIDIRS += $(INSTALL_PATH)/usr/include + SYSLDIRS += $(INSTALL_PATH)/lib $(INSTALL_PATH)/usr/lib + else + INSTALL_PATH := $(INSTALL_ROOT_nto)/armle-v7 + SYSIDIRS += $(INSTALL_ROOT_nto)/usr/include $(QNX_TARGET)/usr/include + SYSLDIRS += $(INSTALL_PATH)/lib $(INSTALL_PATH)/usr/lib $(QNX_TARGET)/armle-v7/lib $(QNX_TARGET)/armle-v7/usr/lib + endif + ifdef IPC_ROOT + IPC_INCS := $(IPC_ROOT)/ + IPC_INCS += $(IPC_ROOT)/inc/ + IPC_INCS += $(IPC_ROOT)/inc/usr/ + IPC_INCS += $(IPC_ROOT)/utils/ + IPC_LIBS := syslink_client + SYSDEFS += DVP_USE_IPC DVP_USE_RCM + SYSIDIRS+= $(IPC_INCS) + endif + ifdef TILER_ROOT + MEM_INCS := $(TILER_ROOT)/ + MEM_INCS += $(TILER_ROOT)/usr/memmgr/ + MEM_INCS += $(TILER_ROOT)/usr/memmgr/public/ + MEM_INCS += $(TILER_ROOT)/usr/memmgr/public/memmgr/ + MEM_LIBS := memmgr + SYSDEFS += DVP_USE_TILER SOSAL_USE_TILER + SYSIDIRS+= $(MEM_INCS) + endif + ifdef OMX_ROOT + OMX_INCS := $(OMX_ROOT)/include + SYSLDIRS += $(OMX_ROOT)/omx_core $(OMX_ROOT)/mm_osal + OMX_LIBS := OMX_Core mmosal + endif + else ifeq ($(TARGET_PLATFORM),CENTEVE) + HOST_COMPILER := TMS470 + TARGET_OS := SYSBIOS + TARGET_CPU := ARM + TARGET_NUM_CORES := 2 + SYSDEFS += TARGET_CENTEVE DVP_STATIC_MANAGERS + SYSIDIRS += $(TMS470_ROOT)/include $(BIOS_ROOT)/packages $(IPC_ROOT)/packages $(XDC_ROOT)/packages + SYSLDIRS += $(TMS470_ROOT)/lib + endif +endif + +ifndef DUCATI_VERSION + DUCATI_VERSION=DUCATI_1_5 +endif + +SYSDEFS += $(TARGET_OS) $(TARGET_CPU) $(TARGET_PLATFORM) TARGET_NUM_CORES=$(TARGET_NUM_CORES) $(DUCATI_VERSION) + +ifeq ($(TARGET_OS),LINUX) + PLATFORM_LIBS := dl pthread rt +else ifeq ($(TARGET_OS),DARWIN) + PLATFORM_LIBS := +else ifeq ($(TARGET_OS),Windows_NT) + PLATFORM_LIBS := Ws2_32 user32 +else ifeq ($(TARGET_OS),__QNX__) + PLATFORM_LIBS := screen socket +else ifeq ($(TARGET_OS),CYGWIN) + PLATFORM_LIBS := c pthread +endif + +ifeq ($(TARGET_CPU),X86) + SYSDEFS+=DVP_TARGET_X86 + TARGET_ARCH=32 +else ifeq ($(TARGET_CPU),X64) + SYSDEFS+=DVP_TARGET_X86 + TARGET_ARCH=64 +else ifeq ($(TARGET_CPU),x86_64) + SYSDEFS+=DVP_TARGET_X86 + TARGET_ARCH=64 +else ifeq ($(TARGET_CPU),ARM) + SYSDEFS+=DVP_TARGET_ARM + TARGET_ARCH=32 +endif + +ifndef TARGET_ARCH +TARGET_ARCH=32 +endif + +SYSDEFS+=ARCH_$(TARGET_ARCH) + +ifdef DVP_DEBUG +SYSDEFS+=DVP_DEBUG=$(DVP_DEBUG) +ifdef DVP_ZONE_MASK +SYSDEFS+=DVP_ZONE_MASK=$(DVP_ZONE_MASK) +endif +endif + +ifdef SOSAL_DEBUG +SYSDEFS+=SOSAL_DEBUG=$(SOSAL_DEBUG) +ifdef SOSAL_ZONE_MASK +SYSDEFS+=SOSAL_ZONE_MASK=$(SOSAL_ZONE_MASK) +endif +endif + +ifdef OMAPRPC_DEBUG +SYSDEFS+=OMAPRPC_DEBUG=$(OMAPRPC_DEBUG) +ifdef OMAPRPC_ZONE_MASK +SYSDEFS+=OMAPRPC_ZONE_MASK=$(OMAPRPC_ZONE_MASK) +endif +endif + +$(info TARGET_OS=$(TARGET_OS)) +$(info TARGET_CPU=$(TARGET_CPU)) +$(info TARGET_PLATFORM=$(TARGET_PLATFORM)) + +# Combinations +# TARGET_CPU=ARM && TARGET_PLATFORM=PLAYBOOK && TARGET_OS=QNX +# TARGET_CPU=X86 && TARGET_PLATFORM=PC +# TARGET_CPU=ARM && TARGET_PLATFORM=SDP +# TARGET_CPU=ARM && TARGET_PLATFORM=BLAZE diff --git a/concerto/tms470.mak b/concerto/tms470.mak new file mode 100644 index 0000000..1b4a81f --- /dev/null +++ b/concerto/tms470.mak @@ -0,0 +1,229 @@ +# Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifndef TMS470_ROOT +$(error You must define TMS470_ROOT!) +endif +ifndef XDC_ROOT +$(error You must define XDC_ROOT!) +endif +ifndef BIOS_ROOT +$(error You must define BIOS_ROOT!) +endif +ifndef IPC_ROOT +$(error You must define IPC_ROOT!) +endif + +CC=cl470 +CP=cl470 +AS=asm470 +AR=ar470 +LD=lnk470 + +ifdef LOGFILE +LOGGING:=&>$(LOGFILE) +else +LOGGING:= +endif + +OBJ_EXT=oeA8F +LIB_PRE= +LIB_EXT=aA8F +ifeq ($(strip $($(_MODULE)_TYPE)),library) + BIN_PRE= + BIN_EXT=.$(LIB_EXT) +else ifeq ($(strip $($(_MODULE)_TYPE)),dsmo) + BIN_PRE= + BIN_EXT=.$(LIB_EXT) +else + BIN_PRE= + BIN_EXT=.$(LIB_EXT) +endif + +$(_MODULE)_BIN := $($(_MODULE)_TDIR)/$(BIN_PRE)$(TARGET)$(BIN_EXT) +$(_MODULE)_OBJS := $(ASSEMBLY:%.S=$($(_MODULE)_ODIR)/%.$(OBJ_EXT)) $(CPPSOURCES:%.cpp=$($(_MODULE)_ODIR)/%.$(OBJ_EXT)) $(CSOURCES:%.c=$($(_MODULE)_ODIR)/%.$(OBJ_EXT)) +$(_MODULE)_ASM := $(ASSEMBLY:%.S=$($(_MODULE)_ODIR)/%.asm) $(CPPSOURCES:%.cpp=$($(_MODULE)_ODIR)/%.asm) $(CSOURCES:%.c=$($(_MODULE)_ODIR)/%.asm) +$(_MODULE)_NFO := $(ASSEMBLY:%.nfo=$($(_MODULE)_ODIR)/%.nfo) $(CPPSOURCES:%.cpp=$($(_MODULE)_ODIR)/%.nfo) $(CSOURCES:%.c=$($(_MODULE)_ODIR)/%.nfo) +# Redefine the local static libs and shared libs with REAL paths and pre/post-fixes +$(_MODULE)_STATIC_LIBS := $(foreach lib,$(STATIC_LIBS),$($(_MODULE)_TDIR)/$(LIB_PRE)$(lib).$(LIB_EXT)) +$(_MODULE)_SHARED_LIBS := $(foreach lib,$(SHARED_LIBS),$($(_MODULE)_TDIR)/$(LIB_PRE)$(lib).$(LIB_EXT)) + +ifeq ($(HOST_OS),Windows_NT) +#$(_MODULE)_OBJS := $(foreach obj,$($(_MODULE)_OBJS), "$(obj)") +endif + +$(_MODULE)_COPT := --gcc + +ifeq ($(TARGET_BUILD),debug) +$(_MODULE)_COPT += --opt_level=0 -g +else ifeq ($(TARGET_BUILD),release) +$(_MODULE)_COPT += --opt_level=3 --gen_opt_info=2 +endif + +ifeq ($(TARGET_CPU),ARM) +$(_MODULE)_COPT +=--endian=little --abi=eabi -mv=7A8 --float_support=vfpv3 +endif + +$(_MODULE)_MAP := -m=$($(_MODULE)_BIN).map +$(_MODULE)_INCLUDES := $(foreach inc,$($(_MODULE)_IDIRS),-I="$(basename $(inc))") $(foreach inc,$($(_MODULE)_SYSIDIRS),-I="$(basename $(inc))") +$(_MODULE)_DEFINES := $(foreach def,$($(_MODULE)_DEFS),-d=$(def)) +$(_MODULE)_LIBRARIES:= $(foreach ldir,$($(_MODULE)_LDIRS),--search_path="$(ldir)") $(foreach ldir,$($(_MODULE)_SYSLDIRS),--search_path="$(ldir)") $(foreach lib,$(STATIC_LIBS),--library=$(LIB_PRE)$(lib).$(LIB_EXT)) $(foreach lib,$(SYS_STATIC_LIBS),--library=$(LIB_PRE)$(lib).$(LIB_EXT)) +$(_MODULE)_AFLAGS := $($(_MODULE)_INCLUDES) +$(_MODULE)_LDFLAGS := -z --warn_sections --reread_libs --rom_model +$(_MODULE)_CPLDFLAGS := $(foreach ldf,$($(_MODULE)_LDFLAGS), $(ldf)) +$(_MODULE)_CFLAGS := $($(_MODULE)_INCLUDES) $($(_MODULE)_DEFINES) $($(_MODULE)_COPT) + +################################################### +# COMMANDS +################################################### + +$(_MODULE)_CLEAN_OBJ := $(CLEAN) $(call PATH_CONV,$($(_MODULE)_OBJS) $($(_MODULE)_ASM) $($(_MODULE)_NFO)) +$(_MODULE)_CLEAN_BIN := $(CLEAN) $(call PATH_CONV,$($(_MODULE)_BIN)) +$(_MODULE)_LINK_LIB := $(call PATH_CONV,$(AR) ru2 $($(_MODULE)_BIN) $($(_MODULE)_OBJS) $($(_MODULE)_STATIC_LIBS)) +$(_MODULE)_LINK_EXE := $(call PATH_CONV,$(AR) ru2 $($(_MODULE)_BIN) $($(_MODULE)_OBJS) $($(_MODULE)_STATIC_LIBS)) + +# $(call PATH_CONV,$(CP) $($(_MODULE)_CPLDFLAGS) -o $($(_MODULE)_BIN) $($(_MODULE)_OBJS) $($(_MODULE)_LIBRARIES) $($(_MODULE)_MAP) $($(_MODULE)_SDIR)) + +################################################### +# MACROS FOR COMPILING +################################################### + +define $(_MODULE)_DEPEND_CC +# Do nothing... +endef + +define $(_MODULE)_DEPEND_CP +# Do nothing... +endef + +define $(_MODULE)_DEPEND_AS +# Do nothing... +endef + +ifeq ($(strip $($(_MODULE)_TYPE)),prebuilt) + +define $(_MODULE)_PREBUILT + +$($(_MODULE)_SDIR)/$(1): + +build:: $($(_MODULE)_SDIR)/$(1) + +install:: $($(_MODULE)_TDIR)/$(notdir $(1)) + +$($(_MODULE)_TDIR)/$(notdir $(1)): $($(_MODULE)_SDIR)/$(1) $($(_MODULE)_ODIR)/.gitignore + @echo Copying Prebuilt binary $($(_MODULE)_SDIR)/$(1) to $($(_MODULE)_TDIR)/$(notdir $(1)) + -$(Q)$(call PATH_CONV,$(COPY) $($(_MODULE)_SDIR)/$(1) $($(_MODULE)_TDIR)/$(notdir $(1))) +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),library) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo No uninstall step for static libraries +endef + +define $(_MODULE)_INSTALL +install:: + @echo No install step for static libraries +endef + +define $(_MODULE)_BUILD +build:: $($(_MODULE)_BIN) + @echo Building $$(notdir $$<) as static library +endef + +define $(_MODULE)_CLEAN_LNK +clean:: +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),dsmo) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo No dynamic objects are supported! +endef + +define $(_MODULE)_INSTALL +install:: + @echo No dynamic objects are supported! +endef + +define $(_MODULE)_BUILD +$($(_MODULE)_BIN): $($(_MODULE)_OBJS) $($(_MODULE)_STATIC_LIBS) $($(_MODULE)_SHARED_LIBS) + @echo Linking $$@ + -$(Q)$(call $(_MODULE)_LINK_LIB) $(LOGGING) + +build:: $($(_MODULE)_BIN) + @echo Building $$(notdir $$<) as static library +endef + +define $(_MODULE)_CLEAN_LNK +clean:: + @echo No dynamic objects are supported! +endef + +else ifeq ($(strip $($(_MODULE)_TYPE)),exe) + +define $(_MODULE)_UNINSTALL +uninstall:: + @echo No uninstall step for $(TARGET_CPU) +endef + +define $(_MODULE)_INSTALL +install:: + @echo No install step for $(TARGET_CPU) +endef + +define $(_MODULE)_BUILD +build:: $($(_MODULE)_BIN) + @echo Building $$(notdir $$<) as static library +endef + +define $(_MODULE)_CLEAN_LNK +clean:: + @echo No clean link step defined! +endef + +endif + +ifeq ($(HOST_OS),Windows_NT) +define $(_MODULE)_COMPILE_TOOLS +$($(_MODULE)_ODIR)/%.$(OBJ_EXT): $($(_MODULE)_SDIR)/%.c $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Compiling C99 $$(notdir $$<) + $(Q)$$(call PATH_CONV,$(CC) -c $($(_MODULE)_CFLAGS) -fr="$$(dir $$@)\" -fo=$$@ -fs="$$(dir $$@)\" -fp="$$<" $(LOGGING)) + +$($(_MODULE)_ODIR)/%.$(OBJ_EXT): $($(_MODULE)_SDIR)/%.cpp $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Compiling C++ $$(notdir $$<) + $(Q)$$(call PATH_CONV,$(CP) -c $($(_MODULE)_CFLAGS) -fr="$$(dir $$@)\" -fo=$$@ -fs="$$(dir $$@)\" -fp="$$<" $(LOGGING)) + +$($(_MODULE)_ODIR)/%.$(OBJ_EXT): $($(_MODULE)_SDIR)/%.S $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Assembling $$(notdir $$<) + $(Q)$$(call PATH_CONV,$(AS) -c $($(_MODULE)_AFLAGS) -fr="$$(dir $$@)" -fo=$$@ "$$<" $(LOGGING)) +endef +else +define $(_MODULE)_COMPILE_TOOLS +$($(_MODULE)_ODIR)/%.$(OBJ_EXT): $($(_MODULE)_SDIR)/%.c $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Compiling C99 $$(notdir $$<) + $(Q)$$(call PATH_CONV,$(CC) -c $($(_MODULE)_CFLAGS) -fr=$$(dir $$@) -eo=.$(OBJ_EXT) -fo=$$@ -fs=$$(dir $$@) -fc=$$< $(LOGGING)) + +$($(_MODULE)_ODIR)/%.$(OBJ_EXT): $($(_MODULE)_SDIR)/%.cpp $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Compiling C++ $$(notdir $$<) + $(Q)$$(call PATH_CONV,$(CP) -c $($(_MODULE)_CFLAGS) -fr=$$(dir $$@) -eo=.$(OBJ_EXT) -fo=$$@ -fs=$$(dir $$@) -fp=$$< $(LOGGING)) + +$($(_MODULE)_ODIR)/%.$(OBJ_EXT): $($(_MODULE)_SDIR)/%.S $($(_MODULE)_ODIR)/.gitignore + @echo [PURE] Assembling $$(notdir $$<) + $(Q)$$(call PATH_CONV,$(AS) -c $($(_MODULE)_AFLAGS) -fr=$$(dir $$@) -eo=.$(OBJ_EXT) -fo=$$@ -fa=$$< $(LOGGING)) +endef + +endif diff --git a/docs/articles.txt b/docs/articles.txt new file mode 100644 index 0000000..4fe4b4f --- /dev/null +++ b/docs/articles.txt @@ -0,0 +1,4 @@ + +/*! \page Articles Articles*/ + + diff --git a/docs/dot/dep_android.dot b/docs/dot/dep_android.dot new file mode 100644 index 0000000..1b39e35 --- /dev/null +++ b/docs/dot/dep_android.dot @@ -0,0 +1,86 @@ +digraph { + label="High Level Android System Dependencies"; + node [color=red shape="box" style=filled]; + + subgraph cluster_omap4 { + label="OMAP4"; + + subgraph cluster_cpu { + + rankdir=TB; + label="Dual Cortex A9"; + + subgraph cluster_android { + label="Android - Native"; + + DVP [label="Distributed\nVision\nProcessing\n(DVP)"]; + SOSAL [label="Simple Operating\nSystem Abstraction\n(SOSAL)"]; + VISIONCAM [label="VisionCam"]; + VISIONENGINE [label="VisionEngine"]; + OMXCAMERA [color=grey label="OpenMAX Camera\nProxy"]; + GRALLOC [color=yellow label="GRALLOC"]; + ANW [color=yellow label="ANativeWindow"]; + + VISIONCAM -> OMXCAMERA; + VISIONENGINE -> VISIONCAM; + VISIONENGINE -> DVP; + VISIONENGINE -> SOSAL; + DVP -> ANW -> GRALLOC; + DVP -> SOSAL; + OMXCAMERA -> GRALLOC; + } + subgraph cluster_kernel { + label="Kernel"; + + OMAPRPC [label="OMAP RPC"]; + ION [color=grey label="ION"]; + RPMSG [color=grey label="rpmsg"]; + REMOTEPROC [color=grey label="remoteproc"]; + PVR [color=grey label="PVR"]; + ASHMEM [color=yellow label="ashmem"]; + OMXRPC [color=grey label="OMX-RPC"]; + + OMAPRPC -> RPMSG; + OMAPRPC -> ION; + OMAPRPC -> PVR; + OMAPRPC -> REMOTEPROC; + PVR -> ION; + OMXRPC -> RPMSG; + OMXRPC -> ION; + OMXRPC -> PVR; + OMXRPC -> REMOTEPROC; + } + SOSAL -> ION [label="/dev/ion"]; + SOSAL -> GRALLOC [label="hw_module"]; + SOSAL -> ASHMEM [label="/dev/ashmem"]; + DVP -> OMAPRPC [label="/dev/dvp_kgm_xxxxx"]; + GRALLOC -> PVR [label="/dev/pvrsrvkm"]; + OMXCAMERA -> OMXRPC [label="/dev/rpmsg-omx1"]; + } + subgraph cluster_ipu { + label="Dual Cortex M3"; + + SRVMGR_IPU [color=grey label="ServiceMgr"]; + OMAPRPC2 [label="OMAP RPC Task"]; + OMXRPC2 [color=grey label="OMX RPC Task"]; + DVP2 [label="DVP KGM SIMCOP"]; + OMXCAMERA2 [color=grey label="OpenMAX Camera"]; + + DVP2 -> OMAPRPC2 -> SRVMGR_IPU; + OMXCAMERA2 -> OMXRPC2 -> SRVMGR_IPU; + } + subgraph cluster_dsp { + label="c64T Tesla"; + + SRVMGR_DSP [color=grey label="ServiceMgr"]; + OMAPRPC3 [label="OMAP RPC Task"]; + DVP3 [label="DVP KGM DSP"]; + + DVP3 -> OMAPRPC3 -> SRVMGR_DSP; + } + + RPMSG -> SRVMGR_IPU [dirType="both" style="dotted" label="(simplified)"]; + RPMSG -> SRVMGR_DSP [dirType="both" style="dotted" label="(simplified)"]; + } +} + diff --git a/docs/dot/dvp.dot b/docs/dot/dvp.dot new file mode 100644 index 0000000..2e9e564 --- /dev/null +++ b/docs/dot/dvp.dot @@ -0,0 +1,189 @@ +digraph dvp_components { + //rankdir=LR; + node [color=red shape="box" style=filled]; + + subgraph cluster_mpu { + label="Dual Core Cortex A9 (MPU)"; + color=grey; + style=filled; + + subgraph cluster_user { + color=white; + style=filled; + label="Client Application"; + CLIENT [color=blue label="User Defined Engine"]; + } + subgraph cluster_engines { + color=white; + style=filled; + label="Vision Services"; + VISIONENGINE [label="VisionEngine"]; + VISIONCAM [label="VisionCam"]; + VISIONENGINE -> VISIONCAM; + } + CLIENT -> VISIONENGINE; + subgraph cluster_dvp { + color=white; + style=filled; + label="Distributed Vision Processing API"; + DVP_API [shape=record color=black fillcolor=red label="{DVP API|{Graphs|Images|Buffers|Display}}"]; + DVP_KGB [label="Kernel Graph Boss"]; + DVP_KGMP_DSP [shape=record color=black fillcolor=red label="{Kernel Graph Manager\n for DSP (Proxy)|RPC}"]; + DVP_KGMP_SIMCOP [shape=record color=black fillcolor=red label="{Kernel Graph Manager\n for SIMCOP (Proxy)|RPC}"]; + DVP_KGMP_EVE [shape=record color=black fillcolor=red label="{Kernel Graph Manager\n for EVE (Proxy)|RPC}"]; + DVP_KGM_CPU [label="Kernel Graph Manager\n on CPU"]; + DVP_KGMP_CLOUD [label="Kernel Graph Manager\n for Cloud (Proxy)"]; + DVP_KGM_OCL [label="Kernel Graph Manager\n for OpenCL"]; + DVP_MEM [label="Memory Subsystem"]; + + DVP_API:f0 -> DVP_KGB; + DVP_API:f0 -> DVP_MEM; + DVP_API:f1 -> DVP_MEM; + DVP_API:f2 -> DVP_MEM; + DVP_KGB -> DVP_KGMP_DSP; + DVP_KGB -> DVP_KGMP_SIMCOP; + DVP_KGB -> DVP_KGMP_EVE; + DVP_KGB -> DVP_KGM_CPU; + DVP_KGB -> DVP_KGMP_CLOUD; + DVP_KGB -> DVP_KGM_OCL; + } + subgraph cluster_sosal { + color=white; + style=filled; + label="Simple Operating System Abstraction"; + SOSAL [shape=record color=black fillcolor=red label="{allocator|bitfield|threads}|{queue|uinput|locks}|{list|hash|heap}|{ring|threadpool|image}"]; + } + VISIONENGINE -> DVP_API; + VISIONENGINE -> SOSAL:f2; + VISIONENGINE -> SOSAL:f3; + DVP_MEM -> SOSAL:f0; + subgraph cluster_openmax { + color=white; + style=filled; + label="OpenMAX"; + OMX_CAMERA_PROXY [label="OpenMAX Camera Proxy"]; + } + VISIONCAM -> OMX_CAMERA_PROXY; + subgraph cluster_opencl { + color=white; + style=filled; + label="OpenCL"; + OPENCL [color=green label="OpenCL Kernels\n for Vision"]; + } + subgraph cluster_kernel { + label="Linux Kernel"; + color=yellow; + style=filled; + V4L2 [shape=record color=black fillcolor=red label="{{UVC|OVERLAY}|V4L2}"]; + OMX_RPC [label="OpenMAX RPC Driver"]; + OMAPRPC_CPU [label="OMAPRPC Kernel Driver"]; + SGX_DRV [label="PowerVR Driver"]; + NETWORK [label="Networking Stack"]; + FILESYS [label="File Systems"]; + ION [label="ION"]; + UINPUT_DRV [label="uinput"]; + } + SOSAL:f0 -> ION; + SOSAL:f4 -> UINPUT_DRV; + VISIONCAM -> V4L2:f0; + VISIONCAM -> FILESYS; + VISIONCAM -> NETWORK; + DVP_API:f3 -> V4L2:f1; + KERNELS_CPU [shape=record color=black fillcolor=green style=filled label="YUV | IMGFILTER | VLIB | IMGLIB"]; + + DVP_KGM_CPU -> KERNELS_CPU; + DVP_KGMP_DSP -> OMAPRPC_CPU; + DVP_KGMP_SIMCOP -> OMAPRPC_CPU; + DVP_KGMP_EVE -> OMAPRPC_CPU; + DVP_KGMP_CLOUD -> NETWORK; + DVP_KGM_OCL -> OPENCL -> SGX_DRV; + OMX_CAMERA_PROXY -> OMX_RPC; + } + + subgraph cluster_cloud { + label="Cloud Computation"; + color=grey; + style=filled; + KGM_CLOUD [label="Kernel Graph Manager Cloud"]; + FLAMES [label="libFlame on Shannon"]; + + KGM_CLOUD -> FLAMES; + } + + NETWORK -> KGM_CLOUD [label="sockets"]; + + subgraph cluster_ipu { + color=grey; + style=filled; + label="Dual Core Cortex M3 (IPU)"; + OMAPRPC_IPU [label="OMAPRPC Service Mgr Task"]; + OMAPRPC_EVE [label="OMAPRPC Service Mgr Task"]; + KGM_SIMCOP [label="Kernel Graph Manager \nfor SIMCOP"]; + KGM_EVE [label="Kernel Graph Manager \nfor EVE"]; + OMX_MGRTSK [label="OMX Service Mgr Task"]; + OMXCAMERA [label="OMX Camera"]; + VRUN [color=green label="VRUN"]; + GRABP [label="GraBP"]; + IPIPE [label="IPipe"]; + + OMAPRPC_IPU -> KGM_SIMCOP -> VRUN; + OMAPRPC_EVE -> KGM_EVE -> GRABP; + OMX_MGRTSK -> OMXCAMERA -> IPIPE; + } + OMAPRPC_CPU -> OMAPRPC_IPU [label="rpmsg"]; + OMAPRPC_CPU -> OMAPRPC_EVE [label="rpmsg"]; + OMX_RPC -> OMX_MGRTSK [label="rpmsg"]; + + subgraph cluster_dsp { + color=grey; + style=filled; + label="C64T (DSP)"; + OMAPRPC_DSP [label="OMAPRPC Service Mgr Task"]; + KGM_DSP [label="Kernel Graph Manager \non DSP"]; + EDMA [label="Enhanced DMA Lib"]; + + KERNELS_DSP [shape=record color=black fillcolor=green style=filled label="VLIB|IMGLIB|RVM|TISMO"]; + + OMAPRPC_DSP -> KGM_DSP -> EDMA; + KGM_DSP -> KERNELS_DSP; + } + OMAPRPC_CPU -> OMAPRPC_DSP [label="rpmsg"]; + + subgraph cluster_gpu { + color=grey; + style=filled; + label="GPU" + SGX [label="OpenCL Runtime"]; + } + SGX_DRV -> SGX [label="pvr"]; + + subgraph cluster_simcop { + color=grey; + style=filled; + label="SIMCOP"; + IMX0 [label="4 MAC iMX"]; + IMX1 [label="4 MAC iMX"]; + } + + VRUN -> IMX0; + VRUN -> IMX1; + + subgraph cluster_eve { + color=grey; + style=filled; + label="Embedded Vision Engine" + EVE0 [label="EVE"]; + EVE1 [label="EVE"]; + } + GRABP -> EVE0; + GRABP -> EVE1; + + subgraph cluster_iss { + color=grey; + style=filled; + label="Imaging Subsystem"; + SENSOR [label="Raw Sensors"]; + } + IPIPE -> SENSOR; + +} diff --git a/docs/dot/high_level.dot b/docs/dot/high_level.dot new file mode 100644 index 0000000..fd79a11 --- /dev/null +++ b/docs/dot/high_level.dot @@ -0,0 +1,51 @@ +digraph high_level_components { + node [shape=box color=red style=filled]; + + subgraph cluster_cpu { + label="CPU"; + style=filled; + color=grey; + APP [label="Application"]; + DVP [shape=record color=black fillcolor=red label="{DVP|KGB}"]; + KGM_CPU [label="KGM CPU"]; + KGM_OCL [label="KGM OpenCL"]; + NEON [shape=record color=black fillcolor=grey label="NEON|SMP"]; + } + + subgraph cluster_ipu { + label="IPU"; + style=filled; + color=grey; + KGM_EVE [label="KGM EVE"]; + KGM_SIMCOP [label="KGM SIMCOP"]; + } + + subgraph cluster_dsp { + label="DSP"; + style=filled; + color=grey; + KGM_DSP [label="KGM DSP"]; + } + + subgraph cluster_gpu { + label="GPU"; + style=filled; + color=grey; + OPENCL [label="OPENCL"]; + } + + subgraph cluster_cloud { + label="Cloud"; + style=filled; + color=grey; + KGM_CLOUD [label="KGM Cloud"]; + } + + APP -> DVP:f0; + DVP:f1 -> KGM_CPU -> NEON; + DVP:f1 -> KGM_OCL -> OPENCL; + DVP:f1 -> KGM_SIMCOP; + DVP:f1 -> KGM_EVE; + DVP:f1 -> KGM_DSP; + DVP:f1 -> KGM_CLOUD; +} diff --git a/docs/dvp_arch.txt b/docs/dvp_arch.txt new file mode 100644 index 0000000..bb00933 --- /dev/null +++ b/docs/dvp_arch.txt @@ -0,0 +1,84 @@ +/*! +\page page_arch_overview Architecture Overview + + \section high_level_diagram High Level Diagram + + \dotfile high_level.dot + + \section sec_distribution Distribution + +DVP uses an RPMSG-based driver called OMAPRPC to distribute work across the OMAP4 +system. + + \section manager_prioritization Manager Prioritization + +DVP internally prioritizes some hardware blocks over others due to implicit +performance advantages due to hardware designs. If multiple Managers support +the same kernel, DVP will internally determine how to prioritize whose kernel +is called. DVP will use the Load Balancing information as a second level of +decision making. + +Currently the prioritization for OMAP4 is: +-# sIMCOP +-# DSP +-# CPU + +This means if there is a Kernel "A" implemented on all Managers, it will +prefer to execute the kernel on the highest priority Manager first working its + way down the priority list only when the Core that the Manager works on is +exhausted of resources. + + \section load_balancing Load Balancing + +DVP understands that real-time contraints can be expected in production +devices and therefore has an Estimated Load table, whose input helps control where the +machine vision kernels execute. Load Balancing is predictive only and does +not use any run-time checking to compute load. This is done because not all +Cores are capable of run-time detection. For example, the SIMCOP is really an +accelerator and is more accurately thought of as serially accessed in bursts +of 100% utilization since no two tasks can be present concurrently (or at +least aren't in this design). + + \section multi_dvp Multiple DVP Instances + +DVP can execute multiple Graphs in parallel within the same process or across +multiple processes. The Estimated Load Table is in a semaphore protected +piece of shared memory so that multiple processes can utilize the DVP system +at once. Each process gets its own instance of the Managers, but there is +only one Estimated Load Table. + + \section nodes Nodes + +A node (\ref DVP_KernelNode_t) is the combination of the Kernel enumeration, the parameters to be +given to the kernel and some needed overhead. + + \section sections Sections + +A section (\ref DVP_KernelGraphSection_t) is a series of nodes collected into a logical set by the client. +At the end of a section a callback is issued to the client. + + \section graphs Graphs + +A graph (\ref DVP_KernelGraph_t), in this context, represents one or more sets of sections which are +executed in series or parallel. The sections are arranged in a specific execution order and if +this order is the same as another section's, parallelism is possible. In this +case, the order is set by the client. + + \section callbacks Section Completion Callbacks + +After each section completes execution, a callback is issued to the client to +notify them of completion. This callback has several features. + +- The Callback is internally semaphore protected so that the client does not +need to implement a protection mechanism. +- The Callback is intended to allow the client to do any necessary operations +between sections of a DVP Graph. These could be: +
    +
  • Private Algorithms performed on the output of the previous section +
  • Logical operations to determine if future sections need to run. If not, + future sections can be marked as "skip" so they will not be executed. The Client + would be responsible for clearing the "skip" flag before the next Graph execution. +
+ +*/ + diff --git a/docs/dvp_callsequence.txt b/docs/dvp_callsequence.txt new file mode 100644 index 0000000..49d5eae --- /dev/null +++ b/docs/dvp_callsequence.txt @@ -0,0 +1,11 @@ +/*! +\page page_callsequences Call Sequences + +This page documents how command sequences flow around the system during DVP execution. + +\section sec_cs_overview System Level View + +\mscfile callgraph.msc + +*/ + diff --git a/docs/dvp_datapath.txt b/docs/dvp_datapath.txt new file mode 100644 index 0000000..a457584 --- /dev/null +++ b/docs/dvp_datapath.txt @@ -0,0 +1,12 @@ +/*! +\page page_datapath Data Paths + +This page documents how data flows around the system during DVP execution. + +\section sec_zero Zero Copy + +Insofar as possible, DVP is a zero-copy system. All memory is sourced and +shared, by translated pointer across cores. + +*/ + diff --git a/docs/dvp_debugging.txt b/docs/dvp_debugging.txt new file mode 100644 index 0000000..60e7051 --- /dev/null +++ b/docs/dvp_debugging.txt @@ -0,0 +1,37 @@ + +/*! \page page_debug Debugging Code + +DVP uses a "ZONE" flag concept to break up the large amount of debugging output +that can occur in a standard set of transactions. \ref DVP_ZONE_MASK is the +bitfield of all zone bits which can be enabled or disabled. There is a hard +limit if the architecture bit depth for the number of zones supported in DVP. + +See \ref group_debugging + +To enable specific zones during a build, make sure the \ref DVP_DEBUG and \ref +DVP_ZONE_MASK (as well as \ref SOSAL_DEBUG and \ref SOSAL_ZONE_MASK) are set +correctly. + +In Linux environments: + +\code + $ export DVP_DEBUG=1 + $ export DVP_ZONE_MASK=0x2103 + $ export SOSAL_DEBUG=1 + $ export SOSAL_ZONE_MASK=0x3 + $ make clean + $ make +\endcode + +In Android Environments: + +\code + $ export DVP_DEBUG=1 + $ export DVP_ZONE_MASK=0x2103 + $ export SOSAL_DEBUG=1 + $ export SOSAL_ZONE_MASK=0x3 + $ dvp.sh clean mm +\endcode + + */ + diff --git a/docs/dvp_depend.txt b/docs/dvp_depend.txt new file mode 100644 index 0000000..de45da3 --- /dev/null +++ b/docs/dvp_depend.txt @@ -0,0 +1,33 @@ +/*! +\page page_depend Software Dependencies + + +DVP depends on multiple system components to acheive it's features. Here's a +high level overview of it's component dependencies. + +\dotfile dep_android.dot + +\section sec_ipc OMAPRPC driver + +DVP on all OMAP4-based platforms depends on the OMAPRPC driver for all remote +procedure calls. OMAPRPC is a RPMSG driver specifically designed to do function +calls. + +\section sec_ion ION Memory Allocator + +DVP would like to have ION caching support for ARM side access to buffers. + +\section sec_anativewindow ANativeWindow + +DVP uses ANativeWindow's for Camera capture buffers in some applications. + +\section sec_omxcamera OpenMAX Camera + +OMX-CAMERA was patched as needed to match Ducati OMX Camera features which we are not introduced on the mainline yet. + +\section sec_android Miscellaneous + +-# init.rc - Adding system daemons and shared memory service as needed. +-# ueventd.rc - Adding dvp_kgm_xxxx endpoints with a+rw permissions. + +*/ diff --git a/docs/dvp_design.txt b/docs/dvp_design.txt new file mode 100644 index 0000000..cae79dd --- /dev/null +++ b/docs/dvp_design.txt @@ -0,0 +1,82 @@ +/*! \page page_design_rationale Design Rationale + +The design rationale of DVP is to create a systematic way to process machine +vision kernels across multiple cores in a heterogeneous computing system like +the OMAP44xx, leveraging specialized hardware which can greatly accelerate +specific machine vision kernels while minimizing latency by aggregating IPC +transactions. + + \section remoteexecution Remote Execution Considerations + + \subsection ipc Interprocess Communication (IPC) Overhead + +One of the biggest challenges of using heterogeneous multi-cores is the +latency involved in IPC. Even with high-speed IPC on the order to microseconds, HLOS's still have +higher level latency issues such as context switches between processes and +kernels, and inter-thread switching. Remote work aggregation is the only +method of mitigating this unpredicatable overhead. + + \subsection example_bad High IPC Overhead Example + +\msc + a [label="Client Process"], b [label="HLOS Kernel"], c [label="Remote Core"]; + a=>b [label="exec(kernel1)"]; + b=>c [label=""]; + c->c [label="kernel1()"]; + b<b [label="exec(kernel2)"]; + b=>c [label=""]; + c->c [label="kernel2()"]; + b<b [label="exec(kernel3)"]; + b=>c [label=""]; + c->c [label="kernel3()"]; + b<b [label="exec(section(kernel1,kernel2,kernel3))"]; + b=>c [label=""]; + c->c [label="kernel1()"]; + c->c [label="kernel2()"]; + c->c [label="kernel3()"]; + b< b -> c -> d -> e -> f -> g -> h; + } + } + } + } +\enddot + +In an optimized version the programmer may have discovered that some nodes +are not dependent on previous nodes and can be reordered and made parallel to +gain performance. In this example, 'b', 'd' and 'e' depend on 'a', 'c' on 'b' +, 'f' on 'e', 'g' on 'c' and 'f' and 'h' on 'g'. There are now 5 Sections, 'a' +, 'bc', 'd', 'ef', and 'gh'. and three Orders: 'a' has 0, 'bc','d', and 'ef' +have order 1, and 'gh' has order 2. + +\dot + digraph graph2 { + label="Series of Parallel Kernel Nodes grouped in Sections/Orders"; + rankdir=LR; + node [shape=box]; + subgraph cluster_graph_0 { + label="Graph" + subgraph order_0 { + label="Order 0"; + subgraph cluster_section0 { + label="Section 0"; + a; + } + } + subgraph order_1 { + label="Order 1" + subgraph cluster_section1 { + label="Section 1"; + b -> c; + } + subgraph cluster_section2 { + label="Section 2"; + d; + } + subgraph cluster_section3 { + label="Section 3"; + e -> f; + } + } + subgraph order2 { + label="Order 2" + subgraph cluster_section4 { + label="Section 4" + g -> h; + } + } + a -> b; + a -> d; + a -> e; + c -> g; + f -> g; + } + } + +\enddot + +In this example 'b', 'd', and 'e' depend on 'a' but not on each other. This Graph will +execute section 0 ('a') first and wait until completion, then will concurrently launch +sections 1, 2 and 3 ('bc +', 'd', 'ef') (potentially in parallel on an SMP/HMP system), then when those have +completed, it will launch section 4 ('gh') and wait for completion. + + +In this example, assuming Nodes 'a' through 'f': + +\dot + digraph graph3 { + label="Two Sections in series with a client callback"; + rankdir=LR; + node [shape=box]; + subgraph cluster_user { + label="Client"; + Callback; + } + subgraph cluster_graph3 { + label="Graph"; + subgraph order0 { + subgraph cluster_section0 { + label="Section 0"; + a -> b -> c; + } + } + subgraph order1 { + subgraph cluster_section1 { + label="Section 1"; + d -> e -> f; + } + } + c -> d; + } + c -> Callback; + f -> Callback; + } +\enddot + +\section sample_implementations Sample Implementations + +The following examples show how to use DVP public APIs. They are +listed in increasing order of complexity. + +- \subpage dvp_simple - A simple DVP graph setup demonstrating the power of +DVP to execute functions in serial or in parallel on different cores. +- \subpage dvp_demo - Takes QQVGA camera frames from the VisionCam, processes +a large kernel graph through DVP, and finally displays on the screen (Note: Not +supported on Android ICS). + +*/ +//----------------------------------------------------------------------------- +/*! + + +\page dvp_simple dvp_simple + +The dvp_simple test is an example of parallel and serial graph execution. +It does not use any camera or display, or input or output image files. +In fact, the input buffers are not initialized to any image data or patterns. +The test is intetended to demonstrate dvp graph construction, and test proper +execution and control flow. This page lists the \ref simple_process of the test, followed +by the \ref simple_graph, \ref simple_usage, and the \ref simple_code. + +File Reference: dvp_simple.c + +\section simple_process Execution Flow +- An array of 11 structures of type DVP_Image_t are initialized therein. +- Images are allocated for each of these based on the parameters initialized (DVP_Image_Alloc()). +- An array of 9 nodes of type DVP_KernelNode_t are allocated. +- An array of 4 sections of type DVP_KernelGraphSection_t are initialized with + the starting node and number of each node for each section. +- A graph of type DVP_KernelGraph_t is initialized with this array of sections, + including order information to specify that the first three sections execute first + in parallel, and the fourth section executes sequentially afterwards. +- Each node structure is configured with the kernel, input/output buffers, core affinity, + and any configuration information that is specific to the kernel assigned. + - In this example, the affinity of the three parallel sections are all different, so that + they can truly execute in parallel on different cores. + - In this example, each of the kernels use the simple transform data type, so there is no + kernel specific parameters other than the input and output buffer. +- For load managment, the core capacity is queried (DVP_GetCoreCapacity()) and set ( + DVP_GetCoreCapacity())for each core. +- The graph is executed by calling DVP_KernelGraphs(), passing the graph and callback + that will be called after each section completes. This is done in a loop until the full number + of frames is completed. +- After the graph execution has completed for the full number of iterations, the built-in + performance profiling instrumentation can be printed to the debug traces using + DVP_PrintPerformanceGraph(), assuming that the DVP_DEBUG and DVP_ZONE_MASK bit, DVP_ZONE_PERF, + environment variables were set when this was built (see \ref page_debug). +- Finally, when the test is completed, all the memory and structures are freed, and the graph resources + are torn down by calling DVP_KernelGraph_Deinit(). + +\section simple_graph Graph Diagram +The following figure depicts the graph construction for this test. +\image html dvp_simple_graph.jpg +\image latex dvp_simple_graph.jpg + +\section simple_usage Usage +\a dvp_simple [OPTIONS]\n\n +OPTIONS (defaults are used when option is not supplied): +- \b -w, --width: Image Width [default: 320] +- \b -h, --height: Image Height [default: 240] +- \b -t, --type: Memory Type (see enum \ref DVP_MemType_e ) [default: DVP_MTYPE_DEFAULT] +- \b -c, --capacity: Limit MHz for each core to this capacity [default: 100] +- \b -i, --iterations: The number of times this graph is executed [default: 1] + +\section simple_code Source +\include dvp_simple.c + + +\page dvp_demo dvp_demo + +dvp_demo is an example of more complex video memory usage and camera capture. It +also has a basic (but large) graph of parallel and serial nodes. + +\include dvp_demo.cpp + +*/ + + diff --git a/docs/dvp_extending.txt b/docs/dvp_extending.txt new file mode 100644 index 0000000..1b39152 --- /dev/null +++ b/docs/dvp_extending.txt @@ -0,0 +1,66 @@ +/*! \page page_extending_dvp Extending DVP + +It is relatively straight forward to extend DVP to provide private +implementations of some kernels. The Kernel Enum list has a definition for a +"user" enum base which can be used to create custom kernel enums. These must +simply not conflict with existing enums in the system. The DVP Boss will scan all +Managers for exported kernel enums and will execute the kernels on those +Managers given the prioritization of the Managers. If no Manager supports a +kernel except the new extended Manager, then prioritization is not an issue. +Prioritization is only considered when two or more Managers contain a kernel +enum. + + \todo creating your own dvp_kl_header.h, library range. etc. + + \section extending_kl Adding your own Kernel Library + +In the \ref dvp_types.h there is a \ref DVP_KernelLibrary_e definition +which lists all the observed Kernel Libraries. Use the \ref +DVP_KL_EXTERNAL_LIBRARIES enum to start counting your library sets. + +\code +enum my_kernel_libraries_e { + MY_KL_SET = DVL_KL_EXTERNAL_LIBRARIES, +}; + +typdef enum _my_kernels_e { + MY_KN_BASE = DVP_LIBRARY_BASE(ML_KL_SET), + MY_KN_ONE, /*!< My First Kernel Algorithm */ +} MyKernels_e; + +\endcode + +You probably do not want to add features to the \ref DVP_KernelFeature_e +list unless you are going to contribute it back to DVP in reference "C" +code. + + \section extending_implement Implementing your own KGM + +Your KGM simply needs to: + +\code +// In "C" +#include + +// In Makefile +LOCAL_C_INCLUDES += $(DVP_ROOT)/source/dvp/dvp_kgraph/include +\endcode + +And implement the KGM interface. See the \ref dvp_kgm_cpu.c file for a +reference. + + \section extending_compiling Compiling your KGM + +Build your KGM as either part of or separately from DVP. + + \section extending_loading Loading + +On HLOS platforms with scandir() and fnmatch() implemented, the DVP Boss will +dynamically load any shared object with the appropriate name ("/ +dvp_kgm_XXXX.so"). While this might seem dangerous from a security point of +view, the Boss will specifically load only from the system library paths, +which must themselves be compromised in order to breach security. On Android, +this is the /system/lib path which is locked to R/W access from Users. + +*/ + diff --git a/docs/dvp_how_to_guide.txt b/docs/dvp_how_to_guide.txt new file mode 100644 index 0000000..280ccb2 --- /dev/null +++ b/docs/dvp_how_to_guide.txt @@ -0,0 +1,149 @@ +/*! + +\page dvp_how_to_guide How-to Guide: Performing Commonly Used Tasks using DVP + +This section is intended to show developers how to implement common tasks and +frequently used operations using DVP. The following declarations are used +across the next sections. For simplicity, the error checking pieces of the code are left out. + +\code + // declaration + DVP_Handle hDVP = 0; + DVP_Image_t images[2]; + DVP_KernelNode_t *pNodes = NULL; + DVP_KernelGraph_t *graph = NULL; + DVP_U32 numNodes = 1; + DVP_Transform_t *io = NULL; +\endcode + +\section howto_init How to Initialize the System + +This is how to initialize the DVP system. + +\code + // get the handle (will implicitly load .so/.dll and initialize RPC). + hDVP = DVP_KernelGraph_Init(); +\endcode + +\section howto_allocate_images How To Allocate Images + +This is how to initialize the image memory structure and allocate the images. + +\code + // initialize the images + DVP_Image_Init(&images[0], width, height, FOURCC_UYVY); + DVP_Image_Init(&images[1], width, height, FOURCC_RGBP); + + // allocate the images + DVP_Image_Alloc(hDVP, &images[0], DVP_MTYPE_DEFAULT); + DVP_Image_Alloc(hDVP, &images[1], DVP_MTYPE_DEFAULT); +\endcode + +\section howto_define_a_node How To Define A Node + +The following shows one possible approach towards creating a node. +In this example, we perform a color conversion from UYVY to RGBp. + +\code + // create the nodes (will implicitly map to other cores) + pNodes = DVP_KernelNode_Alloc(hDVP, numNodes); + + // define the kernel to be invoked by this node + pNodes[0].header.kernel = DVP_KN_UYVY_TO_RGBp; + // assign the image metadata to the node + // (only the metadata is copied, not the images themselves) + io = dvp_knode_to(&pNodes[0],DVP_Transform_t); + DVP_Image_Dup(&io->input, &images[0]); + DVP_Image_Dup(&io->output, &images[1]); +\endcode + +\section howto_assign_core_affinity How To Assign Core Affinity + +The core affinity may be defined per node. Once a +node is declared and defined, the affinity attribute of it's header +(\ref DVP_KernelNodeHeader_t::affinity) can be used to indicate which core the +node should execute on. + +\code + pNodes[0].header.affinity = DVP_CORE_CPU; +\endcode + +\section howto_create_a_graph How To Create A Kernel Graph + +This is how to allocate a graph and set the nodes to be executed in the graph. + +\code + // create the graph with 1 section + graph = DVP_KernelGraph_Alloc(hDVP, 1); + + // initialize the zero-th section to the single node + DVP_KernelGraphSection_Init(hDVP, graph, 0, pNodes, numNodes); +\endcode + +\section howto_process_graph How To Process a Graph without callbacks. + +\code + // process the graph + DVP_KernelGraph_Process(hDVP, graph, NULL, NULL); +\endcode + +\section howto_process_graph How To Process a Graph with a Section Callback + +This requires a pre-defined callback function with conforms to \ref +DVP_SectionComplete_f. + +\code +static void dvp_section_complete(void *cookie, DVP_KernelGraph_t *graph, DVP_U32 sectionIndex, DVP_U32 nne) +{ + // do work. +} +\endcode + +Then during the process call this function will be called after every section +completes. + +\code + ... + // process the graph + DVP_KernelGraph_Process(hDVP, graph, cookie, dvp_section_complete); +\endcode + +\section howto_query_remote_cores How To Query State of Remote Cores + +Following snippet shows how to determine which one of the remote cores are +enabled. + +\code + DVP_U32 c = 0; + DVP_U32 numCoresEnabled = 0; + DVP_CoreInfo_t cores; + // Initialize our sample Kernel Graph + DVP_Handle dvp = DVP_KernelGraph_Init(); + memset(cores, 0, sizeof(cores)); + // query the system + DVP_QuerySystem(dvp, cores); + for (c = 0; c < DVP_CORE_MAX; c++) + { + if (cores[c].enabled) + { + status = STATUS_SUCCESS; + numCoresEnabled++; + } + } + DVP_PRINT(DVP_ZONE_ALWAYS, "%u cores enabled!\n", numCoresEnabled); + DVP_KernelGraph_Deinit(dvp); +\endcode + +\section howto_minimize_ipc_latency How To Minimize IPC Latency + +\todo Add comments on multi-node transactions and setting appropriate cache +operations. + +\code + images[X].skipCacheOpFlush = DVP_TRUE; + or + images[X].skipCacheOpInval = DVP_TRUE; +\endcode + + +*/ diff --git a/docs/dvp_implementation.txt b/docs/dvp_implementation.txt new file mode 100644 index 0000000..d1369d4 --- /dev/null +++ b/docs/dvp_implementation.txt @@ -0,0 +1,36 @@ +/*! +\page page_implementation Implementation Details + + \section languages Languages + +DVP is implemented in C with some C99 extensions. GCC and Microsoft's CL +compiler can both compile the majority of DVP. DVP does contain some NEON ARM +assembly (see Writing ARM Assembly) which is in the AT&T assembly style. + +DVP contains other components which are implemented in C++ (VisionCam/ +VisionEngine). These are convenience classes used to simplify usage of DVP +within a HLOS environment. + + \section supported_hlos Supported HLOS + +- Froyo, Gingerbread, IceCreamSandwich Android - using Android makefiles. +- QNX - using Concerto +- Ubuntu Linux - "Host" Build where the reference "C" versions of the kernels +are used. Using Concerto build. +- Windows NT - "Host" Build where the reference "C" versions of the kernels are +used. Using Concerto build. + + \section android_specific Android Specific Issues + +-# Android Froyo/Gingerbread/ICS do not support a generic shmget (shared memory +allocation) and thus a "work-around" was used which allows multiple DVP +clients to allocate from a shared memory area via a native system service, " +shm_service" which is implemented in the SOSAL. +-# Android does not allow access to the OMX-CAMERA unless you are a "root" +privileged process (due to the need to read DCC files which are marked as +root privilege). +-# Once you access the OMX-CAMERA in root mode, you need a Binder interface for +callers to use to access your Daemon's features. + +*/ + diff --git a/docs/dvp_intro.txt b/docs/dvp_intro.txt new file mode 100644 index 0000000..fc11c77 --- /dev/null +++ b/docs/dvp_intro.txt @@ -0,0 +1,9 @@ +/*! +\page page_introduction Introduction + + Distributed Vision Processing (DVP) is a framework developed by Texas Instruments that provides an API for + clients to construct and call processing graphs of supported low-level vision and imaging functions. + These functions (better known as kernels) are processed using optimized libraries on one of the SoC's supported + cores. On OMAP4, DVP can process libraries on the SIMCOP, DSP, or Cortex A9/Neon. + + */ diff --git a/docs/dvp_kernel_page.txt b/docs/dvp_kernel_page.txt new file mode 100644 index 0000000..d3dfd63 --- /dev/null +++ b/docs/dvp_kernel_page.txt @@ -0,0 +1,15 @@ +/*! \page kernel_page Supported Kernels + + \section kernel_enums Kernel Descriptions + When configuring a kernel node of type DVP_KernelNode_t, the data type used to reference the DVP_KernelNode_t::data object needs to coorespond to the DVP_KernelNode_t::header.kernel enumeration chosen.\n + The \ref DVP_KernelNode_e enumeration lists the following information for each kernel: + - Brief descriptions of each supported DVP kernel (function) + - The cooresponding data type to cast the DVP_KernelNode_t::data object + - The cores currently supported\n + + This list can be extended to support custom kernels as directed in \ref + page_extending_dvp. + +*/ + + diff --git a/docs/dvp_memory.txt b/docs/dvp_memory.txt new file mode 100644 index 0000000..625cf73 --- /dev/null +++ b/docs/dvp_memory.txt @@ -0,0 +1,36 @@ + +/*! \page page_memory Memory Allocation And Usage + +DVP allows the programmer to allocate memory in many formats, depending on +the local HLOS. When DVP is running on a system with a TILER, DVP can +allocate 1D cached and 1D uncached and 2D uncached tiled memory. Normally +most allocations are allocated via malloc, calloc or memalign. The RPC layer +of DVP understands the Cache issues associated with remote core execution and +works to keep buffers consistent after Section executions. + + \section sec_supported_memory Supported Memory Types + +DVP supports multiple memory types for Images and Buffers. +Plain Virtual Memory +- 1D TILER Cached Memory +- 1D TILER Uncached Memory +- 2D TILER Uncached Memory +- Diplay Buffers (2D TILER Uncached) Memory + +On systems where the TILER API is exposed to DVP directly it will use it to +allocate 1D/2D memory. On Host systems, only plain virtual memory is supported. + +To specify the desired memory allocation, you provide the \ref DVP_MemType_e +along with the \ref DVP_Image_Alloc function. + +\code + +DVP_Image_t image; + +DVP_Image_Init(&image, 640, 480, FOURCC_UYVY); +DVP_Image_Alloc(hDVP, &image, DVP_MTYPE_MPUCACHED_1DTILED); + +\endcode + +*/ + diff --git a/docs/dvp_ndk.txt b/docs/dvp_ndk.txt new file mode 100644 index 0000000..7910dd4 --- /dev/null +++ b/docs/dvp_ndk.txt @@ -0,0 +1,14 @@ +/*! \page page_version DVP Android NDK + + + This NDK package includes the public API, documentation, and examples for Texas Instruments + Distributed Vision Processing (DVP) framework which were compiled against the + Google Android NDK. + + \version VERSION + \date DATE + + \todo How to link against the DVP NDK + +*/ + diff --git a/docs/dvp_other_components.txt b/docs/dvp_other_components.txt new file mode 100644 index 0000000..84295a9 --- /dev/null +++ b/docs/dvp_other_components.txt @@ -0,0 +1,46 @@ +/*! \page page_components Other Components + + \section sosal Simple OS Abstraction Layer (SOSAL) +SOSAL is a simple operating system abstraction layer plus design pattern +library which allow for rapid development. It contains: + +- OS: Threads, Mutex, Semaphore, Events, Sockets +- Patterns: List, Hash, Queue, Ring Buffer, RPC over Sockets + + \section display Display +Display, in this context, is a critical component which allows for programmers +to see the images coming from either the camera or the output from kernels. +Supported Display Techs are: + +- V4L2 (Output) +- LibScreen +- GTK + + \section visioncam Vision Camera (VisionCam) + +VisionCam is a C++ Wrapper around the OMX-Camera interface which aims to +simplify the OMX interface down to the bare-minimum needed to enable +Machine Vision applications. + + \subsection subclasses Subclasses +VisionCam has several subclasses which allow for various stages of development +. They include: + +- UVCVisionCam - wraps the V4L2 capture interface for USB Video Camera (UVC) +drivers on Ubuntu PCs. This is used for early development. +- SocketVisionCam - exposes the VisionCam interface over RPC over Sockets to +the Host PC (Ubuntu or Windows). This is used for later develop which still +relies on PC code. +- OMXVisionCam - on production OMAP code bases it uses the OMX-Camera interface. +- FileVisionCam - wraps read RAW image data from a file, either an .avi or .yuv +/.rgb file. Used for testing. + + \section visionengine VisionEngine + +VisionEngine is a utility C++ class used to implement Machine Vision +applications which contain a thread and/or a reference to VisionCam and DVP. It +can construct and run a single DVP Kernel Graph with any number of sections/ +nodes/images + +*/ + diff --git a/docs/dvp_releasenotes.txt b/docs/dvp_releasenotes.txt new file mode 100644 index 0000000..0a0954d --- /dev/null +++ b/docs/dvp_releasenotes.txt @@ -0,0 +1,16 @@ +/*! +\page page_releasenotes Release Notes + +\section sec_r204 RLS_2.04 +Current Release + +\subsection sec_r204_limit Limitations + +No known limitations. + +\subsection sec_r204_ki Known Issues + +No known issues. + +*/ + diff --git a/docs/dvp_sdk.txt b/docs/dvp_sdk.txt new file mode 100644 index 0000000..43769a3 --- /dev/null +++ b/docs/dvp_sdk.txt @@ -0,0 +1,12 @@ +/*! \page page_version DVP SDK + + + This SDK includes public API, documentation, and examples on Texas Instruments + Distributed Vision Processing (DVP) framework. + + + \version RLS_2.04-53-g45d5072-dirty + \date DATE + +*/ + diff --git a/docs/dvp_supported_alg_libs.txt b/docs/dvp_supported_alg_libs.txt new file mode 100644 index 0000000..3a9af3b --- /dev/null +++ b/docs/dvp_supported_alg_libs.txt @@ -0,0 +1,23 @@ +/*! \page supported_algorithms Supported Algorithm Libraries + +Following algorithms are largely from the Machine Vision Algorithms. Currently DVP has several +TI proprietary algorithm kernels which it uses. + +- VLIB (Vision Library) - a collection of computer vision kernels that have been developed by and optimized for TI's media processors. +- RVM (Rear View Module) - Homography Transforms. +- TISMO (TI Stereo Module) - a method to generate a depth map from 2 simple cameras. +- IMGLIB (Image Library) - a collection of more than 70 image processing kernels +optimized for TI's DSP that can be used for image and video processing applications. The rich set of software routines +included in IMGLIB perform image processing functionalities including compression/decompression, image analysis, image filtering, and format +conversion. +- VRUN (Video/Image Coproc)- a subset of VLIB and IMGLIB ported to iMX. +- ORB - an efficient alternative to SIFT or SURF based on BRIEF and FAST. + +DVP also has some algorithm kernels which will be released "openly" with DVP. +- \subpage page_yuv - a set of NEON accelerated image processing functions. +- \subpage page_imgfilter - a 3x3 image convolution library written in NEON. +- \subpage page_ocl - a set of OpenCL kernels which implement a 3x3 image convolution. (Only +available on OpenCL enabled platforms). + +*/ + diff --git a/docs/dvp_testcase.txt b/docs/dvp_testcase.txt new file mode 100644 index 0000000..48d0505 --- /dev/null +++ b/docs/dvp_testcase.txt @@ -0,0 +1,88 @@ +/*! +\page page_testcase Testing + +\section sec_tests Supported Tests + +The follow tests are not strictly examples of how to use DVP as they may cover +failure modes and engaging in robustness testing. They are mentioned here as +they may help developers and users understand how to use DVP. + +- \subpage dvp_unittest - A framework test which covers basic API +operations and framework unit tests. +- \subpage dvp_kr_test - Kernel Regression Tests. Contains examples for configuring every kernel that +is currently supported within DVP. + +*/ +//----------------------------------------------------------------------------- +/*! + +\page dvp_unittest dvp_unittest: The Framework Unit Tests + +The DVP unit test is just a series of frameworking tests to flush out the +API on a given platform. + +\section dvp_unittest_usage Usage + +\code +$ dvp_unittest +\endcode + +\see \ref group_tests + +\include dvp_unittest.c + + +*/ +//----------------------------------------------------------------------------- +/*! + +\page dvp_kr_test dvp_test: The Kernel Regression Tests + + +The dvp_test is a command-line unit test that receives input from VisionCam +(FileVisionCam or OMXVisionCam) and calls specified pre-configured DVP kernel +graphs for each camera frame (defined in TestVisionEngine.cpp in the same directory). + +\section dvp_test_purpose Purpose +- This test is what is used for validating all the kernels from DVP API. +- Can be used to profile kernels on different cores by changing the affinity. +- Can be extended to add and test custom kernels implemented on the A9 or DSP. + +\section dvp_test_usage Usage +Since this test is expected to use input and output files on the file system, it should +be executed from the /sdcard directory on the file system. It is expecting the input +files to be in the /sdcard/raw folder, which is also where it puts the output files. +The input/output file naming convention is expected to be pYUV player compliant.\n\n +\a dvp_test \ \ \ \ \ +\ \ \\n +- \b input: If using the camera input, then this should be "OMX". If reading from a +file input, then this should be the unique string at the beginning of the pYUV player- +complient file name (before the _x_ portion of the file name. +- \b width: The width in pixels of the input image +- \b height: The height of the input image +- \b frame_rate: The frame rate of the input image +- \b color: The color of the input image (must be "UYVY") +- \b num_frames: The number of frames to process +- \b graph: The graph number to process (see the enum \ref TI_GraphType_e) +- \b core affinity: Optional parameter for graphs which support core affinity: cpu, dsp, simcop, or gpu + +Examples: +\par cd sdcard && dvp_test OMX 320 240 30 UYVY 200 3 +This will configure the OMX camera to provide 200 frames of 320x240 resolution +video of UYVY 422 format at 30 frames per second. Then the TI_GRAPH_TYPE_TEST1 graph +setup will be run on this video, placing the output files in the /sdcard/raw directory. +\par cd sdcard && dvp_test handqqvga 160 120 30 UYVY 10 7 +This will try to open the /sdcard/raw/handqqvga_160x120_30Hz_UYVY.yuv file, and read +10 frames into the TI_GRAPH_TYPE_TEST5 grapsh setup, placing the output files in the /sdcard/raw directory. +If the file is not found, then the test will print a warning, and send gray frames. + +\section dvp_test_code Source +\include dvp_test.cpp +\include TestVisionEngine.cpp + + + + + +*/ + diff --git a/docs/dvp_user_guide.txt b/docs/dvp_user_guide.txt new file mode 100644 index 0000000..0fd0a4a --- /dev/null +++ b/docs/dvp_user_guide.txt @@ -0,0 +1,23 @@ +/*! +\mainpage User's Guide + +This is the User's Guide to learning and understanding DVP. + +\tableofcontents + +- \subpage page_introduction +- \subpage page_version +- \subpage page_releasenotes +- \subpage page_arch_overview +- \subpage page_design_rationale +- \subpage page_memory +- \subpage page_components +- \subpage page_datapath +- \subpage page_callsequences +- \subpage page_debug +- \subpage page_examples +- \subpage page_extending_dvp +- \subpage kernel_page + +*/ + diff --git a/docs/full/Doxyfile b/docs/full/Doxyfile new file mode 100644 index 0000000..f877397 --- /dev/null +++ b/docs/full/Doxyfile @@ -0,0 +1,1835 @@ +# Doxyfile 1.8.0-20120429 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = "Distributed Vision Processing (DVP)" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 2.04 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = docs/images/ti_stk_2c_pos_rgb_png.png + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = docs/full + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = YES + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = aidl=JAVA + +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = YES + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = YES + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = YES + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = YES + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = YES + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 28 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = source/ \ + include/ \ + libraries/ \ + docs/dvp_dev_guide.txt \ + docs/dvp_intro.txt \ + docs/dvp_sdk.txt \ + docs/dvp_arch.txt \ + docs/dvp_releasenotes.txt \ + docs/dvp_design.txt \ + docs/dvp_depend.txt \ + docs/dvp_datapath.txt \ + docs/dvp_callsequence.txt \ + docs/dvp_implementation.txt \ + docs/dvp_supported_alg_libs.txt \ + docs/dvp_other_components.txt \ + docs/dvp_memory.txt \ + docs/dvp_kernel_page.txt \ + docs/dvp_examples.txt \ + docs/dvp_extending.txt \ + docs/dvp_kernel_autogen.txt \ + docs/dvp_debugging.txt \ + docs/dvp_testcase.txt \ + docs/dvp_how_to_guide.txt + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.c \ + *.h \ + *.cpp \ + *.aidl \ + *.java + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = source/dvp/dvp_test/ \ + source/dvp/dvp_demo/ + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = docs/images + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# style sheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 205 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 98 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. +# However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = YES + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = POSIX \ + ARCH_32 \ + ANDROID \ + LINUX \ + DVP_USE_IPC \ + DVP_USE_ION \ + DVP_USE_SHARED_T \ + GCAM_CALLER_RETURNFRAME \ + DVP_TARGET_ARM \ + DVP_USE_YUV \ + DVP_USE_OCL \ + DVP_USE_IMGFILTER \ + DVP_DEBUG=2 \ + SOSAL_USE_ION \ + SOSAL_USE_SHARED_T \ + SOSAL_DEBUG=2 + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 8 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = FreeSans.ttf + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = NO + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = YES + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# managable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS = 10 + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = YES + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = docs/dot + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = docs/msc + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/docs/full/concerto.mak b/docs/full/concerto.mak new file mode 100644 index 0000000..6e3fe69 --- /dev/null +++ b/docs/full/concerto.mak @@ -0,0 +1,9 @@ + +include $(PRELUDE) + +TARGET=dvp_full +TARGETTYPE=doxygen +DOXYFILE=Doxyfile + +include $(FINALE) + diff --git a/docs/images/dvp_simple_graph.jpg b/docs/images/dvp_simple_graph.jpg new file mode 100644 index 0000000..683db11 Binary files /dev/null and b/docs/images/dvp_simple_graph.jpg differ diff --git a/docs/images/ti_stk_2c_pos_rgb_png.png b/docs/images/ti_stk_2c_pos_rgb_png.png new file mode 100644 index 0000000..4489146 Binary files /dev/null and b/docs/images/ti_stk_2c_pos_rgb_png.png differ diff --git a/docs/msc/callgraph.msc b/docs/msc/callgraph.msc new file mode 100644 index 0000000..492eeb5 --- /dev/null +++ b/docs/msc/callgraph.msc @@ -0,0 +1,63 @@ +msc { + hscale=2; + + a [label="DVP API"], b [label="DVP Boss"], c [label="DVP KGM DSP Proxy"], d [label="OMAPRPC"], e [label="rpmsg"], f [label="ServiceMgr"], g [label="OMAP RPC Task"], h [label="DVP_KGM_DSP"], i [label="VLIB"]; + + ... [label="Boot-time"]; + f <= g [label="createChanel()"]; + d <= f [label="probe(omaprpc)"]; + d => g [label="request name"]; + d <= g [label="dvp_kgm_dsp"]; + d <= d [label="mknod dvp_kgm_dsp"]; + ---; + ... [label="Use case Initializes"]; + a => b [label="Boss Initialize"]; + b => c [label="Manager Load and Initialize"]; + c => d [label="open(/dev/dvp_kgm_dsp)"]; + d => g [label="msg(connect)"]; + d <= g [label="msg(connected)"]; + c <= d [label="return"]; + c => d [label="call(Initialize)"]; + d => g [label="msg(function 0)"]; + g => h [label="DVP_KGM_DSP Initialize"]; + g <= h [label="return"]; + d <= g [label="msg(function 0 status)"]; + c <= d [label="return"]; + b <= c [label="Manager Initialized"]; + a <= b [label="Boss Initialized"]; + ---; + ... [label="Use case processing"]; + a => b [label="Process Graph"]; + b => c [label="Process Nodes[x..z]"]; + c => d [label="call(Process, nodes[x..z])"]; + d => g [label="msg(function 1, params)"]; + g => h [label="DVP_KGM_DSP Process(Nodes[x..z])"]; + h => i [label="KernelX()"]; + h <= i [label="return"]; + h => i [label="KernelY()"]; + h <= i [label="return"]; + h => i [label="KernelZ()"]; + h <= i [label="return"]; + g <= h [label="return"]; + d <= g [label="msg(function 1, status)"]; + c <= d [label="return"]; + b <= c [label="3 Nodes Completed"]; + b >> b [label="Graph runs to completion"]; + ---; + ... [label="Use case teardown"]; + a => b [label="Boss Deinitialize"]; + b => c [label="Manager Deinitialize"]; + c => d [label="call(Deinitialize)"]; + d => g [label="msg(function 2)"]; + g => h [label="DVP_KGM_DSP Deinitialize"]; + g <= h [label="return"]; + d <= g [label="msg(function 2 status)"]; + c <= d [label="return from call()"]; + c => d [label="close()"]; + d => g [label="msg(disconnect)"]; + d <= g [label="msg(disconnected)"]; + c <= d [label="return"]; + b <= c [label="Manager Deinitialized and Unloaded"]; + a <= b [label="return"]; + +} diff --git a/docs/ndk/Doxyfile b/docs/ndk/Doxyfile new file mode 100644 index 0000000..5f72b2d --- /dev/null +++ b/docs/ndk/Doxyfile @@ -0,0 +1,1827 @@ +# Doxyfile 1.8.0-20120429 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = "Texas Instruments Distributed Vision Processing (DVP)" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 2.02 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "A distributed computation environment for Computer Vision on OMAP" + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = docs/images/ti_om_2c_pos_rgb_png_200.png + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = docs/ndk + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = YES + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = aidl=JAVA + +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = YES + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = YES + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = YES + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = YES + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = YES + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 28 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = include/dvp/ \ + include/sosal/ \ + docs/dvp_ndk.txt \ + docs/dvp_design_and_implementation.txt \ + docs/dvp_supported_alg_libs.txt \ + docs/dvp_other_components.txt \ + docs/dvp_memory.txt \ + docs/dvp_kernel_page.txt \ + docs/dvp_examples.txt \ + docs/dvp_extending.txt \ + docs/dvp_kernel_autogen.txt \ + docs/articles.txt + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.c \ + *.h \ + *.cpp \ + *.aidl \ + *.java + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = Vision*.h + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = source/dvp/dvp_test/ \ + source/dvp/dvp_demo/ + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = docs/images + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# style sheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 205 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 98 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. +# However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = YES + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = POSIX \ + ARCH_32 \ + ANDROID \ + ICS \ + LINUX \ + ARM \ + DVP_USE_IPC \ + DVP_USE_ION \ + DVP_USE_GRALLOC \ + GCAM_CALLER_RETURNFRAME \ + DVP_TARGET_ARM \ + DVP_USE_YUV \ + DVP_USE_OCL \ + DVP_USE_IMGFILTER \ + SOSAL_DEBUG=2 \ + SOSAL_ZONE_MASK=0x3 \ + DVP_DEBUG=2 \ + DVP_ZONE_MASK=0x3 \ + __cplusplus + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = docs/msc + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 8 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = FreeSans.ttf + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = NO + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = YES + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# managable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS = 10 + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = YES + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = docs/dot + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/docs/ndk/concerto.mak b/docs/ndk/concerto.mak new file mode 100644 index 0000000..6e3fe69 --- /dev/null +++ b/docs/ndk/concerto.mak @@ -0,0 +1,9 @@ + +include $(PRELUDE) + +TARGET=dvp_full +TARGETTYPE=doxygen +DOXYFILE=Doxyfile + +include $(FINALE) + diff --git a/include/dvp/ImageDebugging.h b/include/dvp/ImageDebugging.h new file mode 100644 index 0000000..c4cde41 --- /dev/null +++ b/include/dvp/ImageDebugging.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IMAGE_DEBUGGING_H_ +#define _IMAGE_DEBUGGING_H_ + +#include + +/*! The structure used to track image debugging information + * \ingroup group_debugging + */ +typedef struct _image_debug_t { + char filename[MAX_PATH]; /**< The name of the debug file */ +#if defined(DVP_USE_FS) + FILE *debug; /**< Used to maintain a debug file output of this image */ +#endif + DVP_Image_t *pImg; + DVP_Buffer_t *pBuf; +} ImageDebug_t; + +#ifdef __cplusplus +extern "C" { +#endif + + +/*! \brief Used to initialize an image debugging structure + * \ingroup group_debugging + */ +void ImageDebug_Init(ImageDebug_t *pImgd, DVP_Image_t *pImage, const char *path, const char *name); + +/*! \brief Used to initialize a buffer debugging structure + * \ingroup group_debugging + */ +void BufferDebug_Init(ImageDebug_t *pImgd, DVP_Buffer_t *pBuffer, const char *path, const char *name, const char *ext); + +/*! \brief Used to open the files associated with the image debugging structure. + * \ingroup group_debugging + */ +void ImageDebug_Open(ImageDebug_t *pImgd, DVP_U32 numImg); + +/*! \brief Used to write the current frame out to the file. + * \ingroup group_debugging + */ +void ImageDebug_Write(ImageDebug_t *pImgd, DVP_U32 numImg); + +/*! \brief Used to close the file and deinitialize an image debugging structure + * \ingroup group_debugging + */ +void ImageDebug_Close(ImageDebug_t *pImgd, DVP_U32 numImg); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/include/dvp/VisionCam.h b/include/dvp/VisionCam.h new file mode 100644 index 0000000..d776b0e --- /dev/null +++ b/include/dvp/VisionCam.h @@ -0,0 +1,1191 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _VISION_CAM_H_ +#define _VISION_CAM_H_ + +#include +#include +#include + +#ifdef EXPORTED_3A +#include +#endif // EXPORTED_3A + +/** MAX_FACES_COUNT + * + * Maximum number of face coordinates + * that face detect algorithm can output. +*/ +const uint32_t MAX_FACES_COUNT = 35; + +/** VCAM_NUM_BUFFERS + * + * The maximum number of buffers that + * VisionCam would be able to operate with. +*/ +const uint32_t VCAM_NUM_BUFFERS = 8; + +#if (TARGET_BOARD_PLATFORM == omap4) +/** Maximum supported camera number. +*/ +const int32_t VCAM_Max_Supported_Sensor_Count = 3; +#elif (TARGET_BOARD_PLATFORM == omap5) +/** Maximum supported camera number. +*/ +const int32_t VCAM_Max_Supported_Sensor_Count = 4; +#endif + +#define VCAM_DO_IF_FAILED(ret, statement, action) {\ + ret = statement;\ + if (STATUS_FAILED(ret)) { \ + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: VCAM Failure %d in function %s on file:line %s:%u\n", ret, __FUNCTION__, __FILE__, __LINE__);\ + action;\ + }\ +} + +#define VCAM_BREAK_IF_FAILED(ret, statement) VCAM_DO_IF_FAILED(ret, statement, break) +#define VCAM_RETURN_IF_FAILED(ret, statement) VCAM_DO_IF_FAILED(ret, statement, return ret) +#define VCAM_CONTINUE_IF_FAILED(ret, statement) VCAM_DO_IF_FAILED(ret, statement, continue) +#define VCAM_COMPLAIN_IF_FAILED(ret, statement) VCAM_DO_IF_FAILED(ret, statement, ) +#define VCAM_GOTO_IF_FAILED(ret, statement, label) VCAM_DO_IF_FAILED(ret, statement, goto label) + +#define TIME_PROFILE 0 + +/** @enum VisionCamCmd_e + * + * Enumeration containing the all valid commands + * that could be accepted by VisionCam. + * @see VisionCam::sendCommand(). +*/ +typedef enum _vcam_cmds_e +{ + VCAM_CMD_PREVIEW_START = 0, /**< Start preview command. */ + VCAM_CMD_PREVIEW_STOP, /**< Stop preview command. */ + VCAM_EXTRA_DATA_START, /**< Enable transfering of e certain image meta data type. + @see VisionCamExtraDataType_e. + */ + + VCAM_EXTRA_DATA_STOP, /**< Disable transfering of e certain image meta data type. + @see VisionCamExtraDataType_e. + */ + + VCAM_CMD_LOCK_AWB, /**< Lock of auto white balance coeficients. */ + VCAM_CMD_LOCK_AE, /**< Lock exposure */ + VCAM_CMD_QUIT, /**< */ +#if TIME_PROFILE + VCAM_DUMP_TIMES, /**< Performance measurment option. */ +#endif + VCAM_CMD_FACE_DETECTION, /**< Enable/Disable face detection algo. + @see bool_e + */ + + VCAM_CMD_FREEZE_AWB_PARAMS, /**< Freeze white balance parameters aliance. + Auto white balance algorithm continues to work but its output is not applied, + for a certain amount of time. + After this time expires WB parameter are immediately set to the most recent calculated. + A pointer to an unsigned integer representing a time in millseconds. + Minimum freeze time is 0 and maximum 10000. + */ + + VCAM_CMD_FREEZE_AGC_PARAMS, /**< Freeze exposure algorithm aliance. + Auto white balance alorythm continues to work but its output is not applied, + for a certain amount of time. + After this time expires WB parameter are imediately set so the most recent calculated. + A pointer to an unsigned integer representing a time in millseconds. + Minimum freeze time is 0 and maximum 10000. + */ + + VCAM_CMD_SET_CLIENT_NOTIFICATION_CALLBACK, /**< Set client notification handler. + @see VisionCamClientNotifierCallback + */ + VCAM_CMD_PACK_FRAMES, /**< Enables frame packing. + In cases when more than one frame sources are selected + (for example preiew and video port in OMX camera) this option ensures that + the frames from all sources will be passed to VisionCam client + in a single call to its preview callback. + @see VisionCamFramePack + */ + VCAM_CMD_FACE_DETECTION_RAW, + + VCAM_CMD_MAX +} VisionCamCmd_e; + +/** @enum VisionCamParam_e +* +* Enumeration listing possible camera parameters. +* These values are passed to VisionCam::setParameter(). +* @see VisionCam::setParameter(). +*/ +typedef enum _vcam_params_e +{ + VCAM_PARAM_MIN = 0x7F000001, /**< To avoid collisions with VisionCamCmd_e. */ + + VCAM_PARAM_DO_AUTOFOCUS, /**< Start auto focus of a given type @see VisionCamFocusMode. */ + VCAM_PARAM_DO_MANUALFOCUS, /**< Start manual focus; a value representing + focal distance must be passed. */ + + VCAM_PARAM_CONTRAST, /**< Set the contrast parameter; a value, + in the range of -100 to 100 must be passed. */ + + VCAM_PARAM_SHARPNESS, /**< Set the sharpness parameter; a value, + in the range of -100 to 100 must be passed. */ + + VCAM_PARAM_BRIGHTNESS, /**< Brighness parameter; a value, + in the range of 0 to 200 must be passed. */ + + VCAM_PARAM_SATURATION, /**< Saturation parameter; a value, + in the range of -100 to 100 must be passed. */ + + VCAM_PARAM_HEIGHT, /**< Preview frame height. + This will be applied before next start preview command. + If the buffers allocated, at the momonet of next preview start, are not + with corresponding dimensions, you might receive corrupted frames + or even memory corruptions may appear. + This option if not preffered since preview width and height are strongly dependent. + use VCAM_PARAM_RESOLUTION instead. + @see VCAM_PARAM_RESOLUTION . + */ + + VCAM_PARAM_WIDTH, /**< Preview frame width. + This will be applied before next start preview command. + If the buffers allocated, at the momonet of next preview start, do not + have corresponding dimensions, you might receive corrupted frames + or even memory corruptions may appear. + This option isn't preffered since preview width and height are strongly dependent to each other. + use VCAM_PARAM_RESOLUTION instead. + @see VCAM_PARAM_RESOLUTION . + */ + + VCAM_PARAM_FPS_FIXED, /**< Frame rate. */ + + VCAM_PARAM_FPS_VAR, /**< Set the variable frame rate. + A pointer to a structure of type VisionCamVarFramerateType must be passed + to specify minimum and maximum fps. + Variable frame rate means that fps is constantly recalculated + according to current light conditions. + @see VisionCamVarFramerateType . + */ + + VCAM_PARAM_COLOR_SPACE_FOURCC, /**< Color space that will be used. + This should match the color space option, + passed to buffer allocating API. + @see _fourcc + */ + + VCAM_PARAM_NAME, /**< When the input video is read from a file, this is the file name */ + + VCAM_PARAM_FLICKER, /**< Set flicker avoiding parameter. + @see VisionCamFlickerType . + */ + + VCAM_PARAM_CROP, /**< Crop option for preview frame. + @see VisionCamRectType . + */ + VCAM_PARAM_CAP_MODE, /**< Camera operating mode. + different operating modes provide different camera functionalities. + @see VisionCamCaptureMode . + */ + + VCAM_PARAM_SENSOR_SELECT, /**< Active camera. + This can be done either during preview or when preview is stopped. + @see VisionCamSensorSelection. + Where : + primary sensor: the sensor at the back of the device. + secondary sensor: the sensor at the front of the device (user facing sensor). + stereo sensor: in case of stereo camera presence; + this corresponds to the couple of sensors located at the same side. + */ + + VCAM_PARAM_EXPOSURE_COMPENSATION, /**< EV compensation measured in ISOs.*/ + + VCAM_PARAM_RESOLUTION, /**< Preview resolution. + This requires preview stop and reallocating the image buffers. + If preview is running: VisionCam::setParameter() retuns STATUS_INVALID_STATE. + A pointer to a value of VisionCamResolIdex type must be passed. + @see VisionCamResolIdex + @see VisionCamResolutions + @see VisionCamResType + */ + + VCAM_PARAM_MANUAL_EXPOSURE, /**< Manual exposure time. + This affects the frame rate. + A pointer to an unsigned integer value must be passed. + This value must be in the range of 30 to 100 + and represents the exposition time in milliseconds for each frame. + */ + + VCAM_PARAM_AWB_MODE, /**< White balance mode. + @see VisionCamWhiteBalType. + */ + + VCAM_PARAM_COLOR_TEMP, /**< Color temperature in Kelvins. */ + + VCAM_PARAM_EXPOSURE_ISO, /**< Exposure ISO. + An unsigned integer value, in the range of 100 to 800, must be passed. + */ + + VCAM_PARAM_WB_COLOR_GAINS, /**< White balance color gain manual control. + Refers to the color channels of a non-sompressed image. + This is specific setting, valid only in gesture operating modes: + VCAM_GESTURE_MODE and VCAM_STEREO_GEST_MODE (@see VisionCamCaptureMode). + @see VisionCamWhiteBalGains. + @note This functionallity might not be enabled for some devices. + */ + + VCAM_PARAM_GAMMA_TBLS, /**< 3A gamma table coefficients manual control. + This is specific setting, valid only in gesture operating modes: + VCAM_GESTURE_MODE and VCAM_STEREO_GEST_MODE (@see VisionCamCaptureMode). + @see VisionCamGammaTableType + */ + VCAM_PARAM_ROTATION, /**< Preview frame rotation. + Pointer to an unsigned integer value must be passed, + which will represent the degrees of rotation. + Possible values are: 0, 90, 180, 270 in degrees. + @see VisionCamRotation_e + */ + + VCAM_PARAM_MIRROR, /**< Sensor mirroring depending on the sensor, + this setting will provide HW or SW mirroring of the image. + @see VisionCamMirrorType + */ + + VCAM_PARAM_STEREO_INFO, /**< Stereo image layout and subsampling. + @see VisionCamStereoInfo + */ + + VCAM_PARAM_AWB_MIN_DELAY_TIME, /**< This will stop white balance algorithm for a certain period of time. + When this time expires, WB algorithm will start again and will smoothly + change WB parameters until they reach the values that suit to the light conditions. + Parameter is pointer to unsigned integer value, + which represents the delay time in millseconds. + */ + + VCAM_PARAM_GESTURES_INFO, /**< Notify the camera auto algorithms that a gesture is detected, and gives location + of the region of interest. + */ + + VCAM_PARAM_AGC_MIN_DELAY_TIME, /**< This will stop exposure gain recalculations for a certain period of time. + When this time expires, exposure algorithms will smooth + the light conditions. + Parameter is pointer to unsigned integer value, + which represents the delay time in millseconds. + */ + + VCAM_PARAM_AGC_LOW_TH, /**< Automatic gain control low threshold. + Pointer to an integer value must be passed. + Ragne is 0 - 10000. + */ + + VCAM_PARAM_AGC_HIGH_TH, /**< Automatic gain control high threshold. + Pointer to an integer value must be passed. + Ragne is 0 - 10000. + */ + + VCAM_PARAM_2DBUFFER_DIM, /**< Used to get buffer allocation information. + This information is limited to 2D buffer dimensions (width and height). + @see VisionCamResType + */ + + VCAM_PARAM_PATH, /**< + */ + VCAM_PARAM_EXPORTED_3A_HOLD, /**< + */ + + VCAM_PARAM_EXPORTED_3A_SET, /**< + */ + + VCAM_PARAM_EXPORTED_3A_APPLY, /**< + */ + + VCAM_PARAM_EXPORTED_3A_RESET, /**< + */ + + VCAM_PARAM_IMAGE_PYRAMID, /**< Set image pyramid levels and step. + A pointer to a structure of type VisionCamImagePyramidType must be passed + to specify the levels count and scaling factor for image pyramids. + @see VisionCamImagePyramidType. + */ + + VCAM_PARAM_MAX +} VisionCamParam_e; + +/** @enum VisionCamExtraDataType_e + * Defines which meta data type to be transferred. + * @see VCAM_EXTRA_DATA_START + * @see VCAM_EXTRA_DATA_STOP +*/ +typedef enum _vcam_extradatatypes_e +{ + VCAM_EXTRA_DATA_NONE = 0, +// VCAM_EXIF_ATTRIBUTES, + VCAM_ANCILLARY_DATA, + VCAM_WHITE_BALANCE, + VCAM_UNSATURATED_REGIONS, + VCAM_FACE_DETECTION, +// VCAM_BARCODE_DETECTION, +// VCAM_FRONT_OBJECT_DETECTION, +// VCAM_MOTION_ESTIMATION, + VCAM_MTIS_TYPE, +// VCAM_DISTANCE_ESTIMATION, + VCAM_HISTOGRAM, + VCAM_FOCUS_REGION, +// VCAM_EXTRA_DATA_PAN_AND_SCAN, +// VCAM_RAW_FORMAT, +// VCAM_SENSOR_TYPE, +// VCAM_SENSOR_CUSTOM_DATA_LENGTH, +// VCAM_SENSOR_CUSTOM_DATA, + VCAM_MANUAL_WHITE_BALANCE, + VCAM_FACE_DETECTION_RAW, + VCAM_HMS_GAMMA, + VCAM_IMAGE_PYRAMID, + + VCAM_EXTRA_DATA_TYPE_MAX +} VisionCamExtraDataType_e; + +/** @enum VisionCamFlickerType + * Possible flicker avoidance modes. + * @see VCAM_PARAM_FLICKER +*/ +typedef enum _flicker_type +{ + FLICKER_OFF, /**< No flicker correction. */ + FLICKER_AUTO, /**< Automatic flicker correction. */ + FLICKER_50Hz, /**< 50 Hz flicker correction. */ + FLICKER_60Hz, /**< 60 Hz flicker correction. */ + FLICKER_100Hz = FLICKER_50Hz, /**< 100 Hz flicker correction. */ + FLICKER_120Hz = FLICKER_60Hz, /**< 120 Hz flicker correction. */ + + FLICKER_MAX = 0X7fffffff +}VisionCamFlickerType; + +/** @enum VisionCamRotation_e + * Enumatarion that is used to configure + * HW rotation of preview frames. + * @see VCAM_PARAM_ROTATION +*/ +typedef enum _vcam_rotation_e { + VCAM_ROTATION_0 = 0, /**< No rotation. */ + VCAM_ROTATION_90 = 90, /**< Rotate 90 degrees right. */ + VCAM_ROTATION_180 = 180, /**< Rotate 180 degrees */ + VCAM_ROTATION_270 = 270 /**< Rotate 270 degrees right*/ +}VisionCamRotation_e; + +/** @enum VisionCamSensorSelection + * Defines different sensors. + * @see VCAM_PARAM_SENSOR_SELECT +*/ +typedef enum _sensor_selection +{ + VCAM_SENSOR_PRIMARY = 0, /**< Usually this is the sensor on the back of the device. */ + VCAM_SENSOR_SECONDARY = 1, /**< usually, this is the sensor at the front of the device. */ + VCAM_SENSOR_STEREO = 2, /**< In case os stereo cameras, this is stereo use case. */ + + VCAM_SENSOR_MAX = 0x7fffffff +}VisionCamSensorSelection; + +/** @enum VisionCamStereoLayout + * Defines possible stereo imaging layouts. + * @see VisionCamStereoInfo +*/ +typedef enum _stereo_layout +{ + VCAM_STEREO_LAYOUT_TOPBOTTOM, /**< Left and right frames are located one above the other. */ + VCAM_STEREO_LAYOUT_LEFTRIGHT, /**< Left and right frames are located next to each other. */ + + VCAM_STEREO_LAYOUT_MAX +} VisionCamStereoLayout; + +/** @enum VisionCamCaptureMode + * Defines possible camera operating modes. +*/ +typedef enum _capture_mode +{ + VCAM_VIDEO_NORMAL, /**< Normal vide processing pipe. */ + VCAM_VIDEO_HIGH_SPEED, /**< High speed video processing pipe. */ + VCAM_GESTURE_MODE, /**< Video pipe optimized for gesture computations. */ + VCAM_STEREO_MODE, /**< Normal stereo pipe. */ + VCAM_STEREO_GEST_MODE, /**< stereo pipe, optimized for gesture computations. */ +#if defined(__QNX__) + VCAM_VIEWFINDER_MODE, +#endif + VCAM_GESTURE_DUAL_SENSOR_MODE, + + VCAM_CAP_MODE_MAX +}VisionCamCaptureMode; + +/** @enum VisionCamGestureEvent_e + * Defines different gesture events. +*/ +typedef enum _vcam_gesture_event_e { + VCAM_GESTURE_EVENT_INVALID = 0, /**< No or invalid gesture event. Could also mean incompatible software version. */ + VCAM_GESTURE_EVENT_SWIPE_LEFT, /**< Swipe to the left. */ + VCAM_GESTURE_EVENT_SWIPE_RIGHT, /**< Swite to the right. */ + VCAM_GESTURE_EVENT_FIST_LEFT, /**< Fist turned to left. */ + VCAM_GESTURE_EVENT_FIST_RIGHT, /**< Fist turned to right. */ + + VCAM_GESTURE_EVENT_MAX, +} VisionCamGestureEvent_e; + +/** @enum VisionCamFocusMode + * Defines focus modes. +*/ +typedef enum _vcam_focus_mode +{ + VCAM_FOCUS_CONTROL_ON = 0, /**< Focus is enabled. */ + VCAM_FOCUS_CONTROL_OFF, /**< Focus is disabled. */ + VCAM_FOCUS_CONTROL_AUTO, /**< Continuous autofocus is enabled. */ + VCAM_FOCUS_CONTROL_AUTO_LOCK, /**< Single autoficus enabled - once fous position of lens is reached, focus algorithm stops. */ + /// TI extension follow + VCAM_FOCUS_CONTRO_AUTO_MACRO, /**< Auto focus in macro mode. */ + VCAM_FOCUS_CONTROL_AUTO_INFINITY, /**< Infinity focus mode. */ + VCAM_FOCUS_FACE_PRIORITY_MODE, /**< Emphasis of focus algorithm is the output of face detect. */ + VCAM_FOCUS_REGION_PRIORITY_MODE, /**< Focuses on given regions. */ + VCAM_FOCUS_CONTROL_HYPERFOCAL, /**< */ + VCAM_FOCUS_CONTROL_PORTRAIT, /**< */ + VCAM_FOCUS_CONTROL_EXTENDED, /**< */ + VCAM_FOCUS_CONTROL_CONTINOUS_NORMAL, /**< */ + VCAM_FOCUS_CONTROL_CONTINOUS_EXTENDED, /**< */ + VCAM_FOCUS_FACE_PRIORITY_CONTINOUS_MODE, /**< */ + VCAM_FOCUS_REGION_PRIORITY_CONTINOUS_MODE, /**< */ + VCAM_FOCUS_CONTROL_MAX +}VisionCamFocusMode; + +/** @struct VisionCamStereoInfo + * Configuration for stereo operating modes. +*/ +typedef struct _vcam_stereo_info_t { + VisionCamStereoLayout layout; /**< Stereo image layout: top bottom or side by side.*/ + uint32_t subsampling; /**< Set to 1 if you are setting your + dimensions manually to double to desire value. + Set to 2 if you want to compress the two images + into a normal image. + */ +} VisionCamStereoInfo; + +/** @enum VisionCamLockState + * Defines enable and disable modes used for variety of settings. +*/ +typedef enum _vcam_lock_state +{ + UNLOCKED = false_e, + LOCKED = true_e +}VisionCamLockState; + +/** @enum VisionCamResolIdex + * Defines VisionCam resolutions. + * @see VisionCamResolutions + * @see VisionCamResType +*/ +typedef enum _e_resol_index +{ + VCAM_RES_2MP = 0, /**< 1600 x 1200 pixels */ + VCAM_RES_1_25MP, /**< 1300 x 976 pixels */ + VCAM_RES_720p, /**< 1280 x 720 pixels */ + VCAM_RES_SVGA, /**< 800 x 480 pixels */ + VCAM_RES_D1PAL, /**< 720 x 576 pixels */ + VCAM_RES_D1NTSC, /**< 720 x 480 pixels */ + VCAM_RES_PAL, /**< 768 x 576 pixels */ + VCAM_RES_VGA, /**< 640 x 480 pixels */ + VCAM_RES_CIF, /**< 352 x 288 pixels */ + VCAM_RES_QVGA, /**< 320 x 240 pixels */ + VCAM_RES_QCIF, /**< 176 x 144 pixels */ + VCAM_RES_QQVGA, /**< 160 x 120 pixels */ + VCAM_RES_SQCIF, /**< 128 x 96 pixels */ + VCAM_RES_SXVGA, /**< 1280 x 960 pixels */ + + VCAM_RESOL_MAX +}VisionCamResolIdex; + +/** @struct VisionCamResType + * Packs resolution index and resolutin sizes for supported resolutins. + * @see VisionCamResolIdex +*/ +typedef struct _res_type +{ + VisionCamResolIdex mResIdx; /**< VisionCam defined resolution index. */ + uint32_t mWidth; /**< Width in pixels. */ + uint32_t mHeight;/**< Height in pixels. */ +}VisionCamResType; + +/** VisionCamResolutions[] + * Predefined resolution indexes and sizes. + * The only possible for VisionCam. +*/ +const VisionCamResType VisionCamResolutions[] = { + { VCAM_RES_2MP , 1600, 1200 }, + { VCAM_RES_1_25MP , 1300, 976 }, + { VCAM_RES_720p , 1280, 720 }, + { VCAM_RES_SVGA , 800 , 480 }, + { VCAM_RES_D1PAL , 720 , 576 }, + { VCAM_RES_D1NTSC , 720 , 480 }, + { VCAM_RES_PAL , 768 , 576 }, + { VCAM_RES_VGA , 640 , 480 }, + { VCAM_RES_CIF , 352 , 288 }, + { VCAM_RES_QVGA , 320 , 240 }, + { VCAM_RES_QCIF , 176 , 144 }, + { VCAM_RES_QQVGA , 160 , 120 }, + { VCAM_RES_SQCIF , 128 , 96 }, + { VCAM_RES_SXVGA , 1280, 960 } +}; + +/** @enum VisionCamObjectType + * Defines some gesture objects. + * These are not the only supported. +*/ +typedef enum _vcam_object_type { + VCAM_OBJECT_PALM, /**< Palm */ + VCAM_OBJECT_FIST, /**< Fist */ + VCAM_OBJECT_FACE, /**< Face */ + + VCAM_OBJECT_MAX +}VisionCamObjectType; + +/** @enum VisionCamWhiteBalType + * Defines different white balance modes used by VisionCam +*/ +typedef enum _vcam_white_bal_type { + VCAM_WHITE_BAL_CONTROL_OFF = 0, /**< White balance algorithm is turned off. */ + VCAM_WHITE_BAL_CONTROL_AUTO, /**< Automatic white balance. */ + VCAM_WHITE_BAL_CONTROL_SUNLIGHT, /**< WB optimized for sunny light conditions. */ + VCAM_WHITE_BAL_CONTROL_CLOUDY, /**< WB optimized for cloudy light conditions. */ + VCAM_WHITE_BAL_CONTROL_SHADE, /**< WB optimized for shaded light conditions. */ + VCAM_WHITE_BAL_CONTROL_TUNGSTEN, /**< WB optimized for tungsten (worm) light conditions. */ + VCAM_WHITE_BAL_CONTROL_FLUORESCENT, /**< WB optimized for flourescent light conditions. */ + VCAM_WHITE_BAL_CONTROL_INCANDESCENT, /**< WB optimized for incadescent (warm) light conditions. */ + VCAM_WHITE_BAL_CONTROL_FLASH, /**< WB optimized for camera flash. */ + VCAM_WHITE_BAL_CONTROL_HORIZON, /**< WB optimized for landscape sunny conditions.. */ + VCAM_WHITE_BAL_CONTROL_FACEPRIORITYMODE = 0X7F000001, + + VCAM_WHITE_BAL_CONTROL_MAX +}VisionCamWhiteBalType; + +/** @enum VisionCamMirrorType + * Mirroring of image in frame buffer. +*/ +typedef enum _vcam_mirror_type{ + VCAM_MIRROR_NONE, /**< No mirror applied. */ + VCAM_MIRROR_VERTICAL, /**< Mirror by vertical axis. */ + VCAM_MIRROR_HORIZONTAL, /**< Mirror by horizontal axis. */ + VCAM_MIRROR_BOTH, /**< Mirror by bith vertical and horizontal axis. */ + + VCAM_MIRROR_MAX +}VisionCamMirrorType; + +/** @enum VisionCamPort_e + * Defines different camera output ports. + * Sometimes useful as different ports may have different configurations, + * also every port outputs a separate image, so one could be used at one process, + * while another - on other process. + * @note Each frame from a port has a twin on another port. Use frame's timestamp to find the matchin one. + * All ports are synchronised so frames are ouput sequentally. + * Also note that video port is sending frames ONLY when a preview port is sending. +*/ +typedef enum _vision_cam_port_e { + VCAM_PORT_ALL = 0, /**< All port listed below. */ + VCAM_PORT_MIN, + VCAM_PORT_PREVIEW = VCAM_PORT_MIN, /**< Preview port. */ + VCAM_PORT_VIDEO, /**< Video port. */ + + VCAM_PORT_MAX, + VCAM_PORT_NUM = VCAM_PORT_MAX -1 +}VisionCamPort_e; + +/** @enum VCAM_HISTCOMPONENTTYPE + * Histogram types. + * @see VisionCamHistogram +*/ +typedef enum VCAM_HISTCOMPONENTTYPE { + VCAM_HISTCOMP_Y = 0, /**< Luminance histogram (Y) */ + VCAM_HISTCOMP_YLOG, /**< Logarithmic luminance histogram (Y)*/ + VCAM_HISTCOMP_R, /**< Red histogram component (R)*/ + VCAM_HISTCOMP_G, /**< Green histogram component (G)*/ + VCAM_HISTCOMP_B, /**< Blue histogram component (B)*/ + VCAM_HISTCOMP_Cb, /**< Chroma blue histogram component (Cb)*/ + VCAM_HISTCOMP_Cr, /**< Chroma red histogram component (Cr) */ + VCAM_HISTCOMP_32BIT_PATCH = 0x7FFFFFFF +}VCAM_HISTCOMPONENTTYPE; + + +/** @struct VisionCamWhiteBalGains + * Manual white balance gain structure. + * Contains gain for each color channel. + * @see VCAM_PARAM_WB_COLOR_GAINS +*/ +typedef struct _white_bal_gains_type{ + uint16_t mRed; /**< Red color channel. */ + uint16_t mGreen_r; /**< Difference between green and red color. */ + uint16_t mGreen_b; /**< Difference between green and blue color. */ + uint16_t mBlue; /**< Blue channel. */ +}VisionCamWhiteBalGains; + +/** @struct VisionCamAncillary + * Ancillary data type definition. +*/ +typedef struct _ancillary_type { + uint32_t nAncillaryDataVersion; /**< Version of the ancillary data definition implemented by the application in binary coded decimal format. */ + uint32_t nFrameNumber; /**< This is a free-running counter (wraps back to zero at overflow) that is applied to each frame from the sensor whether that frame is not sent or is sent in multiple formats to the host. */ + uint32_t nShotNumber; /**< Indicates the shot number in a multi-shot sequence, counting up from 1 */ + uint16_t nInputImageHeight; /**< Height in pixels of the input image (i.e. from sensor or video decoder) */ + uint16_t nInputImageWidth; /**< Width in pixels of the input image (i.e. from sensor or video decoder) */ + uint16_t nOutputImageHeight; /**< Height in pixels of the image sent to the host */ + uint16_t nOutputImageWidth; /**< Width in pixels of the image sent to the host */ + uint16_t nDigitalZoomFactor; /**< Digital zoom factor: 10 bits decimal, 6 bits fractional. + @note Note: When non-square pixels are sent to the host, as indicated by the pixel aspect ratio ancillary data fields, the digital zoom factor applies in the direction that is the lesser of the pixel aspect ratio fields. + */ + int16_t nCropCenterColumn; /**< Defines the center of cropped region with regard to full sensor field of view. All values are valid, 0x8000 is the left column and 0x7fff is the right column. 0 is the center column. This is effectively a percentage ranging between +/- 50% */ + int16_t nCropCenterRow; /**< Defines the center of cropped region with regard to full sensor field of view. All values are valid, 0x8000 is the top row and 0x7fff is the bottom row. 0 is the center row. This is effectively a percentage ranging between +/- 50%. */ + uint16_t nOpticalZoomValue; /**< Optical zoom factor: 4 bits decimal, 12 bits fractional */ + uint8_t nFlashConfiguration; /**< Number Logical Flash Sources – Maximum 4 logical Flashes. For each logical flash following two fields will be filled. */ + uint8_t nFlashUsage; /**< 1. Bit 0 and 1 (LSB) - Flash Light Type (00b = Not used; 01b = Xenon; 10b = LED; 11b = Other) + 2. Bits 2 and 3 – Flash Charging Status (00b = Not charging; 01b = Charging; 10b = Charged; 11b = Error) + 3. Bits 4 and 5 – Flash Strobe Detection ( 00b = Not supported; 01b = Reserved; 10b = Strobe return light not detected; 11b = Strobe return light detected) + 4. Bit 6 and 7 - Reserved1. Bit 0 and 1 (LSB) - Flash Light Type (00b = Not used; 01b = Xenon; 10b = LED; 11b = Other) + */ + uint32_t nFlashStatus; /**< 1.Bits 0 to 7 - Flash Mode (bit variable). Flash can support more than one mode. + Bit 0 = Capture Flash Mode + Bit 1 = Video Light (Torch) Mode + Bit 2 = Pre-flash Mode + Bit 3 = AF Assist Mode + Bit 4 = Privacy Light Mode + Bit 5 = Red-eye Reduction Mode + Bit 6 = Other Mode 1 + Bit 7 = Other Mode 2 + 2. Bits 8 to 23 - Flash Control Mode. 2bits/Flash Light Mode + 00b = Not used + 01b = Compulsory flash firing + 10b = Compulsory flash suppression + 11b = Auto + 3. Bits 24 to 31 - Flash Intensity + 0 = Flash did not fire + 1 = 255 - Flash Intensity or Flash Intensity Identifier1.Bits 0 to 7 - Flash + */ + uint8_t nAFStatus; /**< Auto Focus status + FAILED is a single bit independent of the other values. + + The other values are mutually exclusive + OFF=not present or N/A + LOCKED=manual + RUNNING=auto, active + FROZEN=suspended + */ + uint8_t nAWBStatus; /**< Auto White Balance status. See explanation in AF status. */ + uint8_t nAEStatus; /**< Auto Exposure status See explanation in AF status. */ + uint32_t nExposureTime; /**< Exposure time in microseconds. */ + uint16_t nEVCompensation; /**< Exposure compensation */ + uint8_t nDigitalGainValue; /**< Digital gain setting */ + uint8_t nAnalogGainValue; /**< Analog gain setting */ + uint16_t nCurrentISO; /**< ISO setting based on reference ISO */ + uint16_t nReferenceISO; /**< Reference ISO for the current sensor */ + uint8_t nApertureValue; /**< Aperture setting */ + uint8_t nPixelRange; /**< Indicates the range of pixel values */ + uint16_t nPixelAspectRatio; /**< Indicates the width corresponding to the aspect ratio (PAR) of the pixels (samples) in the frame to which this ancillary data is attached. The PAR always indicates the true PAR, unless otherwise indicated in the application-specific documentation. */ + uint8_t nCameraShake; /**< Indicates risk of camera shake. For instance, if exposure time is greater than 1/f but less than 2/f, camera shake can be considered MEDIUM_RISK. If exposure time is greater than 2/f, camera_shake can be considered a HIGH_RISK. */ + uint16_t nFocalDistance; /**< Distance in cm from the camera lens if possible (14 lsbs). Upper 2 msbs indicate if the lens is set to: infinity (’10), macro (’01), in between (’00), or moving for AF search (’11). */ + uint64_t nParameterChangeFlags; /**< A 32-bit bit mask where each bit represents a sub-set of parameters. A bit value of ‘0’ indicates that the associated parameter set did not change from the previous frame. A bit value of ‘1’ indicates that the parameter set has changed from the previous frame. + 0: SEN_EXPOSURE (sensor exp) + 1: SEN_GAIN (sensor gain ->analogue and digital are in the same field. + 2: LSC_2D (2d lsc) + 3: VLDC (Vertical Line Defect Correction) + 4: ISIF_GAIN + 5: H3A_WB + 6: FLASH + 7: ISP_NOISE_FILTER_1 (iss noise filter) + 8: GIC (green imbalance correction) + 9: CFA + 10: GBCE + 11: YUV444TO422 (yuv444 to 422) + 12: EDGE_ENH (Edge enhancement) + 13: CAR (chromatic aberration reduction) + 14: LSC_RAD (radial based one - useless) + 15: DFS (Dark frame subtract) + 16: DPC (defect pixel correction in ipipeif) + 17: DPCM + 18: LPF_H (Low pass filter params for Horizontal resizing) + 19: LPF_V (Low pass filter params for Vertical resizing) + 20: CLAMP (ISIF black clamp configuration) + 21: WB_GAINS (wb gains) + 22: GAMMA (Gamma) + 23: RGB2RGB_1 + 24: RGB2YUV + 25: 3D_LUT (3d lut) + 26: DPC LUT + 27: DPC OTF (in ipipe) + 28: RGB2RGB_2 (after gamma) + 29: ISP_NOISE_FILTER_2 (iss noise filter) + 30: CGS (Chroma gain suppression) + 31: IPIPE_IF_DPC1 (ISIF or VP) + 32: IPIPE_IF_DPC2 (from SDRAM) + 33-63: reserved + */ + uint8_t nNumFacesDetected; /**< When Face Detect is enabled, this contains the number of faces detected. When face detect is disabled, this number should be set to 0. */ + uint8_t nConvergenceMode; /**< Reserved for future usage. */ + uint8_t nConvergenceStatus; /**< Reserved for future usage. */ + uint8_t nDCCStatus; /**< Reserved for future usage. */ +}VisionCamAncillary; + +/** @struct VisionCamHistogram + * Histogram data type definition. +*/ +typedef struct _histogram_type{ + uint32_t nBins; /**< The number of bins in the histogram */ + VCAM_HISTCOMPONENTTYPE eComponentType; /**< Specifies the type of the histogram bins according to enum. + It can be selected to generate multiple component types, + then the extradata struct is repeated for each component type */ + uint32_t data[1]; +}VisionCamHistogram; + + +/** @struct VisionCamUnsaturatedRegions + * Unsaturated Regions data + * The extra data having unsaturated regions data is + * described with the following structure.. + */ +typedef struct unsaturated_regions_type { +uint16_t nPaxelsX; /**< The number of paxels in the horizontal direction */ +uint16_t nPaxelsY; /**< The number of paxels in the vertical direction */ +uint16_t data[1]; /**< the first value of an array of values that represent + the percentage of unsaturated pixels within the associated paxel */ +}VisionCamUnsaturatedRegions; + +/** @struct VisionCamMTIS + * MTIS Vendor Specific Motion estimation + * The extra data having MTIS motion estimation data is + * described with the following structure. + */ +typedef struct mtis_meta_data_type { + int32_t nMaxMVh; /**< The maximum MV for horizontal direction */ + int32_t nMaxMVv; /**< The maximum MV for vertical direction */ + uint16_t nMVRelY[9]; /**< The mask for MV reliability */ + uint16_t nMVRelX[9]; /**< The mask for MV reliability */ + int32_t nMVh[9]; /**< The MVs for horizontal direction */ + int32_t nMVv[9]; /**< The MVs for vertical direction */ +}VisionCamMTIS; + +/** @struct VisionCamFocusRegion + * For Extended Focus region Type - + */ +typedef struct focus_region_data_type { + int32_t nLeft; + int32_t nTop; + uint32_t nWidth; + uint32_t nHeight; +} VisionCamFocusRegion; + +typedef struct hms_gamma_data_type { + uint32_t nItems; /**< The number of bins in the histogram */ + uint8_t data[1]; +} VisionCamGamma; + +/** @struct VisionCamMetadata + * Image meta data type definition. +*/ +typedef struct _metadata_type { + VisionCamWhiteBalGains *mAutoWBGains; /**< Info about auto white balance algorithm output: color gains applied by AWB. */ + VisionCamWhiteBalGains *mManualWBGains; /**< Info about manual white balance algorithm : color gains applied by user. */ + VisionCamAncillary *mAncillary; /**< Ancillary data. */ + VisionCamHistogram *mHistogram2D; /**< Histogram data for 2D use cases. */ + VisionCamHistogram *mHistogramL; /**< Histogram data for left channel in case of stereoscopic use cases. */ + VisionCamHistogram *mHistogramR; /**< Histogram data for right channel in case of stereoscopic use cases. */ + + VisionCamGamma *mGamma2D; /**< Gamma data for 2D use cases. */ + VisionCamGamma *mGammaL; /**< Gamma data for left channel in case of stereoscopic use cases. */ + VisionCamGamma *mGammaR; /**< Gamma data for right channel in case of stereoscopic use cases. */ + + VisionCamUnsaturatedRegions *mUnsaturatedRegions; + VisionCamMTIS *mMTIS_Data; + VisionCamFocusRegion *mFocusRegionData; + +}VisionCamMetadata; + +/** @struct VisionCamGammaTableType + * Defines the gamma table data type, that is used while setting manual gamma table coeficients. +*/ +typedef struct _gamma_tbl_type { + int32_t mTableSize; /**< The size of the table. */ + uint16_t *mRedTable; /**< Address of the table with red color coeficients. */ + uint16_t *mGreenTable; /**< Address of the table with green color coeficients. */ + uint16_t *mBlueTable; /**< Address of the table with blue color coeficients. */ +}VisionCamGammaTableType; + +/** @struct VisionCamRectType + * Definition of rectangle type. +*/ +typedef struct _rect_type { + int32_t mLeft; /**< x-axis coordinate of top-left corner of a rectangle. */ + int32_t mTop; /**< y-axis coordinate of top-left corner of a rectangle. */ + uint32_t mWidth; /**< Width of a rectangle. */ + uint32_t mHeight; /**< Height of a rectangle. */ +}VisionCamRectType; + +/** @struct VisionCamFaceType + * Data type containing the output of face detection algorithm output. +*/ +typedef struct _face_type { + /**< Detection score between 0 and 100 + 0 means unknown score, + 1 means least certain, + 100 means most certain the detection is correct */ + uint32_t mScore; + /**< Coordinates of the face */ + VisionCamRectType mFacesCoordinates; + /**< The orientation of the axis of the detected object. + Here roll angle is defined as the angle between the vertical axis of face and the horizontal axis. + All angles can have the value of -180 to 180 degree in Q16 format. + Some face detection algorithm may not be able to fill in the angles */ + int32_t mOrientationRoll; + int32_t mOrientationYaw; + int32_t mOrientationPitch; + /**< Represents priority of each object when there are multiple objects detected */ + uint32_t mPriority; +}VisionCamFaceType; + +/** @struct VisionCamVarFramerateType + * Defines the minimum and maximum fps in case a variable frame rate os selected. + * Variable frame rate, means that expositions and respectively frame rate are recalculated at any moment. +*/ +typedef struct _var_frame_rate_type { + uint32_t mMin; /**< Minimum fps. */ + uint32_t mMax; /**< Maximul fps. */ +}VisionCamVarFramerateType; + +/** @struct VisionCamImagePyramidType + * Defines the levels count and scaling factor for image pyramids. + * mScalingFactor is in Q16 format. + * Image pyramid is same images with different resolutions in common buffer. +*/ +typedef struct _image_pyramid_type { + uint32_t mLevelsCount; + uint32_t mScalingFactor; // Q16 +}VisionCamImagePyramidType; + +/** @struct VisionCamObjectRectType + * Definition of type, describing an area where an object is detected. +*/ +typedef struct _vcam_object_rect_type { + VisionCamObjectType mObjType; /**< The type ofthe object. */ + int32_t mTop; /**< y-axis coordinate of top-left corner of a rectangle. */ + int32_t mLeft; /**< x-axis coordinate of top-left corner of a rectangle. */ + uint32_t mWidth; /**< Width of a rectangle. */ + uint32_t mHeight; /**< Height of a rectangle. */ +}VisionCamObjectRectType; + +#ifdef __cplusplus +/** @struct VisionCamGestureInfo + * Structure containing information about gesures detected inside the stream. +*/ +struct VisionCamGestureInfo { + ~VisionCamGestureInfo() + { + if( mRegions ) + delete [] mRegions; + } + VisionCamGestureEvent_e mGestureType; /**< Type of the gesture event. */ + uint64_t timeStamp; /**< Timestamp of the frame in which this is detected. */ + uint32_t mRegionsNum; /**< The number of the regions in frame, where it is detected. */ + VisionCamObjectRectType *mRegions; /**< Coordinateds and gesture object for each region. */ +}; +#else +/** @struct VisionCamGestureInfo + * Structure containing information about gesures detected inside the stream. +*/ +typedef struct _vcam_gesture_info_type { + VisionCamGestureEvent_e mGestureType; /**< Type of the gesture event. */ + uint64_t timeStamp; /**< Timestamp of the frame in which this is detected. */ + uint32_t mRegionsNum; /**< The number of the regions in frame, where it is detected. */ + VisionCamObjectRectType *mRegions; /**< Coordinateds and gesture object for each region. */ +} VisionCamGestureInfo; +#endif // __cplusplus + +/** @class VisionCamClientNotifier + * User notification class. + * This is used to notify client when an extarnal camera event occur. +*/ +class VisionCamClientNotifier { +public: + /**< @enum VisionCamClientNotificationMsg + * Defines some possible events that may occur outside VisionCam. + */ + typedef enum _vcam_client_notification_msg_type{ + VCAM_MESSAGE_EMPTY, /**< Unknown event occur. */ + VCAM_MESSAGE_ALLOCATE_V4L2_BUFFERS, /**< User may allocate image resources (this is in case resources were previously freed, bacause of external event). */ + VCAM_MESSAGE_FREE_V4L2_BUFFERS, /**< User must free allocated resources. */ + VCAM_MESSAGE_PREEMPT_SUSPEND_ACTIVITY, /**< Camera has been preempted by a higher priority process, so VisionCam will suspend. This means frames will not be received for some time. */ + VCAM_MESSAGE_PREEMPT_RESUME_ACTIVITY, /**< VisionCam has got back its control over camera. */ + VCAM_MESSAGE_PREEMPT_WAIT_RESOURCES, /**< */ + VCAM_MESSAGE_PREAMPT_RESOURCES_READY, /**< */ + VCAM_MESSAGE_STOP_STREAMING, /**< Tells that VisionCam's client must stop Filebased stream, Preview etc.*/ + + VCAM_MESSAGE_MAX + }VisionCamClientNotificationMsg; + + typedef void *(*_vcam_client_notification_callback_type)( _vcam_client_notification_msg_type ); + typedef _vcam_client_notification_callback_type VisionCamClientNotifierCallback; + +public: + /// Constructor + VisionCamClientNotifier() + { + mNotificationCallback = NULL; + } + + /// The notification function, that user will register. + VisionCamClientNotifierCallback mNotificationCallback; +}; + +/** @class VisionCamFrame + * + * Frame descriptor class. Holds preview a frame + * and carries all the data related to it. +*/ +class VisionCamFrame +{ +public: + + /** default contrustor */ + VisionCamFrame(); + + /** copy constructor */ + VisionCamFrame(const VisionCamFrame &frame) : + mCookie(frame.mCookie), + mFrameBuff(frame.mFrameBuff), + mExtraDataBuf(frame.mExtraDataBuf), + mFrameSource(frame.mFrameSource), + mFd(frame.mStartY), + mTimestamp(frame.mTimestamp), + mWidth(frame.mWidth), + mHeight(frame.mHeight), + mOffsetX(frame.mOffsetX), + mOffsetY(frame.mOffsetY), + mLength(frame.mLength), + mExtraDataLength(frame.mExtraDataLength), + mMetadata(frame.mMetadata), + mDetectedFacesNum(frame.mDetectedFacesNum), + mDetectedFacesNumRaw(frame.mDetectedFacesNumRaw) + { + if( mDetectedFacesNum ) + memcpy( &mFaces, &frame.mFaces, mDetectedFacesNum*sizeof(VisionCamFaceType)); + else + memset( &mFaces, 0, sizeof(VisionCamFaceType)*MAX_FACES_COUNT); + + if( mDetectedFacesNumRaw ) + memcpy( &mFacesRaw, &frame.mFacesRaw, mDetectedFacesNumRaw*sizeof(VisionCamFaceType)); + else + memset( &mFacesRaw, 0, sizeof(VisionCamFaceType)*MAX_FACES_COUNT); + }; + + /** This clears all values */ + void clear(); + + /** This serializes all data in the frame into a flat buffer */ + size_t serialize(uint8_t *buffer, size_t len); + + /** This unserializes all the data from a flat buffer back into the instance class object */ + size_t unserialize(uint8_t *buffer, size_t len); + + /** This returns the max possible size (as currently allocated) of the frame for the purpose of allocating flat memory for serialization */ + size_t maxSerialLength(); + +public: + void *mContext; /**< Indicates in which context this frame is set (which VisionCam instance at all). */ + void *mCookie; /**< The cookie data. */ + void *mFrameBuff; /**< The image buffer. @see DVP_Image_t */ + void *mExtraDataBuf; /**< Extra data buffer. */ + VisionCamPort_e mFrameSource; /**< The index of the port from which this frame has arrived. */ + int32_t mFd; /**< */ + int64_t mTimestamp; /**< The timestamp for the frame. + * The timestanp is unique for each frame on a port + * but when multiple ports are running, the timestamp + * is the same for the matching frames on different ports. + */ + uint32_t mWidth; /**< Frame width. */ + uint32_t mHeight; /**< Frame haight. */ + uint32_t mOffsetX; /**< The offset in X-direction of the actual frame data inside the buffer. */ + uint32_t mOffsetY; /**< The offset in Y-direction of the actual frame data inside the buffer. */ + uint32_t mStartX; /**< */ + uint32_t mStartY; /**< */ + uint32_t mLength; /**< The image size in bytes. */ + uint32_t mExtraDataLength; /**< Size in bytes if extra data buffer. */ + VisionCamMetadata mMetadata; /**< Parsed meta data. */ + uint32_t mDetectedFacesNum; /**< Number of faces detected in this frame. */ + VisionCamFaceType mFaces[ MAX_FACES_COUNT ]; /**< Informatin about detected faces. */ + uint32_t mDetectedFacesNumRaw; /**< Number of faces detected in this frame as a raw data from FD algo. */ + VisionCamFaceType mFacesRaw[ MAX_FACES_COUNT ]; /**< Informatin about detected faces as a raw data from FD algo. */ +}; + + +/** @class VisionCamFramePack + * A frame holder. + * This structure keeps the matching frames from all possinble sources. + * This is used when packaging option is enabled. + * Packaging is based on frame timestamp. +*/ +class VisionCamFramePack +{ +public: + VisionCamFramePack(){ + for( int32_t i = 0; i < VCAM_PORT_MAX; i++) { + mFrame[i] = NULL; + mExpectedFrames[i] = false_e; + } + mTimestamp = 0; + mIsEmpty = true_e; + } + + VisionCamFrame *mFrame[VCAM_PORT_MAX]; /**< Addresses of all the frames from all running sources */ + int64_t mTimestamp; /**< Timestamp of these frames. The same for all*/ + + bool_e mExpectedFrames[VCAM_PORT_MAX]; /**< Which frames must be written, + corresponds to the frame sourcs state (running or not). + */ + + bool_e mIsEmpty; /**< Read only field: + true_e when there is a valid data inside mFrame[] + false_e when there is no valid data inside mFrame[] + */ +}; + +/** @typedef Frame callback type. +*/ +typedef void (*FrameCallback_f)(VisionCamFrame *cameraFrame); + +/** @typedef Frame callback type, + * used to pass multiple frames in a single shot. +*/ +typedef void (*FramePackCallback_f)(VisionCamFramePack *cameraFramePacket); + +/** @typedef Focus callback type. +*/ +typedef void ( * FocusCallback_t )(int); + +/** @enum VisionCam_e + * This one is used when a handle to VisionCam is created. + * Those options correspond to the vision processing mode. +*/ +typedef enum _vision_cam_e { + VISIONCAM_FILE, /**< Stream that has already been recorded. */ + VISIONCAM_OMX, /**< Live stream through OMX camera. */ + VISIONCAM_USB, /**< Live stream through USB, for example with a web camera. */ + VISIONCAM_SOCKET, /**< Live stream usinf TPC IP communication */ + + VISIONCAM_MAX, +} VisionCam_e; + +/** @class VCamSensorInfo + * Sensor information type. +*/ +class VCamSensorInfo{ +public: + VCamSensorInfo(){ + nIndex = -1; + supportedModesCnt = 0; + memset(&supportedModes, 0, sizeof(supportedModes)); + } + + int32_t nIndex; + int32_t supportedModesCnt; + VisionCamCaptureMode supportedModes/*[modesNum]*/[VCAM_CAP_MODE_MAX]; +}; + +/** + * @brief The VCamSensorAvailable class + * Contains data about all the cameras detected as attached to the device. + */ +class VCamSensorAvailable { +public: + VCamSensorAvailable(){ + sensorCount = 0; + } + + int32_t sensorCount; + VCamSensorInfo sensors[VCAM_Max_Supported_Sensor_Count]; +}; + +/** VisionCam is a Mixin pattern which defines the abstract interface to the + * class which wraps the physical Camera and/or the USB/File based alternatives + * while implementing some of the common features of the class. + */ +class VisionCam +{ +protected: + FrameCallback_f m_callback; /**< The default callback for preview frames */ + FramePackCallback_f m_pack_callback; /**< The callback for frames received from all ports and sent in a single call to user*/ + FocusCallback_t m_focuscallback; /**< The default focus callback */ + void * m_cookie; /**< The protected cookie data to pass to the m_callback */ + uint32_t m_frameNum; /**< The current number of frames delivered since instantiation */ +public: + VisionCam(); + + /** Deconstructor */ + virtual ~VisionCam(); + + /** Initializing method */ + virtual status_e init(void *cookie) = 0; + + /** Deinitializer */ + virtual status_e deinit() = 0; + + /** This method informs the VisionCam to use the supplied buffer */ + virtual status_e useBuffers( DVP_Image_t *prvBufArr, uint32_t numPrvBuf, VisionCamPort_e port = VCAM_PORT_PREVIEW) = 0; + + /** This method informs the VisionCam to stop using the supplied buffers */ + virtual status_e releaseBuffers( VisionCamPort_e port = VCAM_PORT_PREVIEW ) = 0; + + /** This method informs the VisionCam to recall any outstanding buffers from remote cores or to drop pending copies */ + virtual status_e flushBuffers( VisionCamPort_e port = VCAM_PORT_PREVIEW ) = 0; + + /** This method informs the VisionCam to execute some additional functionality */ + virtual status_e sendCommand( VisionCamCmd_e cmdId, void *param = NULL, uint32_t size = 0, VisionCamPort_e port = VCAM_PORT_PREVIEW) = 0; + + /** This method informs the VisionCam to configure itself with the supplied parameters */ + virtual status_e setParameter( VisionCamParam_e paramId, void* param = NULL, uint32_t size = 0, VisionCamPort_e port = VCAM_PORT_PREVIEW) = 0; + + /** This method informs the VisionCam to configure itself with the supplied parameters */ + virtual status_e getParameter( VisionCamParam_e paramId, void* param = NULL, uint32_t size = 0, VisionCamPort_e port = VCAM_PORT_PREVIEW) = 0; + + /** This method returns a used buffer to the VisionCam to use again in the future */ + virtual status_e returnFrame( VisionCamFrame *cameraFrame ) = 0; + +public: + // Implemented Functions in this Mixin + + /** This returns the number of frames read from the camera since initialization */ + uint32_t GetFrameNumber(); + + /** This method informs the VisionCam to enable the callback to the client which informs the client about the preview frame */ + status_e enablePreviewCbk(FrameCallback_f callback); + + /** This method informs the VisionCam to enable the callback to the client which informs the client about all frames */ + status_e enablePackedFramesCbk(FramePackCallback_f callback); + + /** This method informs the VisionCam to disable the preview frame m_callback */ + status_e disablePreviewCbk(FrameCallback_f callback); + + /** This method informs the VisionCam to disable the packed frames callback */ + status_e disablePackedFramesCbk(FramePackCallback_f callback); + + /** This method give the focus callback to camera */ + status_e setFocusCallBack(FocusCallback_t callback); +}; + +typedef VisionCam *(*VisionCamFactory_f)(VisionCam_e type); + +extern "C" VisionCam *VisionCamFactory(VisionCam_e type); + +uint32_t GetImageSize(uint32_t width, uint32_t height, fourcc_t fourcc); + +#endif + diff --git a/include/dvp/VisionCam_3A_ExportTypes.h b/include/dvp/VisionCam_3A_ExportTypes.h new file mode 100644 index 0000000..1a53ce1 --- /dev/null +++ b/include/dvp/VisionCam_3A_ExportTypes.h @@ -0,0 +1,1318 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _VISION_CAM_3A_EXPORT_TYPES_H_ +#define _VISION_CAM_3A_EXPORT_TYPES_H_ + +#include + +/*! \brief 16 Extended to allow precise H3A for preview */ +#define VCAM_MAX_WINHC (36) +/*! \brief 32 Extended to allow precise H3A for preview */ +#define VCAM_MAX_WINVC (128) +/*! \brief One paxel is 32 Bytes + on every 8 paxel 8*2 Bytes for number of unsaturated pixels in previouse 8 paxels */ +#define VCAM_AWWB_H3A_PAXEL_SIZE_BYTES (32 + 2) +/*! \brief Max buffer size for AEWB H3A */ +#define VCAM_AEWB_H3A_MAX_BUFF_SIZE (1) //(VCAM_MAX_WINHC * VCAM_MAX_WINVC * VCAM_AWWB_H3A_PAXEL_SIZE_BYTES) +/*! \brief AF SCM Range Constants */ +#define VCAM_AF_PAXEL_VERTICAL_COUNT_MAX (127) +/*! \brief AF SCM Range Constants */ +#define VCAM_AF_PAXEL_HORIZONTAL_COUNT_MAX (35) +/*! \brief Max buffer size for AF H3A */ +#define VCAM_AF_H3A_MAX_BUFF_SIZE (1) //(VCAM_AF_PAXEL_VERTICAL_COUNT_MAX * VCAM_AF_PAXEL_HORIZONTAL_COUNT_MAX * 48) +/*! \brief Max sensor with */ +#define VCAM_ISP_IN_WIDTH (4032) +/*! \brief Max sensor height */ +#define VCAM_ISP_IN_HEIGHT (3024) +/*! \brief Max buffer size for IPIPE BOXCAR */ +#define VCAM_IPIPE_BOXCAR_MAX_BUFF_SIZE (1) //(((VCAM_ISP_IN_WIDTH / 8) * (VCAM_ISP_IN_HEIGHT / 8)) * 8) + + +/*! \brief Noise filter number of THR coefficients */ +#define VCAM_ISS_NF_THR_COUNT (8) +/*! \brief Noise filter number of STR coefficients */ +#define VCAM_ISS_NF_STR_COUNT (8) +/*! \brief Noise filter number of SPR coefficients */ +#define VCAM_ISS_NF_SPR_COUNT (8) +/*! \brief Numbers of values in Gamma table */ +#define VCAM_ISS_PREV_GAMMA_TABLE (1024) +/*! \brief Number of offset values on table */ +#define VCAM_ISS_PREV_RGB2RGB_OFFSET (3) +/*! \brief Numbers of values in rows and colomns */ +#define VCAM_ISS_PREV_RGB2RGB_MATRIX (3) +/*! \brief GBCE enhancement table size */ +#define VCAM_ISS_GBCE_TABLE_SIZE (1024) +/*! \brief Edge enhancement table size */ +#define VCAM_ISS_EE_TABLE_SIZE (1024) +/*! \brief Edge enhancement number of coefficients */ +#define VCAM_ISS_COEFF (9) +/*! \brief Histogram dims count */ +#define VCAM_ISS_HIST_DIMS_COUNT (4) +/*! \brief Histogram gain table size */ +#define VCAM_ISS_HIST_GAIN_TBL (4) +/*! \brief 3d lut table size */ +#define VCAM_ISS_3D_LUT_SIZE (1) //(729) +/*! \brief Number of offset values on table */ +#define VCAM_ISS_PREV_RGB2YUV_OFFSET (3) +/*! \brief Numbers of values in rows and colomns */ +#define VCAM_ISS_PREV_RGB2YUV_MATRIX (3) + +/*! \brief Defines which camera 3A configuration parameters, + * could be modified by VisionCam's client. + */ +enum SettingType_e{ + VCAM_3A_Start = 0, + + VCAM_3A_Lsc2D = VCAM_3A_Start, /*!< \see VisionCam_3A_2D_LscConfig_t */ + VCAM_3A_Clamp, /*!< \see VisionCam_3A_Clamp_t */ + VCAM_3A_GainOffset, /*!< \see VisionCam_3A_GainOffset_t */ + VCAM_3A_Vldc, /*!< \see VisionCam_3A_VDLC_t */ + VCAM_3A_Nf1, /*!< \see VisionCam_3A_NoiseFilterConfig_t */ + VCAM_3A_Nf2, /*!< \see VisionCam_3A_NoiseFilterConfig_t */ + VCAM_3A_GIC, /*!< \see VisionCam_3A_GIC_Config_t */ + VCAM_3A_WB, /*!< \see VisionCam_3A_WB_Config_t */ + VCAM_3A_CFA, /*!< \see VisionCam_3A_CFA_Config_t */ + VCAM_3A_Gamma, /*!< \see VisionCam_3A_GammaTableConfig_t */ + VCAM_3A_Rgb2Rgb1, /*!< \see VisionCam_3A_RGB2RGB_t */ + VCAM_3A_Rgb2Rgb2, /*!< \see VisionCam_3A_RGB2RGB_t */ + VCAM_3A_Rgb2Yuv, /*!< \see VisionCam_3A_RGB2YUV_t */ + VCAM_3A_GBCE, /*!< \see VisionCam_3A_GBCE_Config_t */ + VCAM_3A_Yuv2Yuv, /*!< \see VisionCam_3A_Yuv444_toYuv422_Config_t */ + VCAM_3A_Ee, /*!< \see VisionCam_3A_EdgeEnhancement_config_t */ + VCAM_3A_Car, /*!< \see VisionCam_3A_CAR_config_t */ + VCAM_3A_Lsc, /*!< \see VisionCam_3A_LscConfig_t */ + VCAM_3A_Histogram, /*!< \see VisionCam_3A_HistogramConfig_t */ + VCAM_3A_Boxcar, /*!< \see VisionCam_3A_BoxCarConfig_t */ + VCAM_3A_Bsc, /*!< \see VisionCam_3A_BscConfig_t */ + VCAM_3A_3Dcc, /*!< \see VisionCam_3A_3DCC_config_t */ + VCAM_3A_DpcOtf, /*!< \see VisionCam_3A_DpcOtfConfig_t */ + VCAM_3A_DpcLut, /*!< \see VisionCam_3A_DPC_Lut_t */ + VCAM_3A_Cgs, /*!< \see VisionCam_3A_CGS_Config_t */ + VCAM_3A_Dfs, /*!< \see VisionCam_3A_DfsConfig_t */ + VCAM_3A_Dpc1, /*!< \see VisionCam_3A_DpcConfig_t */ + VCAM_3A_Dpc2, /*!< \see VisionCam_3A_DpcConfig_t */ + VCAM_3A_Dpcm, /*!< \see VisionCam_3A_DPCM_Config_t */ + VCAM_3A_HLpf, /*!< \see VisionCam_3A_ResizerLowPassFilter_t */ + VCAM_3A_VLpf, /*!< \see VisionCam_3A_ResizerLowPassFilter_t */ + VCAM_3A_H3aAewbParams, /*!< \see VisionCam_3A_AEWB_config_t */ + VCAM_3A_H3aAfParams, /*!< \see VisionCam_3A_H3A_AutoFocusParam_t */ + VCAM_3A_H3aCommonParams, /*!< \see VisionCam_3A_H3A_CommonConfig_t */ + VCAM_3A_CamControlExpGain, /*!< \see VisionCam_3A_ExpGainControl_t */ + + e3A_ManualSetting_ALL, + e3A_ManualSetting_MAX = e3A_ManualSetting_ALL +}; + +/*! \todo comment this */ +typedef enum _vcam_3a_lsc_gain_mode_e { + VCAM_ISIF_LSC_8_PIXEL = 3, + VCAM_ISIF_LSC_16_PIXEL = 4, + VCAM_ISIF_LSC_32_PIXEL = 5, + VCAM_ISIF_LSC_64_PIXEL = 6, + VCAM_ISIF_LSC_128_PIXEL = 7, + VCAM_ISIF_LSC_128_PIXEL_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_ISIF_LSC_GAIN_MODE_MNTYPE; + +/*! \todo comment this */ +typedef enum _vcam_3a_lsc_format_e { + VCAM_LSC_GAIN_0Q8 = 0, + VCAM_LSC_GAIN_0Q8_PLUS_1 = 1, + VCAM_LSC_GAIN_1Q7 = 2, + VCAM_LSC_GAIN_1Q7_PLUS_1 = 3, + VCAM_LSC_GAIN_2Q6 = 4, + VCAM_LSC_GAIN_2Q6_PLUS_1 = 5, + VCAM_LSC_GAIN_3Q5 = 6, + VCAM_LSC_GAIN_3Q5_PLUS_1 = 7, + VCAM_LSC_GAIN_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_ISIF_LSC_GAIN_FORMATTYPE; + +/*! \todo comment this */ +typedef enum _vcam_3a_lsc_offset_e { + VCAM_ISIF_LSC_OFFSET_NO_SHIFT = 0, + VCAM_ISIF_LSC_OFFSET_1_LEFT_SHIFT = 1, + VCAM_ISIF_LSC_OFFSET_2_LEFT_SHIFT = 2, + VCAM_ISIF_LSC_OFFSET_3_LEFT_SHIFT = 3, + VCAM_ISIF_LSC_OFFSET_4_LEFT_SHIFT = 4, + VCAM_ISIF_LSC_OFFSET_5_LEFT_SHIFT = 5, + VCAM_ISIF_LSC_OFFSET_5_LEFT_SHIFT_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_ISIF_LSC_OFFSET_SHIFTTYPE; + +/*! \todo comment this */ +typedef enum _vcam_3a_lsc_offset_enable_e { + VCAM_ISIF_LSC_OFFSET_OFF = 0, + VCAM_ISIF_LSC_OFFSET_ON = 1, + VCAM_ISIF_LSC_OFFSET_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_ISIF_LSC_OFFSET_ENABLETYPE; + +/*! \todo comment this */ +typedef struct { + uint8_t nEnable; //!< DLSCCFG ENABLE-- enable 2d LSC module + uint16_t nLscHSize; //!< HVAL LSCHVAL--LSC HSIZE + uint16_t nLscVSize; //!< HVAL LSCHVAL--LSC VSIZE + uint16_t nHDirDataOffset; //!< HOFST LSCHOFST DATAHOFST 0-16383-- H-direction data offset + uint16_t nVDirDataOffset; //!< VOFST LSCVOFST DATAHOFST 0-16383-- V-direction data offset + uint8_t nHPosInPaxel; //!< X DLSCINI 6:0-- H-position of the paxel + uint8_t nVPosInPaxel; //!< Y DLSCINI 6:0-- V-position of the paxel + VCAM_3ASKIP_ISIF_LSC_GAIN_MODE_MNTYPE ePaxHeight; //!< GAIN_MODE_M DLSCCFG + VCAM_3ASKIP_ISIF_LSC_GAIN_MODE_MNTYPE ePaxLength; //!< GAIN_MODE_N DLSCCFG + VCAM_3ASKIP_ISIF_LSC_GAIN_FORMATTYPE eGainFormat; //!< GAIN_FORMAT DLSCCFG + uint8_t nOffsetScalingFactor; //!< offset scaling factor + VCAM_3ASKIP_ISIF_LSC_OFFSET_SHIFTTYPE eOffsetShiftVal; //!< OFSTSFT DLSCOFST--offset shift value + VCAM_3ASKIP_ISIF_LSC_OFFSET_ENABLETYPE eOffsetEnable; //!< OFSTSFT DLSCOFST--offset enable value + uint32_t pGainTableAddress[256]; //!< gain table address--32 bit aligned + uint16_t nGainTableLength; //!< gain table length + uint32_t pOffsetTableAddress[256]; //!< offset table address + uint16_t nOffsetTableLength; //!< offset table length +} VCAM_3ASKIP_ISIF_2DLSC_CFGTYPE; + +/*! \todo comment this */ +typedef struct _manual_3A_setting_base_t { + SettingType_e eParamType; + void *pData; +} VisionCam_3Asettings_Base_t; + +/*! \todo comment this */ +typedef struct _vcam_3a_2dlsc_cfg_t +{ + int32_t eSensor; + VCAM_3ASKIP_ISIF_2DLSC_CFGTYPE m2D_LscConfig; +} VisionCam_3A_2D_LscConfig_t; + +/*! \todo comment this */ +typedef enum { + VCAM_ISIF_HORIZONTAL_CLAMP_DISABLED = 0, + VCAM_ISIF_HORIZONTAL_CLAMP_ENABLED = 1, + VCAM_ISIF_PREVIOUS_HORIZONTAL_CLAMP_ENABLED = 2, + VCAM_ISIF_CLAMP_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_ISIF_HORIZONTAL_CLAMP_MODETYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_horizontal_clamp_t +{ + int32_t eSensor; + VCAM_3ASKIP_ISIF_HORIZONTAL_CLAMP_MODETYPE eHorizontalClamp; +} VisionCam_3A_HorizontalClamp_t; + +/*! \todo comment this */ +typedef enum { + VCAM_ISIF_ONE_COLOR_CLAMP = 0, + VCAM_ISIF_FOUR_COLOR_CLAMP = 1, + VCAM_ISIF_COLOR_CLAMP_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_ISIF_BLACK_CLAMP_MODETYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_black_clamp_mode_t +{ + int32_t eSensor; + VCAM_3ASKIP_ISIF_BLACK_CLAMP_MODETYPE eBlackClamp; +} VisionCam_3A_BlackClamp_t; + +/*! \todo comment this */ +typedef enum { + VCAM_ISIF_HBLACK_2PIXEL_TALL = 0, + VCAM_ISIF_HBLACK_4PIXEL_TALL = 1, + VCAM_ISIF_HBLACK_8PIXEL_TALL = 2, + VCAM_ISIF_HBLACK_16PIXEL_TALL = 3, + VCAM_ISIF_HBLACK_PIXEL_TALL_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_ISIF_HBLACK_PIXEL_HEIGHTTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_black_pixel_height_t +{ + int32_t eSensor; + VCAM_3ASKIP_ISIF_HBLACK_PIXEL_HEIGHTTYPE eBlackPixHeight; +} VisionCam_3A_BlackPixelHeight_t; + +/*! \todo comment this */ +typedef enum { + VCAM_ISIF_HBLACK_32PIXEL_WIDE = 0, + VCAM_ISIF_HBLACK_64PIXEL_WIDE = 1, + VCAM_ISIF_HBLACK_128PIXEL_WIDE = 2, + VCAM_ISIF_HBLACK_256PIXEL_WIDE = 3, + VCAM_ISIF_HBLACK_PIXEL_WIDE_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_ISIF_HBLACK_PIXEL_WIDTHTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_horiz_black_pixel_width_t +{ + int32_t eSensor; + VCAM_3ASKIP_ISIF_HBLACK_PIXEL_WIDTHTYPE eBlackPixWidth; +} VisionCam_3A_HorizBlackPixelWidth_t; + +/*! \todo comment this */ +typedef enum { + VCAM_ISIF_VBLACK_PIXEL_NOT_LIMITED = 0, + VCAM_ISIF_VBLACK_PIXEL_LIMITED = 1, + VCAM_ISIF_VBLACK_PIXEL_LIMITED_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_ISIF_HBLACK_PIXEL_VALUE_LIMTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_black_pixel_value_t +{ + int32_t eSensor; + VCAM_3ASKIP_ISIF_HBLACK_PIXEL_WIDTHTYPE eBlackPixValue; +} VisionCam_3A_BlackValue_t; + +/*! \todo comment this */ +typedef enum { + VCAM_ISIF_VBLACK_BASE_WINDOW_LEFT = 0, + VCAM_ISIF_VBLACK_BASE_WINDOW_RIGHT = 1, + VCAM_ISIF_VBLACK_BASE_WINDOW_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_ISIF_HBLACK_BASE_WINDOWTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_black_base_window_t +{ + int32_t eSensor; + VCAM_3ASKIP_ISIF_HBLACK_BASE_WINDOWTYPE eBlackBaseWin; +} VisionCam_3A_BlackBaseWindow_t; + +/*! \todo comment this */ +typedef struct { + uint16_t nVPos; //!< Window Start position (V).Range: 0 - 8191 + VCAM_3ASKIP_ISIF_HBLACK_PIXEL_HEIGHTTYPE eVSize; //!< Vertical dimension of a Window (2^N). + uint16_t nHPos; //!< Window Start position (H).Range: 0 - 8191 + VCAM_3ASKIP_ISIF_HBLACK_PIXEL_WIDTHTYPE eHSize; //!< Horizontal dimension of a Window (2^M). + VCAM_3ASKIP_ISIF_HBLACK_PIXEL_VALUE_LIMTYPE ePixelValueLimit; //!< Pixel value limitation for the Horizontal clamp value calculation + VCAM_3ASKIP_ISIF_HBLACK_BASE_WINDOWTYPE eRightWindow; //!< Base Window select + uint8_t nWindowCountPerColor; //!< Window count per color. Window count = CLHWC+1. Range: 1 - 32 +} VCAM_3ASKIP_ISIFHBLACKPARAMSTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_black_params_horiz_t +{ + int32_t eSensor; + VCAM_3ASKIP_ISIFHBLACKPARAMSTYPE mBlackParams_hor; +} VisionCam_3A_BlackParams_Horiz_t; + +/*! \todo comment this */ +typedef enum { + VCAM_ISIF_VBLACK_2PIXEL_WIDE = 0, + VCAM_ISIF_VBLACK_4PIXEL_WIDE = 1, + VCAM_ISIF_VBLACK_8PIXEL_WIDE = 2, + VCAM_ISIF_VBLACK_16PIXEL_WIDE = 3, + VCAM_ISIF_VBLACK_32PIXEL_WIDE = 4, + VCAM_ISIF_VBLACK_64PIXEL_WIDE = 5, + VCAM_ISIF_VBLACK_PIXEL_WIDE = 0x7FFFFFFF +} VCAM_3ASKIP_ISIF_VBLACK_PIXEL_WIDTHTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_vert_black_pixel_width_t +{ + int32_t eSensor; + VCAM_3ASKIP_ISIF_VBLACK_PIXEL_WIDTHTYPE eBlackPixWidth_Vert; +} VisionCam_3A_VertBlackPixelWidth_t; + +/*! \todo comment this */ +typedef enum { + VCAM_ISIF_VALUE_HORIZONTAL_DIRECTION = 0, + VCAM_ISIF_VALUE_CONFIG_REGISTER = 1, + VCAM_ISIF_VALUE_NOUPDATE = 2, + VCAM_ISIF_VALUE_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_ISIF_VBLACK_RESET_MODETYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_black_reset_vert_t +{ + int32_t eSensor; + VCAM_3ASKIP_ISIF_VBLACK_RESET_MODETYPE eBlackReset_vert; +} VisionCam_3A_BlacReset_Vert_t; + +/*! \brief Vertical black clamp. */ +typedef struct { + uint16_t nVPos; //!< Window Start position (V).Range: 0 - 8191 + uint16_t nVSize; //!< Optical black V valid (V).Range: 0 - 8191 + uint16_t nHPos; //!< position (H).Range: 0 - 8191 + VCAM_3ASKIP_ISIF_VBLACK_PIXEL_WIDTHTYPE HSize; //!< Optical Black H valid (2^L). + uint8_t line_avg_coef; //!< Line average coefficient (k). + VCAM_3ASKIP_ISIF_VBLACK_RESET_MODETYPE reset_mode; //!< Select the reset value for the Clamp value of the Previous line + uint16_t reset_value; //!< Vertical black clamp reset value (U12) Range: 0 to 4095 +} VCAM_3ASKIP_ISIF_VERTICAL_BLACK_PARAMSTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_black_params_vert_t +{ + int32_t eSensor; + VCAM_3ASKIP_ISIF_VERTICAL_BLACK_PARAMSTYPE mBlackParams_vert; +} VisionCam_3A_BlacParams_Vert_t; + +/*! \todo comment this */ +typedef struct { + uint8_t nEnable; //!< clamp module enablement + VCAM_3ASKIP_ISIF_HORIZONTAL_CLAMP_MODETYPE eHClampMode; //!< horizontal clamp mode + VCAM_3ASKIP_ISIF_BLACK_CLAMP_MODETYPE eBlackClampMode; //!< black clamp mode + uint16_t nDCOffsetClampVal; //!< clamp dc-offset value + uint16_t nBlackClampVStartPos; //!< black clamp v-start position (range 0-8191) + VCAM_3ASKIP_ISIF_VERTICAL_BLACK_PARAMSTYPE tHorizontalBlack; //!< horizontal black clamp parameters + VCAM_3ASKIP_ISIF_VERTICAL_BLACK_PARAMSTYPE tVerticalBlack; //!< vertical black clamp parameters +} VCAM_3ASKIP_ISIF_CLAMP_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_black_clamp_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_ISIF_CLAMP_CFGTYPE mClamp; +} VisionCam_3A_Clamp_t; + +/*! \todo comment this */ +typedef struct { + uint8_t gain_offset_featureflag; //!< gain offset feature-flag + uint16_t gain_r; //!< gain R + uint16_t gain_gr; //!< gain GR + uint16_t gain_gb; //!< gain GB + uint16_t gain_bg; //!< gain BG + uint16_t offset; //!< offset + +} VCAM_3ASKIP_ISIF_GAINOFFSET_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_gain_offset_t +{ + int32_t eSensor; + VCAM_3ASKIP_ISIF_GAINOFFSET_CFGTYPE mGainOffset; +} VisionCam_3A_GainOffset_t; + +/*! \todo comment this */ +typedef enum { + VCAM_ISIF_VDLC_WHOLE_LINE = 0, + VCAM_ISIF_VDLC_DISABLE_ABOVE_UPPER_PIXEL = 1, + VCAM_ISIF_VDLC_MAX = 0x7FFFFFFF + +} VCAM_3ASKIP_ISIF_VDLC_PIXEL_DEPENDENCYTYPE; + +/*! \todo comment this */ +typedef enum { + VCAM_ISIF_VLDC_FED_THRO_ONSATURATION = 0, + VCAM_ISIF_VLDC_HORIZONTAL_INTERPOLATION_ONSATURATION = 1, + VCAM_ISIF_VLDC_HORIZONTAL_INTERPOLATION = 2, + VCAM_ISIF_VLDC_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_ISIF_VLDC_MODE_SELECTTYPE; + +/*! \todo comment this */ +typedef struct { + uint16_t nVerticalDefectPosition; //!< Vertical Defect position + uint16_t nHorizontalDefectPosition; //!< horizontal defect position + uint8_t nSub1ValueVldc; //!< Defect correction Memory 2 + uint8_t nSub2LessThanVldc; //!< Defect correction Memory 3 + uint8_t nSub3GreaterThanVldc; //!< Defect correction Memory 4 +} VCAM_3ASKIP_ISIF_VLDCDEFECT_LINEPARAMSTYPE; + +/*! \todo comment this */ +typedef struct { + uint8_t nEnable; //!< enable VLDC module + VCAM_3ASKIP_ISIF_VDLC_PIXEL_DEPENDENCYTYPE eDisableVldcUpperPixels; //!< pixel dependency + uint8_t nVldcShiftVal; //!< VLDC shift values + VCAM_3ASKIP_ISIF_VLDC_MODE_SELECTTYPE eVldcModeSelect; //!< VLDC mode select + uint16_t nVldcSaturationLvl; //!< VLDC saturation level: U12 range 0 - 4095 + uint8_t nDefectLines; //!< number of defect lines-maximum 8 + VCAM_3ASKIP_ISIF_VLDCDEFECT_LINEPARAMSTYPE tVldcDefectLineParams; //!< defect line paramaters +} VCAM_3ASKIP_ISIF_VLDC_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_vdlc_t +{ + int32_t eSensor; + VCAM_3ASKIP_ISIF_VLDC_CFGTYPE mVLDC; +} VisionCam_3A_VDLC_t; + +/*! \todo comment this */ +typedef enum { + VCAM_NOISE_FILTER_1 = 1, + VCAM_NOISE_FILTER_2 = 2, + VCAM_NOISE_FILTER_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_NOISE_FILTERTYPE; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPE_NF_SPR_SINGLE = 0, + VCAM_IPIPE_NF_SPR_LUT = 1, + VCAM_IPIPE_NF_SPR_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_NF_SELTYPE; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPE_NF_LSC_GAIN_OFF = 0, + VCAM_IPIPE_NF_LSC_GAIN_ON = 1, + VCAM_IPIPE_NF_LSC_GAIN_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_NF_LSC_GAINTYPE; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPE_NF_SAMPLE_BOX = 0, + VCAM_IPIPE_NF_SAMPLE_DIAMOND = 1, + VCAM_IPIPE_NF_SAMPLE_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_NF_SAMPLE_METHODTYPE; + +/*! \todo comment this */ +typedef struct { + uint8_t nEnable; //!< Enable-disable for Noise filter in pipe + VCAM_3ASKIP_IPIPE_NOISE_FILTERTYPE eNFNum; //!< Noise filter number + VCAM_3ASKIP_IPIPE_NF_SELTYPE eSel; //!< Selecting the spread in NF + VCAM_3ASKIP_IPIPE_NF_LSC_GAINTYPE eLscGain; //!< Controling the lsc gain applied in Noise Filter + VCAM_3ASKIP_IPIPE_NF_SAMPLE_METHODTYPE eTyp; //!< Selecting the sampling method + uint8_t nDownShiftVal; + uint8_t nSpread; + uint16_t pThr[VCAM_ISS_NF_THR_COUNT]; + uint8_t pStr[VCAM_ISS_NF_STR_COUNT]; + uint8_t pSpr[VCAM_ISS_NF_SPR_COUNT]; + uint16_t nEdgeMin; + uint16_t nEdgeMax; +} VCAM_3ASKIP_IPIPE_NOISE_FILTER_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_noise_filter_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_NOISE_FILTER_CFGTYPE eNoiseFilterConfig; +} VisionCam_3A_NoiseFilterConfig_t; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPE_GIC_LSC_GAIN_OFF = 0, + VCAM_IPIPE_GIC_LSC_GAIN_ON = 1, + VCAM_IPIPE_GIC_LSC_GAIN_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_GIC_LSC_GAINTYPE; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPE_GIC_GICTHR = 0, + VCAM_IPIPE_GIC_NF2THR = 1, + VCAM_IPIPE_GIC_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_GIC_SELTYPE; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPE_GIC_DIFF_INDEX = 0, + VCAM_IPIPE_GIC_HPD_INDEX = 1, + VCAM_IPIPE_GIC_INDEX_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_GIC_INDEXTYPE; + +/*! \brief GIC: Green Inbalance Correction */ +typedef struct { + /* only if data format is GR,GB */ + uint16_t nEnable; //!< Enable-disable for diffrerent components in ipipe + VCAM_3ASKIP_IPIPE_GIC_LSC_GAINTYPE eLscGain; //!< Selecting LSC gain in GIC + VCAM_3ASKIP_IPIPE_GIC_SELTYPE eSel; //!< Slection of threshold vaue in GIC filter + VCAM_3ASKIP_IPIPE_GIC_INDEXTYPE eTyp; //!< Selecting the index in GIC + uint8_t nGicGain; + uint8_t nGicNfGain; + uint16_t nGicThr; + uint16_t nGicSlope; +} VCAM_3ASKIP_IPIPE_GIC_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_gic_cfg_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_GIC_CFGTYPE mGIC_config; +} VisionCam_3A_GIC_Config_t; + +/*! \todo comment this */ +typedef struct { + /*offseet after R,GR,GB,B*/ + uint16_t pOffset[4]; + /*gain for R gr gb B*/ + uint16_t pGain[4]; +} VCAM_3ASKIP_IPIPE_WB_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_wb_cfg_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_WB_CFGTYPE eWB_config; +} VisionCam_3A_WB_Config_t; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPE_CFA_MODE_2DIR = 0, + VCAM_IPIPE_CFA_MODE_2DIR_DA = 1, + VCAM_IPIPE_CFA_MODE_DAA = 2, + VCAM_IPIPE_CFA_MODE_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_CFA_MODETYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_cfa_mode_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_CFA_MODETYPE eCFA_mode; +} VisionCam_3A_CFA_mode_t; + +/*! \todo comment this */ +typedef struct { + uint16_t nHpfThr; + uint16_t nHpfSlope; + uint16_t nMixThr; + uint16_t nMixSlope; + uint16_t nDirThr; + uint16_t nDirSlope; + uint16_t nDirNdwt; +} VCAM_3ASKIP_IPIPE_CFA_DIRTYPE; + +/*! \todo comment this */ +typedef struct { + uint8_t nMonoHueFra; + uint8_t nMonoEdgThr; + uint16_t nMonoThrMin; + uint16_t nMonoThrSlope; + uint16_t nMonoSlpMin; + uint16_t nMonoSlpSlp; + uint16_t nMonoLpwt; +} VCAM_3ASKIP_IPIPE_CFA_DAATYPE; + +/*! \todo comment this */ +typedef struct { + uint8_t nEnable; + VCAM_3ASKIP_IPIPE_CFA_MODETYPE eMode; + VCAM_3ASKIP_IPIPE_CFA_DIRTYPE tDir; + VCAM_3ASKIP_IPIPE_CFA_DAATYPE tDaa; +} VCAM_3ASKIP_IPIPE_CFA_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_cfa_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_CFA_CFGTYPE mCFA_config; +} VisionCam_3A_CFA_Config_t; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPE_GAMMA_TBL_64 = 0, + VCAM_IPIPE_GAMMA_TBL_128 = 1, + VCAM_IPIPE_GAMMA_TBL_256 = 2, + VCAM_IPIPE_GAMMA_TBL_512 = 3, + VCAM_IPIPE_GAMMA_TBL_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_GAMMA_TABLE_SIZETYPE; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPE_GAMMA_BYPASS_ENABLE = 1, + VCAM_IPIPE_GAMMA_BYPASS_DISABLE = 0, + VCAM_IPIPE_GAMMA_BYPASS_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_GAMMA_BYPASSTYPE; + +/*! \todo comment this */ +typedef struct { + uint8_t nEnable; + VCAM_3ASKIP_IPIPE_GAMMA_TABLE_SIZETYPE eGammaTblSize; + uint8_t nTbl; //!< May not be needed, since table is always in RAM + //!< o not bypassed + VCAM_3ASKIP_IPIPE_GAMMA_BYPASSTYPE eBypassB; + VCAM_3ASKIP_IPIPE_GAMMA_BYPASSTYPE eBypassG; + VCAM_3ASKIP_IPIPE_GAMMA_BYPASSTYPE eBypassR; + /*poVCAM_Ser to red gamma table Red gamma table - (U8Q0) + * Blue gamma table - (U8Q0) + * Green gamma table - (U8Q0) + */ + int8_t pRedTable[VCAM_ISS_PREV_GAMMA_TABLE]; + int8_t pBlueTable[VCAM_ISS_PREV_GAMMA_TABLE]; + int8_t pGreenTable[VCAM_ISS_PREV_GAMMA_TABLE]; +} VCAM_3ASKIP_IPIPE_GAMMA_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_gamma_table_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_GAMMA_CFGTYPE mGammaTable; +} VisionCam_3A_GammaTableConfig_t; + +/*! \todo comment this */ +typedef struct { + /* [RR] [GR] [BR] + * [RG] [GG] [BG] + * [RB] [GB] [BB]*/ + /* Blending values(S12Q8 format) */ + /*RR,GR,BR,RG,GG,BG,RB,GB,BB each 11 bits*/ + uint16_t pMulOff[VCAM_ISS_PREV_RGB2RGB_MATRIX][VCAM_ISS_PREV_RGB2RGB_MATRIX]; + /* Blending offset value for R,G,B - (S10Q0) */ + /*R,G,B each 13 bits*/ + uint16_t pOft[VCAM_ISS_PREV_RGB2RGB_OFFSET]; +} VCAM_3ASKIP_IPIPE_RGBRGB_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_rgb_to_rgb_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_RGBRGB_CFGTYPE mRGB_config; +} VisionCam_3A_RGB2RGB_t; + +/*! \todo comment this */ +typedef struct { + uint8_t nBrightness; + uint8_t nContrast; + /* [CSCRY] [CSCGY] [CSCBY] + * [CSCRCB] [CSCGCB] [CSCBCB] + * [CSCRCR] [CSCGCR] [CSCBCR] */ + /* Color space conversion coefficients(S10Q8) */ + /*RY,GY,BY,RCB,GCB,BCB ,RCR,GCR,BCR 12 bits*/ + int16_t pMulVal[VCAM_ISS_PREV_RGB2YUV_MATRIX][VCAM_ISS_PREV_RGB2YUV_MATRIX]; + /* CSC offset values for Y offset, CB offset + * and CR offset respectively (S8Q0) */ + /*Y,CB,CR -11bits*/ + int16_t pOffset[VCAM_ISS_PREV_RGB2YUV_OFFSET]; +} VCAM_3ASKIP_IPIPE_RGBYUV_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_rgb_to_yuv_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_RGBYUV_CFGTYPE mRGB2YUV; +} VisionCam_3A_RGB2YUV_t; + +/*! \todo comment this */ +typedef enum { + /*! Cr CB unmodified */ + VCAM_IPIPE_GBCE_METHOD_Y_VALUE = 0, + VCAM_IPIPE_GBCE_METHOD_GAIN_TBL = 1, + VCAM_IPIPE_GBCE_METHOD_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_GBCE_METHODTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_gbce_method_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_GBCE_METHODTYPE eGBCE_method; +} VisionCam_3A_GBCE_Method_t; + +/*! \todo comment this */ +typedef struct { + uint16_t nEnable; //!< Enable-disable for GBCE in ipipe + VCAM_3ASKIP_IPIPE_GBCE_METHODTYPE nTyp; //!< Selecting the type of GBCE method + uint16_t pLookupTable[VCAM_ISS_GBCE_TABLE_SIZE]; //!< GBCE LookUp Tabale +} VCAM_3ASKIP_IPIPE_GBCE_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_gbce_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_GBCE_CFGTYPE mGBCE_config; +} VisionCam_3A_GBCE_Config_t; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPE_PROC_COMPR_NO, + VCAM_IPIPE_PROC_COMPR_DPCM, + VCAM_IPIPE_PROC_COMPR_ALAW, + VCAM_IPIPE_PROC_COMPR_PACK, + VCAM_IPIPE_PROC_COMPR_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_PROC_COMPRESSIONTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_conpression_type_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_PROC_COMPRESSIONTYPE eCompression; +} VisionCam_3A_CompressionType_t; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPE_YUV_PHS_POS_COSITED = 0, + VCAM_IPIPE_YUV_PHS_POS_CENTERED = 1 +} VCAM_3ASKIP_IPIPE_YUV_PHASE_POSTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_yuv_phase_position_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_YUV_PHASE_POSTYPE eYuvPhasePosition; +} VisionCam_3A_YuvPhasePosition_t; + +/*! \brief ISS configuration structure which controls the operation of yuv444 to yuv 422 */ +typedef struct { + VCAM_3ASKIP_IPIPE_YUV_PHASE_POSTYPE ePos; + uint8_t nLpfEn; +} VCAM_3ASKIP_IPIPE_YUV444YUV422_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_yuv444_to_yuv422_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_YUV444YUV422_CFGTYPE mYuvToYuv_config; +} VisionCam_3A_Yuv444_toYuv422_Config_t; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPE_HALO_REDUCTION_ENABLE = 1, + VCAM_IPIPE_HALO_REDUCTION_DISABLE = 0, + VCAM_IPIPE_HALO_REDUCTION_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_EE_HALO_CTRLTYPE; + +/*! \brief ISS configuration structure Edge enhancement */ +typedef struct { + /*! Defect Correction Enable */ + uint16_t nEnable; + /*! Enable-disable for halo reduction in Edge enhancement */ + VCAM_3ASKIP_IPIPE_EE_HALO_CTRLTYPE eHaloReduction; + /*! 9 coefficients */ + int16_t pMulVal[VCAM_ISS_COEFF]; + uint8_t nSel; + uint8_t nShiftHp; + uint16_t nThreshold; + uint16_t nGain; + uint16_t nHpfLowThr; + uint8_t nHpfHighThr; + uint8_t nHpfGradientGain; + uint8_t nHpfgradientOffset; + int16_t pEeTable[VCAM_ISS_EE_TABLE_SIZE]; +} VCAM_3ASKIP_IPIPE_EE_CFGTYPE; + +typedef struct _vcam_3a_halo_reduction_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_EE_CFGTYPE eEdgeEnhConfig; +} VisionCam_3A_EdgeEnhancement_config_t; + +/*! \brief ISS configuration structure for CAR module in ipipe */ +typedef struct { + /*! Enable-disable for CAR module in ipipe */ + uint8_t nEnable; + uint8_t nTyp; + uint8_t nSw0Thr; + uint8_t nSw1Thr; + uint8_t nHpfType; + uint8_t nHpfShift; + uint8_t nHpfThr; + uint8_t nGn1Gain; + uint8_t nGn1Shift; + uint16_t nGn1Min; + uint8_t nGn2Gain; + uint8_t nGn2Shift; + uint16_t nGn2Min; +} VCAM_3ASKIP_IPIPE_CAR_CFGTYPE; + +typedef struct _vcam_3a_car_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_CAR_CFGTYPE mCar; +} VisionCam_3A_CAR_config_t; + +/*! \brief ISS configuration structure for LSC */ +typedef struct { + uint16_t nVOffset; + int16_t nVLinearCoeff; + int16_t nVQuadraticCoeff; + uint8_t nVLinearShift; + uint8_t nVQuadraticShift; + uint16_t nHOffset; + int16_t nHLinearCoeff; + int16_t nHQuadraticCoeff; + uint8_t nHLinearShift; + uint8_t nHQuadraticShift; + uint8_t nGainR; //!< Gain value for R + uint8_t nGainGR; //!< Gain value for GR + uint8_t nGainGB; //!< Gain value for GB + uint8_t nGainB; //!< Gain value for B + uint8_t nOffR; //!< Offset value for R + uint8_t nOffGR; //!< Offset value for GR + uint8_t nOffGB; //!< Offset value for GB + uint8_t nOffB; //!< Offset value for B + uint8_t nShift; + uint16_t nMax; +} VCAM_3ASKIP_IPIPE_LSC_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_lsc_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_LSC_CFGTYPE mLsc; +} VisionCam_3A_LscConfig_t; + +/*! \todo comment this */ +typedef struct { + uint16_t nVPos; + uint16_t nVSize; + uint16_t nHPos; + uint16_t nHSize; +} VCAM_3ASKIP_IPIPE_HIST_DIMTYPE; + +/*! \brief ISS configuration structure for Histogram in ipipe */ +typedef struct { + uint8_t nEnable; //!< Enable-disable for Histogram in pipe + uint8_t nOst; + uint8_t nSel; + uint8_t nType; + uint8_t nBins; + uint8_t nShift; + uint8_t nCol; //!< Bits [3:0], 0 is disable + uint8_t nRegions; //!< [3:0], 0 is disable + VCAM_3ASKIP_IPIPE_HIST_DIMTYPE pHistDim[VCAM_ISS_HIST_DIMS_COUNT]; //!< Pointer to array of 4 structs + uint8_t nClearTable; + uint8_t nTableSel; + uint8_t pGainTbl[VCAM_ISS_HIST_GAIN_TBL]; //!< r,gr,gb,b +} VCAM_3ASKIP_IPIPE_HIST_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_histogram_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_HIST_CFGTYPE mHistogramConfig; +} VisionCam_3A_HistogramConfig_t; + +/*! \todo comment this */ +typedef enum { + VCAM_BOXCAR_DISABLED = 0, + VCAM_BOXCAR_ENABLED = 1, + VCAM_BOXCAR_ENB_DSB_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_BOXCAR_ENABLETYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_box_car_t +{ + int32_t eSensor; + VCAM_3ASKIP_BOXCAR_ENABLETYPE eBoxCarEnable; +} VisionCam_3A_BoxCAR_t; + +/*! \todo comment this */ +typedef enum { + VCAM_BOXCAR_FREE_RUN = 0, + VCAM_BOXCAR_ONE_SHOT = 1, + VCAM_BOXCAR_FREE_ONE_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_BOXCAR_MODETYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_box_car_mode_t +{ + int32_t eSensor; + VCAM_3ASKIP_BOXCAR_MODETYPE eBoxCarMode; +} VisionCam_3A_BoxCarMode_t; + +/*! \todo comment this */ +typedef enum { + VCAM_BOXCAR_8x8 = 0, + VCAM_BOXCAR_16x16 = 1, + VCAM_BOXCAR_SIZE_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_BOXCAR_SIZETYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_box_car_size_t +{ + int32_t eSensor; + VCAM_3ASKIP_BOXCAR_SIZETYPE eBoxCarSize; +} VisionCam_3A_BoxCarSize_t; + +/*! \todo comment this */ +typedef struct { + uint8_t nEnable; + uint8_t nOst; //!< One shot or free run + uint8_t nBoxSize; + uint8_t nShift; + uint32_t pAddr[VCAM_IPIPE_BOXCAR_MAX_BUFF_SIZE]; +} VCAM_3ASKIP_IPIPE_BOXCAR_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_box_car_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_BOXCAR_CFGTYPE eBoxCarConfig; +} VisionCam_3A_BoxCarConfig_t; + +/*! \todo comment this */ +typedef struct { + uint8_t nVectors; + uint8_t nShift; + uint16_t nVPos; //!< Vertical position + uint16_t nHPos; //!< Horizontal position + uint16_t nVNum; //!< Vertical number + uint16_t nHNum; //!< Horizontal number + uint8_t nVSkip; //!< Horizontal skip + uint8_t nHSkip; //!< Vertical skip +} VCAM_3ASKIP_IPIPE_BSCPOS_PARAMSTYPE; + +/*! \todo comment this */ +typedef struct { + uint8_t nEnable; //!< Enable-disable for BSC in pipe + uint8_t nMode; //!< BSC mode in ipipe + uint8_t nColSample; //!< BSC Color Sample + uint8_t nRowSample; //!< BSC Row Sample + uint8_t nElement; //!< Y or CB or CR + VCAM_3ASKIP_IPIPE_BSCPOS_PARAMSTYPE nColPos; //!< Color Position parameters + VCAM_3ASKIP_IPIPE_BSCPOS_PARAMSTYPE nRowPos; //!< Row Position parameters +} VCAM_3ASKIP_IPIPE_BSC_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_bsc_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_BSC_CFGTYPE mBscConfig; +} VisionCam_3A_BscConfig_t; + +/*! \brief Enable-disable enum for DFS in ipipeif */ +typedef enum { + VCAM_IPIPEIF_FEATURE_ENABLE = 1, + VCAM_IPIPEIF_FEATURE_DISABLE = 0, + VCAM_IPIPEIF_FEATURE_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPEIF_FEATURE_SELECTTYPE; + +/*! \todo comment this */ +typedef struct { + VCAM_3ASKIP_IPIPEIF_FEATURE_SELECTTYPE eDfsGainEn; //!< Enable-disable for DFS in ipipeif + uint16_t nDfsGainVal; //!< Valid only if eDfsGainEn = VCAM_IPIPEIF_FEATURE_ENABLE + uint16_t nDfsGainThr; //!< Valid only if eDfsGainEn = VCAM_IPIPEIF_FEATURE_ENABLE + uint16_t nOclip; //!< Valid only if eDfsGainEn = VCAM_IPIPEIF_FEATURE_ENABLE + uint8_t nDfsDir; //!< Set to 0 if Sensor Parallel interface data is to be subtracted by DRK frm in SDRAM +} VCAM_3ASKIP_IPIPEIF_DFS_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_dfs_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPEIF_DFS_CFGTYPE mDfsConfig; +} VisionCam_3A_DfsConfig_t; + +/*! \brief ISS struct to control defect pixel corrction in ipipeif */ +typedef struct { + VCAM_3ASKIP_IPIPEIF_FEATURE_SELECTTYPE eDpcEn; //!< Enable-disable for DPC in ipipeif + uint16_t eDpcThr; +} VCAM_3ASKIP_IPIPEIF_DPC_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_dpc_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPEIF_DPC_CFGTYPE mDpcConfig; +} VisionCam_3A_DpcConfig_t; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPEIF_DPCM_PREDICTION_SIMPLE = 0, + VCAM_IPIPEIF_DPCM_PREDICTION_ADVANCED = 1, + VCAM_IPIPEIF_DPCM_PREDICTION_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPEIF_DPCM_PRED_TYPTYPE; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPEIF_DPCM_BIT_SIZE_8_10 = 0, + VCAM_IPIPEIF_DPCM_BIT_SIZE_8_12 = 1, + VCAM_IPIPEIF_DPCM_BIT_SIZE_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPEIF_DPCM_BIT_SIZETYPE; + +/*! \todo comment this */ +typedef struct { + //!< Enable-disable for DPCM in ipipeif + VCAM_3ASKIP_IPIPEIF_FEATURE_SELECTTYPE nDpcmEn; + //!< Valid only if DPCM is enabled; dpcm_en=1 + VCAM_3ASKIP_IPIPEIF_DPCM_PRED_TYPTYPE nDpcmPredictor; + //!< Valid only if DPCM is enabled; dpcm_en=1 + VCAM_3ASKIP_IPIPEIF_DPCM_BIT_SIZETYPE nDpcmBitSize; +} VCAM_3ASKIP_IPIPEIF_DPCM_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_dpcm_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPEIF_DPCM_CFGTYPE mDPCM; +} VisionCam_3A_DPCM_Config_t; + +/*! \todo comment this */ +typedef enum { + VCAM_RSZ_IP_IPIPE = 0, + VCAM_RSZ_IP_IPIPEIF = 1, + VCAM_RSZ_IP_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_RSZ_IP_PORT_SELTYPE; + +/*! \todo comment this */ +typedef enum { + VCAM_MEM_INPUT_IPIPEIF, + VCAM_MEM_INPUT_CCP, + VCAM_MEM_INPUT_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_MEM_PROC_INPUT_SELECTTYPE; + +/*!< \brief ISS low pass filter params for Horizontal resizing */ +typedef struct { + uint8_t nCIntensity; + uint8_t nYIntensity; +} VCAM_3ASKIP_RSZ_LPF_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_resizer_lps_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_RSZ_LPF_CFGTYPE mRszLpfConfig; +} VisionCam_3A_ResizerLowPassFilter_t; + +/*! \brief Enable-Disable H3A Features */ +typedef enum { + VCAM_H3A_FEATURE_DISABLE = 0, + VCAM_H3A_FEATURE_ENABLE = 1, + VCAM_H3A_FEATURE_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE; + +/*! \brief H3A Pixel Configuration */ +typedef struct { + uint16_t nVPos; //!< AEWINSTART WINSV AFPAXSTART PAXSV + uint8_t nVSize; //!< AEWWIN1 WINW AFPAX1 PAXH + uint16_t nHPos; //!< AEWINSTART WINSH AFPAXSTART PAXSH + uint8_t nHSize; //!< AEWWIN1 WINH AFPAX1 PAXW + uint8_t nVCount; //!< AEWWIN1 WINVC AFPAX2 PAXVC + uint8_t nVIncr; //!< AEWSUBWIN AEWINCV AFPAX2 AFINCV + uint8_t nHCount; //!< AEWWIN1 WINHC AFPAX2 PAXHC + uint8_t nHIncr; //!< AEWSUBWIN AEWINCH AFPAX2 AFINCH +} VCAM_3ASKIP_H3A_PAXEL_CFGTYPE; + +/*! \todo comment this */ +typedef struct { + uint16_t nVPos; //!< AEWINBLK WINSV single row of black line vpos + uint16_t nHPos; //!< AEWINBLK WINH win height +} VCAM_3ASKIP_H3A_AEWB_BLKDIMSTYPE; + +/*! \todo comment this */ +typedef enum { + VCAM_H3A_AEWB_OP_FMT_SUM_OF_SQR = 0, + VCAM_H3A_AEWB_OP_FMT_MINMAX = 1, + VCAM_H3A_AEWB_OP_FMT_SUM_ONLY = 2, + VCAM_H3A_AEWB_OP_FMT_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_H3A_AEWB_OP_FMTTYPE; + + +/*! \todo comment this */ +typedef struct { + VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE eAewbEnable; //!< Enable-disable the Aewb engine + VCAM_3ASKIP_H3A_PAXEL_CFGTYPE tAewbPaxelWin; //!< Paxel config + VCAM_3ASKIP_H3A_AEWB_BLKDIMSTYPE tBlkWinDims; //!< AEWB Block Dimensions + VCAM_3ASKIP_H3A_AEWB_OP_FMTTYPE eAeOpFmt; //!< AEWCFG AEFMT + uint8_t nShiftValue; //!< AEWCFG SUMFST + uint16_t nSaturationLimit; //PCR AVE2LMT + uint32_t pAewbOpAddr[VCAM_AEWB_H3A_MAX_BUFF_SIZE]; +} VCAM_3ASKIP_H3A_AEWB_PARAMTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_aewb_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_H3A_AEWB_PARAMTYPE mAEWB_config; +} VisionCam_3A_AEWB_config_t; + +/*! \todo comment this */ +typedef enum { + VCAM_H3A_AF_RGBPOS_GR_GB_BAYER = 0, + VCAM_H3A_AF_RGBPOS_RG_GB_BAYER = 1, + VCAM_H3A_AF_RGBPOS_GR_BG_BAYER = 2, + VCAM_H3A_AF_RGBPOS_RG_BG_BAYER = 3, + VCAM_H3A_AF_RGBPOS_GG_RB_CUSTOM = 4, + VCAM_H3A_AF_RGBPOS_RB_GG_CUSTOM = 5, + VCAM_H3A_AF_RGBPOS_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_H3A_RGB_POSTYPE; + +/*! \todo comment this */ +typedef struct { + uint16_t pIirCoef[11]; + uint16_t nHfvThres; +} VCAM_3ASKIP_H3A_AF_IIRPARAMTYPE; + +/*! \todo comment this */ +typedef struct { + uint8_t pFirCoef[5]; + uint8_t nVfvThres; +} VCAM_3ASKIP_H3A_AF_FIRPARAMTYPE; + +/*! \todo comment this */ +typedef struct { + VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE eAfEnable; //!< Enable-Disable the AF engine + VCAM_3ASKIP_H3A_RGB_POSTYPE eRgbPos; //!< Valid only if vertical focus is enabled + VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE ePeakModeEn; //!< Enable-Disable the PeakMode engine + VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE eVerticalFocusEn; //!< Enable-Disable the VerticalFocus engine + uint16_t nIirStartPos; //!< AFIIRSH IIRSH + VCAM_3ASKIP_H3A_PAXEL_CFGTYPE tAfPaxelWin; //!< Paxel config + VCAM_3ASKIP_H3A_AF_IIRPARAMTYPE tIir1; + VCAM_3ASKIP_H3A_AF_IIRPARAMTYPE tIir2; + VCAM_3ASKIP_H3A_AF_FIRPARAMTYPE tFir1; + VCAM_3ASKIP_H3A_AF_FIRPARAMTYPE tFir2; + uint32_t pAfOpAddr[VCAM_AF_H3A_MAX_BUFF_SIZE]; //!< AEWBUFST AEWBUFST, 64 bit aligned address +} VCAM_3ASKIP_H3A_AF_PARAMTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_h3a_af_param_t +{ + int32_t eSensor; + VCAM_3ASKIP_H3A_AF_PARAMTYPE mH3A_AutoFocusParam; +} VisionCam_3A_H3A_AutoFocusParam_t; + +/*! \todo comment this */ +typedef struct { + VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE eAfMedianEn; //!< Enable-disable for H3A AF Median engine + VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE eAewbMedianEn; //!< Enable-disable for H3A AEWB Median engine + uint8_t nMedianFilterThreshold; //!< Valid only if eAfMedianEn is set to VCAM_H3A_FEATURE_ENABLE + VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE eAfAlawEn; //!< Enable-disable for AFAlaw engine + VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE eAewbAlawEn; //!< Enable-disable for AEWBAlaw engine + VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE eIpipeifAveFiltEn; //!< Enable-disable for IPIPEIFAve filter engine + VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE eH3aDecimEnable; //!< Enable-disable for H3A decimation + uint32_t nReserved; //!< Reserved +} VCAM_3ASKIP_H3A_COMMON_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_h3a_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_H3A_COMMON_CFGTYPE mH3A_CommonConfig; +} VisionCam_3A_H3A_CommonConfig_t; + +/*! \todo comment this */ +typedef struct { + uint8_t enable; //Enable-disable for 3Dcc + uint32_t pInBiffData[VCAM_ISS_3D_LUT_SIZE]; //3D LUT +} VCAM_3ASKIP_IPIPE_3DCC_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_3dcc_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_3DCC_CFGTYPE m3dccConfig; +} VisionCam_3A_3DCC_config_t; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPE_DPC_LUT_REPLACE_BLACK = 0, + VCAM_IPIPE_DPC_LUT_REPLACE_WHITE = 1, + VCAM_IPIPE_DPC_LUT_REPLACE_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_DPC_LUT_REPLACEMENTTYPE; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPE_DPC_LUT_TBL_SIZE_1024 = 0, + VCAM_IPIPE_DPC_LUT_TBL_SIZE_INF = 1, + VCAM_IPIPE_DPC_LUT_TBL_SIZE_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_DPC_LUT_TBL_SIZETYPE; + +/*! \todo comment this */ +typedef struct { + /*! Enable-disable for DPC Lut */ + uint16_t nEnable; + VCAM_3ASKIP_IPIPE_DPC_LUT_TBL_SIZETYPE eTableType; + VCAM_3ASKIP_IPIPE_DPC_LUT_REPLACEMENTTYPE eReplaceType; + uint16_t pLutValidAddr[256]; + uint16_t nLutSize; + uint32_t pLutTable0Addr[256]; + uint32_t pLutTable1Addr[256]; +} VCAM_3ASKIP_IPIPE_DPCLUT_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_dpc_lut_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_DPCLUT_CFGTYPE mDPC_lut; +} VisionCam_3A_DPC_Lut_t; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPE_DPC_OTF_ALG_MINMAX2 = 0, + VCAM_IPIPE_DPC_OTF_ALG_MINMAX3 = 1, + VCAM_IPIPE_DPC_OTF_ALG_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_DPC_ALGOTYPE; + +/*! \todo comment this */ +typedef enum { + VCAM_IPIPE_DPC_OTF_MAX1_MIN1 = 0, + VCAM_IPIPE_DPC_OTF_MAX2_MIN2 = 1, + VCAM_IPIPE_DPC_OTF_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_IPIPE_DPC_OTFTYPE; + +/*! \todo comment this */ +typedef struct { + uint16_t thr_cor_r; + uint16_t thr_cor_gr; + uint16_t thr_cor_gb; + uint16_t thr_cor_b; + + uint16_t thr_det_r; + uint16_t thr_det_gr; + uint16_t thr_det_gb; + uint16_t thr_det_b; +} VCAM_3ASKIP_IPIPE_DPCOTF_DPC2TYPE; + +/*! \todo comment this */ +typedef struct { + uint8_t nDThr; + uint8_t nDSlp; + uint16_t nDMin; + uint16_t nDMax; +} VCAM_3ASKIP_IPIPE_DPCOFT_FILTERTYPE; + +/*! \todo comment this */ +typedef struct { + uint8_t eShift; + VCAM_3ASKIP_IPIPE_DPCOFT_FILTERTYPE eOtfCorr; + VCAM_3ASKIP_IPIPE_DPCOFT_FILTERTYPE eOtfDett; +} VCAM_3ASKIP_IPIPE_DPCOTF_DPC3TYPE; + +/*! \brief Union which helps selec either dpc2-dpc 3 params */ +typedef union { + VCAM_3ASKIP_IPIPE_DPCOTF_DPC2TYPE tDpc2Params; + VCAM_3ASKIP_IPIPE_DPCOTF_DPC3TYPE tDpc3Params; +} VCAM_3ASKIP_IPIPE_DPCOTF_FILTER_PARAMSTYPE; + +/*! \todo comment this */ +typedef struct { + uint8_t nEnable; //!< Enable-disable for DPC + VCAM_3ASKIP_IPIPE_DPC_OTFTYPE eType; //!< ISS dpc otf type + VCAM_3ASKIP_IPIPE_DPC_ALGOTYPE eAlgo; //!< ISS dpc otf definitions + VCAM_3ASKIP_IPIPE_DPCOTF_FILTER_PARAMSTYPE tDpcData; //!< Union which helps selec either dpc2-dpc 3 params +} VCAM_3ASKIP_IPIPE_DPCOTF_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_dpc_otf_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_DPCOTF_CFGTYPE mDPC; +} VisionCam_3A_DpcOtfConfig_t; + +/*! \todo comment this */ +typedef struct { + uint16_t thr; + uint16_t gain; + uint16_t shift; + uint16_t min; +} VCAM_3ASKIP_IPIPE_CHROMA_PARAMSTYPE; + +/*! \todo comment this */ +typedef struct { + //!< Enable-disable for CGC in ipipe + uint16_t enable; + VCAM_3ASKIP_IPIPE_CHROMA_PARAMSTYPE y_chroma_low; + VCAM_3ASKIP_IPIPE_CHROMA_PARAMSTYPE y_chroma_high; + VCAM_3ASKIP_IPIPE_CHROMA_PARAMSTYPE c_chroma; +} VCAM_3ASKIP_IPIPE_CGS_CFGTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_cgs_config_t +{ + int32_t eSensor; + VCAM_3ASKIP_IPIPE_CGS_CFGTYPE mCgs; +} VisionCam_3A_CGS_Config_t; + +/*! \todo comment this */ +typedef enum { + VCAM_TRANSFER_ONLINE = 0, + VCAM_TRANSFER_OFFLINE = 1, + VCAM_TRANSFER_MAX = 0x7FFFFFFF +} VCAM_3ASKIP_CAM_TRANSFERTYPE; + +/*! \todo comment this */ +typedef struct { + uint32_t exp; + uint32_t a_gain; + uint8_t mask; + uint32_t nAgainErr; + uint32_t nDigitalISPGain; +} VCAM_3ASKIP_CAM_CONTROL_EXPGAINTYPE; + +/*! \todo comment this */ +typedef struct _vcam_3a_exposure_gain_control_t +{ + int32_t eSensor; + VCAM_3ASKIP_CAM_CONTROL_EXPGAINTYPE mExpGainControl; +} VisionCam_3A_ExpGainControl_t; + + +#endif // _VISION_CAM_3A_EXPORT_TYPES_H_ diff --git a/include/dvp/VisionEngine.h b/include/dvp/VisionEngine.h new file mode 100644 index 0000000..ec61457 --- /dev/null +++ b/include/dvp/VisionEngine.h @@ -0,0 +1,308 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _VISION_ENGINE_H_ +#define _VISION_ENGINE_H_ + +#include + +#include +#include +#include + +#include +#include +#include + +#if defined(ANDROID) && (defined(ICS) || defined(JELLYBEAN)) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +using namespace android; + +#endif + +/** This structure correlates the array indices of m_images back to the camera port they are assigned to. */ +typedef struct _vcam_port_desc_t { + VisionCamPort_e port; + uint32_t width; + uint32_t height; + fourcc_t color; + uint32_t fps; + VisionCamRotation_e rotate; + VisionCamMirrorType mirror; + uint32_t minIdx; + uint32_t curIdx; + uint32_t maxIdx; + uint32_t req_width; //Output - width+padding needed by the camera + uint32_t req_height;//Output - height+padding needed by the camera +} VisionCamPortDesc_t; + +/** This structure allows us to correlate a particular kernel graph with a particular port from the VisionCam */ +typedef struct _kgraph_to_image_correlation_t { + VisionCamPort_e portIdx; +} KGraph_Image_Corr_t; + +class VisionEngine : public CThreaded +{ +protected: + // Structural Variables + bool_e m_active; + bool_e m_processing; + event_t m_wait; + queue_t *m_framequeue; + semaphore_t m_engineLock; + + // Display Parameters + dvp_display_t *m_display; /**< The DVP Debug Display Interface */ + bool_e m_display_enabled; + uint32_t m_display_width; + uint32_t m_display_height; + uint32_t m_display_rotation; + bool_e m_display_special; +#if defined(ANDROID) && (defined(ICS) || defined(JELLYBEAN)) + anativewindow_t *m_anw; + sp m_surface; + sp m_window; +#endif + + // Camera Parameters + uint32_t m_width; + uint32_t m_height; + uint32_t m_fps; + uint32_t m_fourcc; + uint32_t m_numFrames; /**< The desired number of frames to capture. */ + uint32_t m_capFrames; /**< The actual number of frames captured */ + uint32_t m_camera_rotation; + uint32_t m_droppedFrames; + VisionCamSensorSelection m_sensorIndex; + VisionCamWhiteBalType m_whitemode; + VisionCamFlickerType m_flicker; + VisionCamFocusMode m_focus; + VisionCamCaptureMode m_capmode; + bool_e m_face_detect; + bool_e m_face_detect_raw; + VisionCamStereoInfo m_stereo_info; + uint32_t m_focus_delay; + int32_t m_focusDepth; + + DVP_Perf_t m_capPerf; /**< Used to calculate the average capture rate */ + + char m_name[MAX_PATH]; /**< For file based cameras, this is the prefix of the filename */ + char m_path[MAX_PATH]; /**< For file based cameras, this is the path to the file */ + + DVP_Handle m_hDVP; /**< The handle to the DVP context */ + DVP_KernelGraph_t *m_graphs; /**< The pointer to the graph array */ + uint32_t m_numGraphs; /**< The number of graphs allocated in m_graphs */ + DVP_KernelNode_t *m_pNodes; /**< The pointer to the kernel node array */ + uint32_t m_numNodes; /**< The number of nodes in the kernel graph */ + DVP_Image_t *m_images; /**< The pointer to the allocated images */ + uint32_t m_numImages; /**< The number of images */ + bool_e m_imgdbg_enabled; /** Enables file writing */ + char m_imgdbg_path[MAX_PATH]; /**< Path to write the files to */ + ImageDebug_t *m_imgdbg; /**< The pointer to the debugging structures for images */ + uint32_t m_numImgDbg; /**< The number of debugging images */ + DVP_Buffer_t *m_buffers; /**< The pointer to the allocated buffers */ + uint32_t m_numBuffers; /**< The number of buffers */ + VisionCam *m_pCam; /**< The pointer to the camera object */ + uint32_t m_camIdx; /**< Indicates which buffer we're currently using for camera buffer */ + uint32_t m_camMin; /**< Inidactes the minimum index to give to the camrea. */ + uint32_t m_camMax; /**< Indicates how many total camera buffers we have */ + uint32_t m_dispIdx; /**< Indicates which buffer we're currently using for display */ + uint32_t m_dispMin; /**< Indicates the minimum index to display */ + uint32_t m_dispMax; /**< Indicates how many total display buffers we have */ + uint32_t m_vidMin; /**< Indicates the minimum index of the video port images */ + uint32_t m_vidIdx; /**< Indicates the current index of the video port image */ + uint32_t m_vidMax; /**< Indicates the maximum index of the video port images */ + uint32_t m_procMin; /**< Indicates the minimum index of the processing buffers/images */ + uint32_t m_procIdx; /**< Indicates the current index of the processing buffers/images */ + uint32_t m_procMax; /**< Indicates the maximum index of the processing buffers/images */ + FrameCallback_f m_camcallback; + FramePackCallback_f m_pack_callback; + VisionCam_e m_camtype; /**< Indicates which GesureCam to attach to */ + KGraph_Image_Corr_t*m_correlation;/**< The allows us to match a graph to a camera port */ + uint32_t m_numPorts; /**< An indication of the number of ports enabled on the VisionCam */ + +public: + /** Default Constructor */ + VisionEngine(); + + /** Complex Constructor */ + VisionEngine(uint32_t width, uint32_t height, uint32_t fps, fourcc_t color, char *camName, uint32_t numFrames); + + /** Deconstructor */ + virtual ~VisionEngine(); + + /** Thread Wrapper */ + thread_ret_t RunThread(); + + /** This method causes the thread to start and the engine to run */ + virtual bool Startup(); + + /** This method causes the Engine loop to exit */ + virtual void Shutdown(); + + /** This is the main loop which processes the vision */ + virtual status_e Engine(); + + /** This initalizes the VisionCam with a simple interface */ + virtual status_e CameraInit(void *cookie, fourcc_t color); + + /** This configures the VisionCam with a more complex set of parameters */ + virtual status_e CameraInit(void *cookie, VisionCamPortDesc_t *desc, uint32_t numDesc, bool_e sendBuffers = true_e, bool_e startCam = true_e); + + /** This sends all buffers to VisionCam */ + virtual status_e SendCameraBuffers(VisionCamPortDesc_t *desc, uint32_t numDesc); + + /** This starts VisionCam */ + virtual status_e StartCamera(); + + /** This deinitializes the VisionCam */ + virtual status_e CameraDeinit(); + + /** This method sets up the graph */ + virtual status_e GraphSetup() = 0; + + /** This method updates the DVP Kernel Graph with the delivered image */ + virtual status_e GraphUpdate(VisionCamFrame *cameraFrame) = 0; + + /** This method processes the DVP Kerel Graph */ + virtual DVP_U32 GraphExecute(DVP_KernelGraph_t *graph); + + /** This deinitalizes the DVP Kernel Graph */ + virtual status_e GraphTeardown(); + + /** This method processes camera image */ + virtual status_e ProcessImage(VisionCamFrame * cameraFrame); + + /** The receives the image from the VisionCam and places it into an internal queue. */ + virtual void ReceiveImage(VisionCamFrame * cameraFrame); + + /** This removes the camera frame from the internal queue. Child classes can overload to change frame-dropper */ + virtual VisionCamFrame *DequeueImage(); + + /** This method is run directly after the Kernel Graphs are executed */ + virtual status_e PostProcessImage(VisionCamFrame *cameraFrame, uint32_t numSections); + + /** This method allows the child classes to overload and implement their own focus settings */ + virtual status_e DelayedCameraFocusSetting(); + + /** This method allows the child classes to overload image rendering */ + virtual status_e RenderImage(VisionCamFrame *cameraFrame); + + /** This method allow child classes to overload when the camera frame is returned to the camera */ + virtual status_e ReturnCameraFrame(VisionCamFrame *cameraFrame); + + /** This method is invoked by the DVP Section Completion Callback */ + virtual void GraphSectionComplete(DVP_KernelGraph_t * graph, DVP_U32 sectionIndex, DVP_U32 numNodesExecuted) = 0; + + /** This method allows the user to wait until all the frames are processed */ + bool WaitForCompletion(uint32_t timeout = EVENT_FOREVER); + + /** This method allows the user to limit the maximum capacity of a core */ + virtual void SetCoreCapacity(DVP_Core_e core, DVP_U32 limit); + + /** This method allows the user to remove any previously set limits on the core */ + virtual DVP_U32 GetCoreCapacity(DVP_Core_e core); + + // Support APIs + + /** This allows the engine to allocate images out of the shared region */ + bool AllocateImageStructs(uint32_t numImages); + + /** This frees the allocated images from the shared region */ + void FreeImageStructs(); + + /** This allocates kernel nodes out of the shared region of memory */ + bool AllocateNodes(uint32_t numNodes); + + /** This frees the kernel nodes allocated out of the shared region of memory */ + void FreeNodes(); + + /** This allocates a number of sections for the graph */ + bool AllocateSections(DVP_KernelGraph_t *graph, uint32_t numSections); + + /** This frees the sections and order */ + void FreeSections(DVP_KernelGraph_t *graph); + + /** This allocates a number of Kernel Graphs */ + bool AllocateGraphs(uint32_t numGraphs); + + /** This frees the Kernel graph structures */ + void FreeGraphs(); + + /** This allocates the data structures used to debug intermediate output */ + bool AllocateImageDebug(uint32_t numImgDbg); + + /** This frees the intermediate output debug data structure */ + void FreeImageDebug(); + + /** This allows the engine to allocate buffers out of the shared region */ + bool AllocateBufferStructs(uint32_t numBuffers); + + /** This frees the allocated buffers from the shared region */ + void FreeBufferStructs(); + + // Display API + + /** The convienence call wraps the DVP Display "C" API or uses the ICS special mechanisms */ + bool DisplayCreate(uint32_t image_width, uint32_t image_height, + uint32_t buffer_width, uint32_t buffer_height, + uint32_t scaled_width, uint32_t scaled_height, + uint32_t crop_top, uint32_t crop_left); + + /** The convienence call wraps the DVP Display "C" API or uses the ICS special mechanisms */ + bool DisplayAllocate(DVP_Image_t *pImage); + + /** The convienence call wraps the DVP Display "C" API or uses the ICS special mechanisms */ + void DisplayFree(DVP_Image_t *pImage); + + /** The convienence call wraps the DVP Display "C" API or uses the ICS special mechanisms */ + void DisplayDestroy(); + + /** The convienence call wraps the DVP Display "C" API or uses the ICS special mechanisms */ + virtual void DisplayRender(DVP_Image_t *pImage); + + /** The method by which to return a buffer to it's display mechanism to prevent out of order rendering */ + void DisplayDrop(DVP_Image_t *pImage); + +#if defined(ANDROID) && (defined(ICS) || defined(JELLYBEAN)) + /** If used, this method will be called before the Create/Allocate calls */ + virtual void DisplayOnWindow(const sp& binder, const sp& window); + virtual void DisplayOnSurface(const sp& surface); + virtual void DisplayOnTexture(const sp& texture); +#endif + +protected: + /** A protected constructor for this class and subclasses to call to initialize */ + virtual void Constructor(uint32_t width, uint32_t height, uint32_t fps, fourcc_t color, char *camName, uint32_t numFrames); + +}; + +#endif + diff --git a/include/dvp/anativewindow.h b/include/dvp/anativewindow.h new file mode 100644 index 0000000..add72bd --- /dev/null +++ b/include/dvp/anativewindow.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DVPANATIVEWINDOW_H_ +#define _DVPANATIVEWINDOW_H_ + +#if defined(ANDROID) && (defined(ICS) || defined(JELLYBEAN)) + +#if defined(ICS) +#include +#include +#else +#include +#include +#endif +#include +#include +#include + +/*! \brief The "special" code for Android whcih indicates NV12. + * \ingroup group_display + */ +#define ANW_NV12_FORMAT (0x100) + +using namespace android; + +/*! + * \brief A book-keeping structure used to manage the ANativeWindow interface. + * \ingroup group_display + */ +typedef struct _anativewindow_t { + sp m_window; + ANativeWindowBuffer **m_native_buffers; + int32_t m_format; + uint32_t m_numBuffers; + int32_t m_usage; + uint32_t m_nonqueue; + uint32_t m_width; + uint32_t m_height; + uint32_t m_curIdx; +} anativewindow_t; + +/*! + * \brief + * \param panw The pointer to the pointer to the book-keeping structure + * \ingroup group_display + */ +void anativewindow_destroy(anativewindow_t **panw); + +/*! + * \brief + * \ingroup group_display + */ +anativewindow_t *anativewindow_create(const sp &window); + +/*! + * \brief + * \param anw The pointer to the book-keeping structure + * \ingroup group_display + */ +void anativewindow_free(anativewindow_t *anw); + +/*! + * \brief + * \param anw The pointer to the book-keeping structure + * \ingroup group_display + */ +bool_e anativewindow_allocate(anativewindow_t *anw, + uint32_t buffer_width, + uint32_t buffer_height, + int32_t numBuffers, + int32_t format, + bool flipH); + +/*! + * \brief + * \param anw The pointer to the book-keeping structure + * \ingroup group_display + */ +bool_e anativewindow_acquire(anativewindow_t *anw, void **pHandle, uint8_t **ptrs, int32_t *stride); + +/*! + * \brief + * \param anw The pointer to the book-keeping structure + * \ingroup group_display + */ +bool_e anativewindow_release(anativewindow_t *anw, void *handle); + +/*! + * \brief + * \param anw The pointer to the book-keeping structure + * \ingroup group_display + */ +bool_e anativewindow_enqueue(anativewindow_t *anw, void *handle); + +/*! + * \brief + * \param anw The pointer to the book-keeping structure + * \ingroup group_display + */ +bool_e anativewindow_dequeue(anativewindow_t *anw, void **pHandle); + +/*! + * \brief This causes a single frame to be dropped from the render queue. + * \param anw The pointer to the book-keeping structure + * \param handle + * \ingroup group_display + */ +bool_e anativewindow_drop(anativewindow_t *anw, void *handle); + +/*! + * \brief Sets the cropping rectangle onthe native window. + * \param anw The pointer to the book-keeping structure + * \param crop_left + * \param crop_top + * \param crop_width + * \param crop_height + * \ingroup group_display + */ +bool_e anativewindow_set_crop(anativewindow_t *anw, + uint32_t crop_left, + uint32_t crop_top, + uint32_t crop_width, + uint32_t crop_height); + + +#endif + +#endif diff --git a/include/dvp/dvp.h b/include/dvp/dvp.h new file mode 100644 index 0000000..c998ed2 --- /dev/null +++ b/include/dvp/dvp.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DVP_H_ +#define _DVP_H_ + +/*! + * \file dvp.h + * \brief The top level header (external or internal use) for the Distributed Vision Processing framework. + * \author Erik Rainey + * \author Jesse Villarreal + * \defgroup group_system DVP System + * \defgroup group_graphs DVP Graph + * \defgroup group_sections DVP Section + * \defgroup group_nodes DVP Node + * \defgroup group_images DVP Image + * \defgroup group_buffers DVP Buffer + * \defgroup group_kernels DVP Kernels + * \defgroup group_capacity DVP Capacity + * \defgroup group_debugging DVP Debugging + * \defgroup group_performance DVP Performance + * \defgroup group_types DVP Types + * \defgroup group_display DVP Display + * \defgroup group_memory DVP Memory + * \defgroup group_tests DVP Tests + */ + +#include +#include +#include + +#endif + diff --git a/include/dvp/dvp_api.h b/include/dvp/dvp_api.h new file mode 100644 index 0000000..c5f4491 --- /dev/null +++ b/include/dvp/dvp_api.h @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DVP_KGRAPH_H_ +#define _DVP_KGRAPH_H_ + + +/*! + * \file dvp_api.h + * \brief The Distributed Vision Processing API Specification. + * \author Erik Rainey + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \brief This function creates an instance of DVP which can process a kernel graph. + * \note This function must be called before any other call in DVP. + * \ingroup group_system + */ +DVP_Handle DVP_KernelGraph_Init(); + +/*! + * \brief This function creates an instance of DVP which can only import and free imported memory. + * \ingroup group_system + */ +DVP_Handle DVP_MemImporter_Create(); + +/*! + * \brief This function destroys an existing DVP instance. + * \param [in] The handle to the DVP instance. + * \pre DVP_KernelGraph_Init + * \ingroup group_system + */ +void DVP_KernelGraph_Deinit(DVP_Handle handle); + +/*! + * \brief This function destroys an existing mem handler DVP instance. + * \param [in] handle The hande to the DVP instance. + * \ingroup group_system + */ +void DVP_MemImporter_Free(DVP_Handle handle); + +/*! + * \brief This function creates a graph with the requested number of sections. + * \param [in] handle The handle to the DVP context. + * \param [in] numSections The number of sections needed. + * \return Returns a Kernel Graph pointer. + * \retval NULL Could not allocate a graph. + * \ingroup group_graphs + */ +DVP_KernelGraph_t *DVP_KernelGraph_Alloc(DVP_Handle handle, DVP_U32 numSections); + +/*! + * \brief This function frees the sections, order and graph. + * \note Nodes will not be freed! Your graph pointer will need to be set to NULL + * after this function. + * \param [in] handle The handle to the DVP context. + * \param [in] graph The pointer to the graph to be freed. + * \ingroup group_graphs + */ +void DVP_KernelGraph_Free(DVP_Handle handle, DVP_KernelGraph_t *graph); + +/*! + * \brief This function initializes the desired section to execute the nodes + * indicated. + * \param [in] handle The handle to the DVP context. + * \param [in] graph The pointer to the graph to modify. + * \param [in] sectionIndex The index of the section to modify + * \param [in] pNodes The pointer to the first node for this section to execute. + * \param [in] numNodes The number of nodes from the indicated node to assign to + * the section. + * \ingroup group_sections + */ +DVP_Error_e DVP_KernelGraphSection_Init(DVP_Handle handle, + DVP_KernelGraph_t *graph, + DVP_U32 sectionIndex, + DVP_KernelNode_t *pNodes, + DVP_U32 numNodes); + +/*! + * \brief The typedef for callbacks from completed sections. + * \param [in] cookie Private pointer supplied to \ref vlProcessGraph. + * \param [in] graph The pointer to the graph. + * \param [in] sectionIndex The index of which section completed. + * \param [in] numNodesExecuted The number of nodes in the section which completed. + * \ingroup group_sections + */ +typedef void (*DVP_SectionComplete_f)(void *cookie, DVP_KernelGraph_t *graph, DVP_U32 sectionIndex, DVP_U32 numNodesExecuted); + +/*! + * \brief This function processes a DVP_KernelGraph_t and will inform + * the client after each section of nodes executed in that graph, + * successful or not. + * \param [in] handle The handle to DVP returned from \ref DVP_KernelGraph_Init. + * \param [in] graph The pointer to a Kernel Graph structure. + * \param [in] cookie A user supplied pointer to pass to the callback + * \param [in] callback The function to call after each graph completes. + * \note In parallel mode, the callback is mutex protected. + * \ingroup group_graphs + */ +DVP_U32 DVP_KernelGraph_Process(DVP_Handle handle, + DVP_KernelGraph_t *graph, + void *cookie, + DVP_SectionComplete_f callback); + +/*! + * \brief This function clears and initializes the DVP_Perf_t structure. + * \ingroup group_performance + * \param [out] perf The performance structure to clear. + */ +void DVP_Perf_Clear(DVP_Perf_t *perf); + +/*! + * \brief Initializes the performance data in each node. All prexisting performance data is lost. + * \param [in] handle The handle to DVP returned from \ref DVP_KernelGraph_Init. + * \param [in] pNodes The array of nodes to clear. + * \param [in] numNodes The number of nodes in pNodes + * \ingroup group_performance + */ +void DVP_PerformanceClear(DVP_Handle handle, DVP_KernelNode_t * pNodes, DVP_U32 numNodes); + +/*! + * \brief Captures the start time. + * \param [in] pPerf The pointer to the performance structure + * \pre \ref DVP_Perf_Clear + * \ingroup group_performance + */ +void DVP_PerformanceStart(DVP_Perf_t *pPerf); + +/*! + * \brief Captures the stop time and updates the other performance variables. + * \param [in] pPerf The pointer to the performance structure + * \pre \ref DVP_PerformanceStart + * \ingroup group_performance + */ +void DVP_PerformanceStop(DVP_Perf_t *pPerf); + +/*! + * \brief Prints the Performance information in the structure with a custom prefix string. + * \param [in] pPerf The pointer to the performance structure + * \param [in] prefix A short character series to print before the performance information. + * \pre \ref DVP_PerformanceStop + * \ingroup group_performance + */ +void DVP_PerformancePrint(DVP_Perf_t *pPerf, const char *prefix); + +/*! + * \brief This function calls printf to list the performance metrics of each node in + * a format which can be cut and pasted into a CSV file. + * \param [in] handle The handle to DVP returned from \ref DVP_KernelGraph_Init. + * \param [in] pNodes The array of nodes to print the performance information from. + * \param [in] numNodes The number of nodes which \ref nodes refers to. + * \ingroup group_performance + */ +void DVP_PrintPerformanceCSV(DVP_Handle handle, DVP_KernelNode_t * pNodes, DVP_U32 numNodes); + +/*! + * \brief This function call printf to list the performance metrics of each section and the overall + * graph performance. + * \param [in] handle The handle to DVP returned from \ref DVP_KernelGraph_Init. + * \param [in] pSection The section to print performance from. + * \ingroup group_performance + */ +void DVP_PrintPerformanceSection(DVP_Handle handle, DVP_KernelGraphSection_t *pSection); + +/*! + * \brief This function call printf to list the performance metrics of each section and the overall + * graph performance. + * \param [in] handle The handle to DVP returned from \ref DVP_KernelGraph_Init. + * \param [in] pGraph The graph to print performance from. + * \ingroup group_performance + */ +void DVP_PrintPerformanceGraph(DVP_Handle handle, DVP_KernelGraph_t *pGraph); + +/*! + * \brief This prints ou the members of the Kernel Node structure. + * \param [in] zone The debugging zone to place the printout in. + * \param [in] node The pointer to the node to print. + * \ingroup group_nodes + */ +void DVP_PrintNode(DVP_U32 zone, DVP_KernelNode_t *node); + +/*! + * \brief This prints out the members of the image structure in the given zone. + * \param [in] zone The debugging zone to place the printout in. + * \param [in] img The pointer to the DVP_Image_t to print. + * \ingroup group_image + */ +void DVP_PrintImage(DVP_U32 zone, DVP_Image_t *img); + +/*! + * \brief This prints out the member of the buffer data structure in the given zone. + * \param [in] zone The debugging zone to place the printout in. + * \param [in] buf The pointer to the buffer to print. + * \ingroup group_buffer + */ +void DVP_PrintBuffer(DVP_U32 zone, DVP_Buffer_t *buf); + +/*! \brief The data range of the capacity limit's + * \ingroup group_capacity + */ +#define DVP_CAPACITY_DATA_RANGE (1000) + +/*! \brief This function returns the capacity for the requested core. + * \param [in] handle The handle to DVP returned from \ref DVP_KernelGraph_Init. + * \param [in] core Core identifier to get. + * \returns A number between 0 and DVP_CAPACITY_DATA_RANGE inclusive. + * \ingroup group_capacity + */ +DVP_U32 DVP_GetCoreCapacity(DVP_Handle handle, DVP_Core_e core); + +/*! \brief This function sets the capacity for the requested core, asssuming it is enabled. + * \param [in] handle The handle to DVP returned from \ref DVP_KernelGraph_Init. + * \param [in] core Core identifier to set. + * \param [in] limit A number between 0 and DVP_CAPACITY_DATA_RANGE inclusive. + * \ingroup group_capacity + */ +void DVP_SetCoreCapacity(DVP_Handle handle, DVP_Core_e core, DVP_U32 limit); + +/*! + * \brief This function returns information about each core in the DVP system. + * \param [in] handle The handle to DVP returned from \ref DVP_KernelGraph_Init. + * \param [in,out] info A preallocated array of DVP_CORE_MAX elems of DVP_CoreInfo_t. + * Use \ref DVP_Core_e to index the array. + * \pre DVP_KernelGraph_Init + * \ingroup group_system + */ +void DVP_QuerySystem(DVP_Handle handle, const DVP_CoreInfo_t info[DVP_CORE_MAX]); + +/*! + * \brief Allows the user to query the system to see which cores implement a + * kernel. + * \param [in] handle The handle to DVP returned from \ref DVP_KernelGraph_Init. + * \param [in] kernel The enumeration of the kernel to search. + * \param [in,out] present An array of size DVP_CORE_MAX, which indicates if the kernel + * is implemented on the core (\ref DVP_Core_e is the index to this array). + * \pre DVP_KernelGraph_Init + * \ingroup group_kernels + */ +void DVP_QueryKernel(DVP_Handle handle, DVP_KernelNode_e kernel, DVP_BOOL present[DVP_CORE_MAX]); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/dvp/dvp_debug.h b/include/dvp/dvp_debug.h new file mode 100644 index 0000000..0bcc3d1 --- /dev/null +++ b/include/dvp/dvp_debug.h @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DVP_DEBUG_H_ +#define _DVP_DEBUG_H_ + +/*! + * \file dvp_debug.h + * \brief Contains the debugging definitions used by internal development. + * \author Erik Rainey + */ + +#ifdef DVP_DEBUG +#include +#if defined(ANDROID) +#include +#endif + +//#pragma message("DVP_DEBUG: Debugging Enabled!") + +/*! \brief A generic assert wrapper. + * \ingroup group_debugging + */ +#define DVP_ASSERT(conditional) if (!(conditional)) {\ + printf("DVP_ASSERT in %s@%u: %s\n", __FILE__, __LINE__, #conditional);\ +} + +#if defined(WIN32) && !defined(CYGWIN) +#include +#ifdef DVP_CONSOLE +/*! \brief An inline function used to get around MS compiler limitations on variable + * arguments to macros. + * \ingroup group_debugging + */ +_inline void DVP_PRINT(int conditional, char *format, ...) { + if (conditional) + { + char string[1024]; + va_list ap; + va_start(ap, format); + vsprintf(string, format, ap); + va_end(ap); + WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), string, strlen(string), NULL, NULL); + } +} +#else +/*! \brief An inline function used to get around MS compiler limitations on variable + * arguments to macros. + * \ingroup group_debugging + */ +_inline void DVP_PRINT(int conditional, char *string, ...) { + if (conditional) + { + va_list ap; + va_start(ap, string); + vprintf(string, ap); + va_end(ap); + } +} +#endif // DVP_CONSOLE +#elif defined(SYSBIOS) +/*! \brief An inline function which allows for variable arguments to the printing function + * the TMS470 Compiler which does not allow variable arguments in macros. + * \param [in] conditional Typically a DVP Zone flag. + * \param [in] string The format string to print. + * \param [in] ... The variable arguments used to fill in the format string. + * \ingroup group_sosal_debug + */ +inline void DVP_PRINT(int conditional, char *string, ...) { + if (conditional) + { + va_list ap; + va_start(ap, string); + vprintf(string, ap); + va_end(ap); + } +} +#else +#if (DVP_DEBUG == 2) && defined(ANDROID) +#include +/*! \brief A wrapper around a platform specific debugging API. + * \param [in] conditional Typically a DVP_ZONE_XXXX defintion. + * \param [in] string A format string + * \param [in] ... Variable arguments to match the format string. + * \ingroup group_debugging + */ +#define DVP_PRINT(conditional, string, ...) if (conditional) { __android_log_print(ANDROID_LOG_DEBUG, #conditional, string, ## __VA_ARGS__); } +#else +/*! \brief A wrapper around a platform specific debugging API. + * \param [in] conditional Typically a DVP_ZONE_XXXX defintion. + * \param [in] string A format string + * \param [in] ... Variable arguments to match the format string. + * \ingroup group_debugging + */ +#define DVP_PRINT(conditional, string, ...) if (conditional) { printf(#conditional ": " string, ## __VA_ARGS__); } +#endif +#endif + +#ifndef DVP_ZONE_MASK +#define DVP_RUNTIME_DEBUG + +/*! \brief The runtime zone mask for DVP. + * \ingroup group_debugging + */ +extern uint32_t dvp_zone_mask; + +/*! The definition of which zones are enabled. Each bit in the mask is an + * individual zone as specified by the zone definitions. + * \ingroup group_debugging + */ +#define DVP_ZONE_MASK dvp_zone_mask +#endif + +#else // ifdef DVP_DEBUG + +#ifndef DVP_ZONE_MASK +/*! \brief The definition of which zones are enabled. Each bit in the mask is an + * individual zone as specified by the zone definitions. + * \ingroup group_debugging + */ +#define DVP_ZONE_MASK (0x00000000) +#endif + +//#pragma message("DVP_DEBUG: No debugging enabled!") + +/*! \brief A wrapper around a platform specific debugging API. + * \param conditional Typically a DVP_ZONE_XXXX defintion. + * \param string A format string + * \param ... Variable arguments to match the format string. + * \ingroup group_debugging + */ +#define DVP_PRINT(conditional, string, ...) {} + +#endif // ifdef DVP_DEBUG + +#define DVP_BIT(x) (1 << (x)) +#define DVP_ZONE_ERROR (DVP_BIT(0) & DVP_ZONE_MASK) /*!< Intended for error cases in all the code. \ingroup group_debugging */ +#define DVP_ZONE_WARNING (DVP_BIT(1) & DVP_ZONE_MASK) /*!< Intended for warning in any code. \ingroup group_debugging */ +#define DVP_ZONE_API (DVP_BIT(2) & DVP_ZONE_MASK) /*!< Intended for API tracing in any code. \ingroup group_debugging */ +#define DVP_ZONE_MOD (DVP_BIT(3) & DVP_ZONE_MASK) /*!< Intended for informational purposes in module loading code only. \ingroup group_debugging */ + +#define DVP_ZONE_RPC (DVP_BIT(4) & DVP_ZONE_MASK) /*!< Intended for informational purposes in RPC code only. \ingroup group_debugging */ +#define DVP_ZONE_MEM (DVP_BIT(5) & DVP_ZONE_MASK) /*!< Intended for informational purposes in MEM code only. \ingroup group_debugging */ +#define DVP_ZONE_KGM (DVP_BIT(6) & DVP_ZONE_MASK) /*!< Intended for informational purposes in any KGM code only. \ingroup group_debugging */ +#define DVP_ZONE_KGB (DVP_BIT(7) & DVP_ZONE_MASK) /*!< Intended for informational purposes in the KGB code only. \ingroup group_debugging */ + +#define DVP_ZONE_LOAD (DVP_BIT(8) & DVP_ZONE_MASK) /*!< Intended for load balanacing information. \ingroup group_debugging */ +#define DVP_ZONE_PERF (DVP_BIT(9) & DVP_ZONE_MASK) /*!< Intended for performance metrics output only. \ingroup group_debugging */ +#define DVP_ZONE_CAM (DVP_BIT(10)& DVP_ZONE_MASK) /*!< Intended for debugging the VisionCam. \ingroup group_debugging */ +#define DVP_ZONE_IMGDBG (DVP_BIT(11)& DVP_ZONE_MASK) /*!< Intended for debugging the Image Debug Library. \ingroup group_debugging */ + +#define DVP_ZONE_VIDEO (DVP_BIT(12)& DVP_ZONE_MASK) /*!< Intended for debugging the display code. \ingroup group_debugging */ +#define DVP_ZONE_KGAPI (DVP_BIT(13)& DVP_ZONE_MASK) /*!< Intended for debugging the multiple graph calling code in the API. \ingroup group_debugging */ +#define DVP_ZONE_ENGINE (DVP_BIT(14)& DVP_ZONE_MASK) /*!< Intended for debugging the VisionEngine. \ingroup group_debugging */ + +#define DVP_ZONE_ALWAYS (1) + +/*! A generic error checking macro which can take a parameterized action + * \param [out] lvalue Typically a status variable. + * \param [in] statement Typically a statement which returns a status variable. + * \param [in] action A block of code to execute when lvalue is a failure code. + * \ingroup group_debugging + */ +#define DVP_DO_IF_FAILED(lvalue, statement, action) {\ + lvalue = statement;\ + if (DVP_FAILED(lvalue)) {\ + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: "#statement" returned error %d! (%s:%u)!\n", lvalue, __FUNCTION__,__LINE__);\ + action;\ + }\ +} + +/*! A generic waring macro when the statement is false. + * \param [in] statement Typically a statement which returns a status variable. + * \ingroup group_debugging + */ +#define DVP_COMPLAIN_IF_FALSE(statement) {\ + if (DVP_FALSE == statement) {\ + DVP_PRINT(DVP_ZONE_WARNING, "WARNING: "#statement" is false! (%s:%u)!\n", __FUNCTION__,__LINE__);\ + }\ +} + +/*! Macro used to check the statement return value and if failed, return immediately. @note The function should return the DVP_Error_e type. \ingroup group_debugging*/ +#define DVP_RETURN_IF_FAILED(lvalue, statement) DVP_DO_IF_FAILED(lvalue, statement, return lvalue); +/*! Macro used to check the statement return value and if failed, break immediately. @note Should only be used in a for or while construct. \ingroup group_debugging */ +#define DVP_BREAK_IF_FAILED(lvalue, statement) DVP_DO_IF_FAILED(lvalue, statement, break); +/*! Macro used to check the statement return value and if failed, continue immediately. @note Should only be used in a for or while construct. \ingroup group_debugging*/ +#define DVP_CONTINUE_IF_FAILED(lvalue, statement) DVP_DO_IF_FAILED(lvalue, statement, continue); +/*! Macro used to check the statement return value and if failed, goto a supplied label immediately. @note The label must exist in the function. \ingroup group_debugging */ +#define DVP_GOTO_IF_FAILED(lvalue, statement, label) DVP_DO_IF_FAILED(lvalue, statement, goto label); + +#endif diff --git a/include/dvp/dvp_display.h b/include/dvp/dvp_display.h new file mode 100644 index 0000000..28bdc6c --- /dev/null +++ b/include/dvp/dvp_display.h @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DVP_DISPLAY_H_ +#define _DVP_DISPLAY_H_ + +/*! + * \file dvp_display.h + * \brief Contains the display code for previewing DVP processed images. + * \author Erik Rainey + */ + +#include +#include + +/*! The default number of display buffers + * \ingroup group_display + */ +#define DVP_DISPLAY_NUM_BUFFERS (5) + +// This may be platform without a display +#if !defined(SCREEN_DIM_X) && !defined(SCREEN_DIM_Y) + +/*! The default display width. + * \ingroup group_display + */ +#define DVP_DISPLAY_WIDTH (1024) + +/*! The default display height. + * \ingroup group_display + */ +#define DVP_DISPLAY_HEIGHT (768) + +#else + +/*! The default display width. + * \ingroup group_display + */ +#define DVP_DISPLAY_WIDTH (SCREEN_DIM_X) + +/*! The default display height. + * \ingroup group_display + */ +#define DVP_DISPLAY_HEIGHT (SCREEN_DIM_Y) + +#endif + +#ifndef _DVP_DISPLAY_T +#define _DVP_DISPLAY_T +typedef uint32_t dvp_display_t; /*!< This type is internally defined to avoid cross-os dependencies. \ingroup group_display */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief Creates a display which is internally HLOS technology dependant. + * \param [in] image_width The width of the raw image + * \param [in] image_height The height of the raw image + * \param [in] buffer_width The width of the allocated buffer holding the image. + * \param [in] buffer_height The height of the allocated buffer holding the image. + * \param [in] display_width The width of the actual display + * \param [in] display_height The height of the actual display + * \param [in] scaled_width The desired rendered width. + * \param [in] scaled_height The desired rendered height + * \param [in] crop_top The pixel position of the top of the image. + * \param [in] crop_left The pixel position of the left of the image. + * \param [in] color The FOURCC color space to use. + * \param [in] rotation The rotation of the display (0,90,180,270). + * \param [in] numBuffers The number of desired buffers to internally allocate. + * \ingroup group_display + */ +dvp_display_t *DVP_Display_Create(uint32_t image_width, uint32_t image_height, + uint32_t buffer_width, uint32_t buffer_height, + uint32_t display_width, uint32_t display_height, + uint32_t scaled_width, uint32_t scaled_height, + uint32_t crop_top, uint32_t crop_left, + fourcc_t color, int32_t rotation, uint32_t numBuffers); + +/*! + * \brief Destroys the DVP Display. + * \param [in,out] dvpd The pointer to the pointer to the display structure. Will return as NULL. + * \pre \ref DVP_Display_Create + * \ingroup group_display + */ +void DVP_Display_Destroy(dvp_display_t **dvpd); + +/*! + * \brief Queues the image to be rendered by the underlying display technology. + * \param [in] dvpd The pointer to the DVP Display Structure. + * \param [in] pImage The pointer to the image to render. Must have been allocated by the \see DVP_Display_Alloc. + * \pre \ref DVP_Display_Create + * \ingroup group_display + */ +void DVP_Display_Render(dvp_display_t *dvpd, DVP_Image_t *pImage); + +/*! + * \brief Internally copies the attributes of an allocated buffer to the pImage structure. + * \param [in] dvpd The pointer to the DVP Display Structure. + * \param [in] pImage The pointer to the image structure to be filled in. + * \note This can only be called equal to the number of allcoated buffers in \see DVP_Display_Create. + * \note This memory is not yet mapped to all remote cores and must be passed to DVP_Image_Alloc with the memory types set to the type corresponding to display buffers. + * \pre \ref DVP_Display_Create + * \ingroup group_display + */ +DVP_BOOL DVP_Display_Alloc(dvp_display_t *dvpd, DVP_Image_t *pImage); + +/*! + * \brief Internally returns the image to the display pool. + * \param [in] dvpd The pointer to the DVP Display structure. + * \param [in] pImage The pointer to the image to be freed. The structure will be zeroed. + * \pre \ref DVP_Display_Alloc + * \ingroup group_display + */ +DVP_BOOL DVP_Display_Free(dvp_display_t *dvpd, DVP_Image_t *pImage); + +/*! + * \brief Internally this causes this frame to be marked as not-rendered + * (if that is needed by the underlying tech). + * \param [in] dvpd The pointer to the DVP Display Structure. + * \param [in] pImage The image to drop. + * \pre \ref DVP_Display_Create + * \ingroup group_display + */ +DVP_BOOL DVP_Display_Drop(dvp_display_t *dvpd, DVP_Image_t *pImage); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/dvp/dvp_mem.h b/include/dvp/dvp_mem.h new file mode 100644 index 0000000..1e69e59 --- /dev/null +++ b/include/dvp/dvp_mem.h @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DVP_MEM_H_ +#define _DVP_MEM_H_ + +/*! \file + * \brief The DVP Memory API. + * \author Erik Rainey + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \brief Unmaps and frees memory from remote cores. + * \param [in] handle The handle to the DVP system. + * \param [in] ptr The pointer to free. + * \param [in] numElem The number of elements in the array. + * \param [in] sizeElem The size of each element. + * \ingroup group_memory + */ +void dvp_free(DVP_Handle handle, DVP_PTR ptr, DVP_U32 numElem, DVP_U32 sizeElem); + +/*! + * \brief Allocates and clears virtual memory, internally takes care of mapping to remote cores. + * \param [in] handle The handle to the DVP system. + * \param [in] numElem The number of elements to allocate. + * \param [in] sizeElem The size of each element in bytes. + * \ingroup group_memory + */ +DVP_PTR dvp_calloc(DVP_Handle handle, DVP_U32 numElem, DVP_U32 sizeElem); + +/*! + * \brief Initializes the image structure to the correct parameters for the color format. + * \note Does not allocate any memory! + * \param [in] pImage The pointer to the structure to be filled in. + * \param [in] width The desired width in pixels. + * \param [in] height The desired height in pixels. + * \param [in] fourcc The desired color space. + * \ingroup group_images + */ +void DVP_Image_Init(DVP_Image_t *pImage, DVP_U32 width, DVP_U32 height, fourcc_t fourcc); + +/*! + * \brief Allocates and maps an image to all enabled remote cores. + * \param [in] handle The handle to DVP. + * \param [in] pImage The pointer to the initialized image structure. + * \param [in] dvpMemType The desired memory allocation type. + * \note Display buffers are already allocated if acquired through DVP_Display_Alloc. Use an appropriate mem type which will not cause a reallocation. + * \ingroup group_images + */ +DVP_BOOL DVP_Image_Alloc(DVP_Handle handle, DVP_Image_t *pImage, DVP_MemType_e dvpMemType); + +/*! + * \brief Unmaps and Frees the allocated memory in the image. + * \param [in] handle The handle to DVP. + * \param [in] pImage The pointer to the image structure whose data will be freed. The structure will NOT be cleared afterward. + * \ingroup group_images + */ +DVP_BOOL DVP_Image_Free(DVP_Handle handle, DVP_Image_t *pImage); + +/*! + * \brief Performs the necessary operations to share this image with another process + * \param [in] handle The handle to DVP. + * \param [in] pImage The pointer to the image structure whose data will be shared. + * \param [in] shared_fds the file descriptors that can be used to import this image in a different process + * \note the shared_fds array size must match the number of planes in the image + * \ingroup group_images + */ +DVP_BOOL DVP_Image_Share(DVP_Handle handle, DVP_Image_t *pImage, DVP_S32 *shared_fds); + +/*! + * \brief Import the image into the calling process + * \param [in] handle The handle to DVP. + * \param [in] pImage The pointer to the image structure whose data will be imported. + * \param [in] shared_fds the file descriptors obtained from DVP_Image_Share + * \param [in] hdls internal handles, needed to free the image through DVP_Image_Free_Import + * \note the hdls array size must match the number of planes in the image + * \note This image can only be freed through DVP_Image_Free_Import + * \ingroup group_images + */ +DVP_BOOL DVP_Image_Import(DVP_Handle handle, DVP_Image_t *pImage, DVP_S32 *shared_fds, DVP_VALUE *hdls); + +/*! + * \brief Free an imported image + * \param [in] handle The handle to DVP. + * \param [in] pImage The pointer to the image structure whose data will be freed. + * \param [in] hdls the internal handles obtained during DVP_Image_Import + * \note only imported images can be freed through this API + * \ingroup group_images + */ +DVP_BOOL DVP_Image_Free_Import(DVP_Handle handle, DVP_Image_t *pImage, DVP_VALUE *hdls); + +/*! + * \brief Deinitializes the image structure. + * \param [in] pImage the data structure to clear. + * \ingroup group_images + */ +void DVP_Image_Deinit(DVP_Image_t *pImage); + +/*! + * \brief Copies a flat buffer into a DVP Image structure. + * \param pImage The image to fill. + * \param ptr The pointer to the data to fill from. + * \param size The number of bytes in ptr. + * \ingroup group_images + */ +void DVP_Image_Fill(DVP_Image_t *pImage, DVP_S08 *ptr, uint32_t size); + +/*! + * \brief Copies the source image to the destination image with no conversions other than stride. + * \param [in] pDst The destination image. + * \param [in] pSrc The source image. + * \ingroup group_images + */ +DVP_BOOL DVP_Image_Copy(DVP_Image_t *pDst, DVP_Image_t *pSrc); + +/*! + * \brief Duplicates the source DVP_Image_t structure into another structure. No image data is copied, only metadata. + * \param [in] dst The destintation image metadata structure. + * \param [in] src The source image metadata structure. + * \ingroup group_images + */ +void DVP_Image_Dup(DVP_Image_t* dst, DVP_Image_t *src); + +/*! + * \brief Serializes the meta data about the image and the image itself into a flat buffer. + * \param [in] pImage The image to serialize. + * \param [in] buffer The buffer to serialize into. + * \param [in] len The length of the buffer to prevent overflows. + * \ingroup group_images + */ +size_t DVP_Image_Serialize(DVP_Image_t *pImage, uint8_t *buffer, size_t len); + +/*! + * \brief Unserializes the meta data and the image from a flat buffer. + * \param [in] pImage The image to unserialize. + * \param [in] buffer The buffer to unserialize from. + * \param [in] len The length of the buffer to prevent overflows. + * \ingroup group_images + */ +size_t DVP_Image_Unserialize(DVP_Image_t *pImage, uint8_t *buffer, size_t len); + +/*! + * \brief Calculates the size of the plane indexed as given. + * \param [in] pImage The image pointer to calculate the plane size of. + * \param [in] plane The plane index to use to get the size from. + * \ingroup group_images + */ +DVP_U32 DVP_Image_PlaneSize(DVP_Image_t *pImage, DVP_U32 plane); + +/*! + * \brief Calculates the byte size of all the data in the image. + * \param [in] pImage The pointer to the image structure. + * \ingroup group_images + */ +DVP_U32 DVP_Image_Size(DVP_Image_t *pImage); + +/*! + * \brief Allocates and maps a flat buffer to all remote cores. + * \param [in] handle The handle to DVP. + * \param [in] pBuffer The pointer to the buffer structure to fill in. + * \param [in] dvpMemType The memory type requested. + * \ingroup group_buffers + */ +DVP_BOOL DVP_Buffer_Alloc(DVP_Handle handle, DVP_Buffer_t *pBuffer, DVP_MemType_e dvpMemType); + +/*! + * \brief Unmaps and Frees the allocated buffer. + * \param [in] handle The handle to DVP. + * \param [in] pBuffer the pointer to the buffer structure to free. + * \ingroup group_buffers + */ +DVP_BOOL DVP_Buffer_Free(DVP_Handle handle, DVP_Buffer_t *pBuffer); + +/*! + * \brief Performs the necessary operations to share this buffer with another process + * \param [in] handle The handle to DVP. + * \param [in] pBuffer The pointer to the buffer structure whose data will be shared. + * \param [in] shared_fd the file descriptor that can be used to import this buffer in a different process + * \ingroup group_buffers + */ +DVP_BOOL DVP_Buffer_Share(DVP_Handle handle, DVP_Buffer_t *pBuffer, DVP_S32 *shared_fd); + +/*! + * \brief Import the buffer into the calling process + * \param [in] handle The handle to DVP. + * \param [in] pBuffer The pointer to the buffer structure whose data will be imported. + * \param [in] shared_fd the file descriptor obtained from DVP_Buffer_Share + * \param [in] hdl internal buffer handle, needed to free the image through DVP_Buffer_Free_Import + * \note This buffer can only be freed through DVP_Buffer_Free_Import + * \ingroup group_buffers + */ +DVP_BOOL DVP_Buffer_Import(DVP_Handle handle, DVP_Buffer_t *pBuffer, DVP_S32 shared_fd, DVP_VALUE *hdl); + +/*! + * \brief Free an imported buffer + * \param [in] handle The handle to DVP. + * \param [in] pBuffer The pointer to the buffer structure whose data will be freed. + * \param [in] hdl the internal buffer handle obtained during DVP_Buffer_Import + * \note only imported buffers can be freed through this API + * \ingroup group_buffers + */ +DVP_BOOL DVP_Buffer_Free_Import(DVP_Handle handle, DVP_Buffer_t *pBuffer, DVP_VALUE hdl); + +/*! + * \brief Initializes the buffer structure to the correct parameters. + * \note Does not allocate any memory! + * \param [in] pBuffer The pointer to the structure to be initialized. + * \param [in] elemSize The size of an individual element. + * \param [in] numBytes The total number of bytes to be requested. + * \ingroup group_buffers + */ +void DVP_Buffer_Init(DVP_Buffer_t *pBuffer, DVP_U32 elemSize, DVP_U32 numBytes); + +/*! + * \brief Deinitializes the image structure. + * \param [in] pBuffer the data structure to clear. + * \ingroup group_buffers + */ +void DVP_Buffer_Deinit(DVP_Buffer_t *pBuffer); + +/*! + * \brief The function allocates the requested number of DVP_KernelNode_t structures in shared memory and maps them to all enabled remote cores. + * \param [in] handle The handle to DVP. + * \param [in] numNodes The desired number of contigiuous node structures. + * \return DVP_KernelNode_t Returns a mapped array of Nodes. + * \note The nodes will be allocated with \ref DVP_MTYPE_KERNELGRAPH. + * \ingroup group_nodes + */ +DVP_KernelNode_t *DVP_KernelNode_Alloc(DVP_Handle handle, DVP_U32 numNodes); + +/*! + * \brief Unmaps and Frees the supplied node array for the number of nodes requested. + * \param [in] handle The handle to DVP. + * \param [in] pNodes The array of nodes. + * \param [in] numNodes The number of nodes that pNodes points to. + * \ingroup group_nodes + */ +void DVP_KernelNode_Free(DVP_Handle handle, DVP_KernelNode_t *pNodes, DVP_U32 numNodes); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/dvp/dvp_types.h b/include/dvp/dvp_types.h new file mode 100644 index 0000000..78af0d1 --- /dev/null +++ b/include/dvp/dvp_types.h @@ -0,0 +1,1372 @@ +/* ==================================================================== + * Copyright (C) 2012 Texas Instruments Incorporated + * ==================================================================== */ + +#ifndef _DVP_TYPES_H_ +#define _DVP_TYPES_H_ + +//****************************************************************************** +// INCLUDES +//****************************************************************************** + +#include +#include +#if !defined(SYSBIOS) +#include +#elif defined(SYSBIOS) && defined(CENTEVE) +#include +#endif + +//****************************************************************************** +// DEFINES +//****************************************************************************** + +/*! \brief Major Interface Version Number. + * \ingroup group_system + */ +#define DVP_VERSION_MAJOR (0x0002) + +/*! \brief Minor Interface Version Number. + * \ingroup group_system + */ +#define DVP_VERISON_MINOR (0x0000) + +/*! \brief The version number of the interface. + * \ingroup group_system + */ +#define DVP_VERSION ((DVP_VERSION_MAJOR << 16) | DVP_VERISON_MINOR) + +#if defined(ANDROID) || defined(LINUX) || defined(SYSBIOS) || defined(__QNX__) || defined(DARWIN) +#ifndef PAGE_SIZE +#define PAGE_SIZE (4096) +#endif +#define DVP_PAGE_SIZE (PAGE_SIZE) +#else +#define DVP_PAGE_SIZE (4096) +#endif + +#define DVP_MAX_NAME (32) + +#ifndef MAX_PATH +#define MAX_PATH (255) +#endif + +/*! \brief The maximum number of subplanes of an image. + * \ingroup group_images + */ +#define DVP_MAX_PLANES (4) + +#if defined(SYSBIOS) && !defined(CENTEVE) +#define MAX_RTIMER_T (0xFFFFFFFFFFFFFFFF) +#define rtimer_freq() (CLOCKS_PER_SEC) +#endif + +// Default Systems Configuration +#if defined(ARM) && defined(ANDROID) && (defined(FROYO) || defined(GINGERBREAD)) +#ifndef DVP_USE_TILER +#define DVP_USE_TILER +#endif +#elif defined(ARM) && defined(ANDROID) && (defined(ICS) || defined(JELLYBEAN)) +#ifndef DVP_USE_ION +#define DVP_USE_ION +#endif +#ifndef DVP_USE_GRALLOC +#define DVP_USE_GRALLOC +#endif +#elif defined(ANDROID) // NDK or external users (we assume ICS NDK) +#ifndef DVP_USE_ION +#define DVP_USE_ION +#endif +#ifndef DVP_USE_GRALLOC +#define DVP_USE_GRALLOC +#endif +#ifndef DVP_USE_SHARED_T +#define DVP_USE_SHARED_T +#endif +#elif defined(ARM) && defined(LINUX) +#ifndef DVP_USE_BO +#define DVP_USE_BO +#endif +#elif defined(ARM) && defined(__QNX__) +#ifndef DVP_USE_TILER +#define DVP_USE_TILER +#endif +#endif + +//****************************************************************************** +// ENUMERATIONS AND TYPEDEFS +//****************************************************************************** + +/*! \brief A signed 8 bit value. + * \ingroup group_types + */ +typedef int8_t DVP_S08; + +/*! \brief A signed 16 bit value. + * \ingroup group_types + */ +typedef int16_t DVP_S16; + +/*! \brief A signed 32 bit value. + * \ingroup group_types + */ +typedef int32_t DVP_S32; + +/*! \brief A signed 64 bit value. + * \ingroup group_types + */ +typedef int64_t DVP_S64; + +/*! \brief An unsigned 8 bit value. + * \ingroup group_types + */ +typedef uint8_t DVP_U08; + +/*! \brief An unsigned 16 bit value. + * \ingroup group_types + */ +typedef uint16_t DVP_U16; + +/*! \brief An unsigned 32 bit value. + * \ingroup group_types + */ +typedef uint32_t DVP_U32; + +/*! \brief An unsigned 64 bit value. + * \ingroup group_types + */ +typedef uint64_t DVP_U64; + +#if defined(SYSBIOS) && !defined(CENTEVE) + +/*! \brief A generic pointer. + * \ingroup group_types + */ +typedef void *DVP_PTR; + +/*! \brief An architecture depth defined generic value. + * \ingroup group_types + */ +typedef size_t DVP_VALUE; + +#ifndef FMT_RTIMER_T +/*! \brief For platforms without SOSAL, this is a 64 bit unsigned number. + * \ingroup group_types + */ +typedef uint64_t rtime_t; +#endif + +#else // on other platforms, use SOSAL's definitions + +/*! \brief A DVP typedef for a SOSAL type. + * \ingroup group_types + */ +typedef ptr_t DVP_PTR; + +/*! \brief A DVP typedef for a SOSAL type. + * \ingroup group_types + */ +typedef value_t DVP_VALUE; + +#endif + +/*! \brief A fixed size enumeration field used to force compilers to + * not automatically downsize fields. + * \ingroup group_types + */ +typedef int32_t DVP_ENUM; + +/*! + * \brief This is a simple boolean typedef for DVP functions. + * \ingroup group_types + */ +typedef enum _dvp_bool_e { + DVP_FALSE = 0, /*!< Logically false */ + DVP_TRUE, /*!< Logically true */ +} DVP_BOOL; + +/*! + * \brief These errors can be returned by the DVP_KernelGraphManager_Init call on the remote cores. + * \ingroup group_system + */ +typedef enum _dvp_error_e { + DVP_ERROR_NO_RESOURCE = -10, /*!< A critical resource was not available. */ + DVP_ERROR_NO_MEMORY = -9, /*!< There was not enough memory to complete the operation */ + DVP_ERROR_INVALID_PARAMETER = -8, /*!< A supplied parameter was incorrect */ + DVP_ERROR_NOT_IMPLEMENTED = -7, /*!< The requested operation has not been implemented */ + DVP_ERROR_VERSION_MISMATCH = -1, /*!< The initialization of the remote KGM failed due to a DVP mismatch */ + DVP_ERROR_FAILURE = 0, /*!< Generic Failure */ + DVP_SUCCESS = 1, /*!< Success */ +} DVP_Error_e; + +/*! \brief Resolves to non-zero when DVP_Error_e codes return any failure + * \ingroup group_debugging + */ +#define DVP_FAILED(x) (x <= DVP_ERROR_FAILURE) + +/*! \brief Resolves to non-zero when DVP_Error_e codes are successful + * \ingroup group_debugging + */ +#define DVP_PASSED(x) (x == DVP_SUCCESS) + +/*! + * \brief This structure defines a 1d buffer used with some DVP kernels. + * \ingroup group_buffers + */ +typedef struct _dvp_buffer_t { + DVP_U08 *pData; /*!< The pointer to the data region */ + DVP_U32 elemSize; /*!< The size of each element in the buffer */ + DVP_U32 numBytes; /*!< The number of bytes allocated for the entire buffer */ + DVP_U32 memType; /*!< The memory mapping type, options are DVP_MemType_e enumeration */ + DVP_PTR reserved; /*!< Used for internal tracking */ + DVP_S32 skipCacheOpInval; /*!< Used to indicate to the DVP lower layers to skip cache operations for this image because it will not be used on the local core */ + DVP_S32 skipCacheOpFlush; /*!< Used to indicate to the DVP lower layers to skip cache operations for this image because it will not be used on the local core */ +} DVP_Buffer_t; + +/*! + * \brief This enumeration defines the memory types used in DVP. + * \ingroup group_system + */ +typedef enum _dvp_mtype_e { + DVP_MTYPE_MPUCACHED_VIRTUAL = 0, /*!< MPU has a cached virtual view of the memory, but the accelerators can not be utilized in this memory */ +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + DVP_MTYPE_MPUCACHED_1DTILED, /*!< MPU has a cached virtual view of the memory, and the accelerators can access it as contiguous 1D tiled memory */ + DVP_MTYPE_MPUNONCACHED_1DTILED, /*!< MPU has a non-cached 1D virtual view of the memory, and the accelerators can operate 1D tiled memory (test mode) */ + DVP_MTYPE_MPUNONCACHED_2DTILED, /*!< MPU has a non-cached 2D virtual view of the memory, and the accelerators can operate optimally with 2D tiled memory */ +#endif + //#if defined(DVP_USE_TILER) || defined(DVP_USE_GRALLOC) + DVP_MTYPE_DISPLAY_2DTILED, /*!< MPU has a non-cached 2D virtual view of memory allocated out of the display subsystem */ + //#endif +#if defined(DVP_USE_GRALLOC) || defined(DVP_USE_BO) + DVP_MTYPE_GRALLOC_2DTILED, /*!< MPU allocated GFX 2D buffers */ +#endif +#if defined(DVP_USE_SHARED_T) + DVP_MTYPE_MPUCACHED_VIRTUAL_SHARED, /*!< MPU has a cached virtual view of the memory, but the accelerators can not be utilized in this memory. The memory can be shared among processes.*/ +#endif + DVP_MTYPE_MAX, + + /*! The default memory allocation type on the platform. */ +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) + DVP_MTYPE_DEFAULT = DVP_MTYPE_MPUCACHED_1DTILED, +#elif defined(DVP_USE_BO) + DVP_MTYPE_DEFAULT = DVP_MTYPE_MPUCACHED_1DTILED, +#else + DVP_MTYPE_DEFAULT = DVP_MTYPE_MPUCACHED_VIRTUAL, +#endif + + /*! The memory type used to contain command structures shared across mulitple cores */ +#if defined(DVP_USE_ION) + DVP_MTYPE_KERNELGRAPH = DVP_MTYPE_MPUNONCACHED_1DTILED, +#elif defined(DVP_USE_BO) + DVP_MTYPE_KERNELGRAPH = DVP_MTYPE_MPUNONCACHED_1DTILED, +#else + DVP_MTYPE_KERNELGRAPH = DVP_MTYPE_MPUCACHED_VIRTUAL, +#endif +} DVP_MemType_e; + +/*! + * \brief The image structure defines a 1D, or 2D image of up to DVP_MAX_PLANES with arbitrary pixel depth and line stride. + * \ingroup group_images + */ +typedef struct _dvp_image_t { + DVP_U08 *pData[DVP_MAX_PLANES]; /*!< The byte pointer to the image data, the color type will indicate how this pointer is indexed. Each plane has a separate pointer. Up to DVP_MAX_PLANES are supported */ + DVP_U08 *pBuffer[DVP_MAX_PLANES]; /*!< The raw allocated buffers per plane. */ + DVP_U32 planes; /*!< This indicates the number of planes in the planes array. An interleaved format will only have 1 plane. */ + DVP_U32 width; /*!< pixel width of the (sub-)image */ + DVP_U32 height; /*!< pixel height of the (sub-)image */ + DVP_U32 bufWidth; /*!< pixel width of the raw image */ + DVP_U32 bufHeight; /*!< pixel height of the raw image */ + DVP_U32 x_start; /*!< X Pixel Offset into the raw image for sub-image */ + DVP_U32 y_start; /*!< Y Pixel Offset into the raw image for sub-image */ + DVP_S32 x_stride; /*!< byte distance from one pixel to the next pixel in the x direction, not necessarily the same as pixel size */ + DVP_S32 y_stride; /*!< byte distance from one pixel to the next pixel in the y direction, not necessarily the same as pixel size times width. Note: all planes should use the same stride, thus should be allocated identically. Subsampled planes will be overallocated. */ + DVP_U32 color; /*!< used a FourCC code (http://www.fourcc.org) \see fourcc_t */ + DVP_U32 numBytes; /*!< The allocated byte size of this image */ + DVP_U32 memType; /*!< The memory mapping type, \see DVP_MemType_e */ + DVP_PTR reserved; /*!< Used for internal tracking */ + DVP_S32 skipCacheOpInval; /*!< Used to indicate to the DVP lower layers to skip cache operations for this image because it will not be used on the local core */ + DVP_S32 skipCacheOpFlush; /*!< Used to indicate to the DVP lower layers to skip cache operations for this image because it will not be used on the local core */ +} DVP_Image_t; + +/*! + * \brief This structure allows for image write-out during graph execution for debugging. + * The name of the file will be determeined by the PYUV library. The name here will + * be used to uniquely identify the file. The full filename will be stored in fullname. + * \ingroup group_kernels + */ +typedef struct _dvp_image_debug_t { + DVP_Image_t image; /*!< The image to dump */ + char name[DVP_MAX_NAME]; /*!< The short prefix name of the file. */ + char path[MAX_PATH]; /*!< The path to store the file in */ + char fullname[MAX_PATH]; /*!< The full path qualified name of the file */ +#if defined(DVP_USE_FS) + FILE *fp; /*!< (Internal) The open FILE pointer */ +#endif +} DVP_ImageDebug_t; + +/*! + * \brief This structure allows for buffer write-out during graph execution for debugging. + * \ingroup group_kernels + */ +typedef struct _dvp_buffer_debug_t { + DVP_Buffer_t buffer; /*!< The buffer to dump. */ + char fullname[MAX_PATH]; /*!< The full path qualified name of the file */ +#if defined(DVP_USE_FS) + FILE *fp; /*!< (Internal) The open FILE pointer */ +#endif +} DVP_BufferDebug_t; + +/*! + * \brief A transform structure is used on any kernel which goes from one image format to another with no parameters needed other than the parameters of the supplied images. + * \ingroup group_kernels + */ +typedef struct _dvp_transform_t { + DVP_Image_t input; /*!< Input image */ + DVP_Image_t output; /*!< Output image */ +} DVP_Transform_t; + +/*! + * \brief This structure is used in conjunction with Morphology operations like Erosion and Dilation. + * \ingroup group_kernels + */ +typedef struct _dvp_morphology_t { + DVP_Image_t input; /*!< Input image */ + DVP_Image_t output; /*!< Output image */ + DVP_Image_t mask; /*!< Mask matrix, only used with mask operations */ +} DVP_Morphology_t; + +/*! + * \brief This structure is used in kernels that need bounding information. + * \ingroup group_kernels + */ +typedef struct _dvp_bounds_t { + DVP_U08 *pData; /*!< Boundary array */ + DVP_U32 width; /*!< Width */ + DVP_U32 height; /*!< Height */ +} DVP_Bounds_t; + +/*! + * \brief This structure is used with IIR Filters. + * \ingroup group_kernels + */ +typedef struct _dvp_iir_t { + DVP_Image_t input; /*!< Input image */ + DVP_Image_t output; /*!< Output image */ + DVP_Bounds_t bounds[2]; /*!< Horz={left, right}, Vert={top,bottom} */ + DVP_Image_t scratch; // \TODO remove + DVP_U16 weight; /*!< Weight */ +} DVP_IIR_t; + +/*! + * \brief This strucutre is used with Image Convolution operations. + * \ingroup group_kernels + */ +typedef struct _dvp_image_conv_t { + DVP_Image_t input; /*!< Input image */ + DVP_Image_t output; /*!< Output image */ + DVP_Image_t mask; /*!< A signed 8-bit mask matrix (3x3, 5x5, 7x7, or MxN) */ + DVP_U16 shiftMask; /*!< Number of bits to right shift the mask values */ +} DVP_ImageConvolution_t; + +/*! + * \brief This structure is used with Canny 2d Gradients. + * \ingroup group_kernels + */ +typedef struct _dvp_canny_2d_gradient_t { + DVP_Image_t input; /*!< Input image, 8bit */ + DVP_Image_t outGradX; /*!< Output horizontal gradient, 16bit */ + DVP_Image_t outGradY; /*!< Output vertical gradient, 16bit */ + DVP_Image_t outMag; /*!< Output magnitude, 16bit */ +} DVP_Canny2dGradient_t; + +/*! + * \brief This structure is used with Canny Non-maximum suppression. + * \ingroup group_kernels + */ +typedef struct _dvp_canny_non_maximum_t { + DVP_Image_t inMag; /*!< Input magnitude, 16bit */ + DVP_Image_t inGradX; /*!< Input horizontal gradient, 16bit */ + DVP_Image_t inGradY; /*!< Input vertical gradient, 16bit */ + DVP_Image_t output; /*!< Output image, 8bit */ +} DVP_CannyNonMaxSuppression_t; + +/*! + * \brief This structure is used with Canny Hysterisis Threshholding. + * \ingroup group_kernels + */ +typedef struct _dvp_canny_hyst_thresh_t { + DVP_Image_t inMag; /*!< Input magnitude, 16bit */ + DVP_Image_t inEdgeMap; /*!< Input edge map, 8bit */ + DVP_Image_t output; /*!< Output image, 8bit */ + DVP_U08 loThresh; /*!< Input lower threshold */ + DVP_U08 hiThresh; /*!< Input upper threshold */ + DVP_U32 numEdges; /*!< Output number of edges */ +} DVP_CannyHystThresholding_t; + +/*! + * \brief This structure is used with thresholding operations. + * \ingroup group_kernels + */ +typedef struct _dvp_threshold_t { + DVP_Image_t input; /*!< Input image */ + DVP_Image_t output; /*!< Output image */ + DVP_S16 thresh; /*!< Threshold value */ +} DVP_Threshold_t; + +/* + * \brief This structure is used with inteleaved to planar(more than 8bits) kernels. + * \ingroup group_kernels + */ +typedef struct _dvp_int2pl_t { + DVP_Image_t input; /*!< Input image */ + DVP_Image_t output1; /*!< Output image 1 */ + DVP_Image_t output2; /*!< Output image 2 */ + DVP_Image_t output3; /*!< Output image 3 */ + DVP_Buffer_t scratch; /*!< Scratch buffer */ + DVP_S32 factor; /*!< Factor value */ +} DVP_Int2Pl_t; + +/*! + * \brief This structure is used with SAD Kernels. + * \ingroup group_kernels + */ +typedef struct _dvp_sad_t { + DVP_Image_t input; /*!< Input image */ + DVP_Image_t output; /*!< Output image */ + DVP_Image_t refImg; /*!< Reference image */ + DVP_U16 shiftMask; /*!< Downshift value */ + DVP_U32 refPitch; /*!< Reference pitch */ + DVP_U16 refStartOffset; /*!< Reference offset */ +} DVP_SAD_t; + +/*! + * \brief This structure is used with Histogram Kernels. + * \ingroup group_kernels + */ +typedef struct _dvp_histogram_t { + DVP_Image_t input; /*!< Input Image */ + DVP_Buffer_t edges; /*!< Edges of each bin, array size=numBins, the last edge in this array is its own bin */ + DVP_U32 numBins; /*!< Used for weighted and nonweighted 1D histograms; must be a multiple of 2 */ + DVP_U32 dimX; /*!< Used for nD histograms; must be a multiple of 2 */ + DVP_U16 binWeight; /*!< Used for normal histograms */ + DVP_U16 clearFlag; /*!< When set to 1, the output is automatically cleared before processing */ + DVP_Buffer_t numBinsArray; /*!< Used for weighted nD histograms */ + DVP_Buffer_t binWeights; /*!< Used for weighted histograms */ + DVP_Buffer_t hOut; /*!< Final output Histogram, size=numBins */ + DVP_Buffer_t histArray; /*!< Internal scratch memory; initialize to 0 first time, size = largest expected input value+1 */ + DVP_Buffer_t h[3]; /*!< Internal scratch memory; h[0] needed for 16bit & all h[0,1,2] needed for 8bit; size=numBins */ + DVP_Buffer_t scratch; /*!< Internal scratch memory; Used in the ND histogram */ +} DVP_Histogram_t; + +/*! \brief This structure is used with Gamma kernels. + * \ingroup group_gamma + */ +typedef struct _dvp_gamma_t { + DVP_Image_t input; + DVP_Image_t output; + DVP_U08 gammaLut[256]; +} DVP_Gamma_t; + +/*! \brief An enumeration of all registered DVP feature sets. Features are generic + * kernels that least two or more libraries implement. Implementations must be data-equivalent. + * \ingroup group_kernels + */ +typedef enum _dvp_kfeat_e { + DVP_KF_INVALID = 0, /*!< An invalid kernel feature range */ + DVP_KF_DEBUG, /*!< The debugging features range */ + DVP_KF_COLOR_CONVERT, /*!< The color conversion feature range */ + DVP_KF_FILTER, /*!< The image convolution feature range */ + DVP_KF_MORPH, /*!< The image mophology feature range */ + DVP_KF_CANNY, /*!< The canny image features range */ + DVP_KF_CONVERT, /*!< The image bit depth conversion feature range */ + DVP_KF_IIR, /*!< The recursive image first order filters */ + DVP_KF_NONMAXSUPPRESS, /*!< The non-maximum suppression filters */ + DVP_KF_CONV, /*!< The image convolution filters */ + DVP_KF_THR, /*!< The image thresholding filters */ + DVP_KF_SOBEL, /*!< The image sobel edge filters */ + DVP_KF_INTEGRAL, /*!< The integral feature range */ + DVP_KF_OPTIMIZED = 0x30000, /*!< This base range will used for local KGM optimized implementations */ + DVP_KF_MAX = 0x40000, /*!< This is the maximum feature set range */ +} DVP_KernelFeature_e; + +/*! \brief An enumeration of all registered DVP algorithm libraries. This values are used to set the algo-specific ranges. + * \ingroup group_kernels + */ +typedef enum _dvp_klib_e { + DVP_KL_INVALID = 0, /*!< The invalid kernel range. */ + DVP_KL_YUV, /*!< A set of NEON functions designed around YUV color spaces */ + DVP_KL_IMGFILTER, /*!< A set of NEON functions designed around 3x3 convolutions, and 3x1 filters */ + DVP_KL_OCL, /*!< A set of predefined OpenCL kernels. */ + DVP_KL_VLIB, /*!< Texas Instruments Vision Library 2.2 */ + DVP_KL_IMGLIB, /*!< Texas Instruments Imaging Library */ + DVP_KL_RVM, /*!< Texas Instruments Rear-View Module for Homography Transforms */ + DVP_KL_VRUN, /*!< Texas Instruments VRUN algo library for iMX */ + DVP_KL_TISMO, /*!< Texas Instruments Stereo Module */ + DVP_KL_ORB, /*!< A fast ORB implementation */ + DVP_KL_ARTI, /*!< Augmented Reality Library from Texas Instruments */ + DVP_KL_POINTCLOUD, /*!< A point-cloud library */ + DVP_KL_DSPLIB, /*!< A set of DSP optimized algorithms */ + DVP_KL_DEI, /*!< Deinterlacer algorithm library */ + // new libraries get added here + DVP_KL_EXTERNAL_LIBRARIES = 0x80, /*!< 3rd parties can add algos libraries from here */ + DVP_KL_LIBRARY_MAX = 0xFF, /*!< The maximum library set */ +} DVP_KernelLibrary_e; + +/*! \brief The maxium range a library set can have. + * \ingroup group_kernels + */ +#define DVP_KN_RANGE (0x1000) // 4096 kernels per library should be sufficient? + +/*! \brief We cut the enum space in half. The lower half is for "features" which multiple libraries may overload. + * \ingroup group_kernels + */ +#define DVP_KN_FEATURE_START (0x0) + +/*! \brief The upper half of the kernel space is for libraries to have explicitly targeted kernels. + * \ingroup group_kernels + */ +#define DVP_KN_LIBRARY_START (0x40000000) + +/*! \brief Used to retrieve the library which a kernel is in. + * \ingroup group_kernels + */ +#define DVP_KN_LIBRARY_MASK(k) ((0x000FF000 & k) >> 12) + +/*! + * \brief Set your base kernel enum to your DVP_KN_LIBRARY_BASE(DVP_KL_XXXXX) + * \ingroup group_kernels + */ +#define DVP_KN_LIBRARY_BASE(library) (DVP_KN_LIBRARY_START + (library * DVP_KN_RANGE)) + +/*! + * \brief Sets the base value of a feature set. + * \ingroup group_kernels + */ +#define DVP_KN_FEATURE_BASE(set) (DVP_KN_FEATURE_START + (set * DVP_KN_RANGE)) + +/*! \brief An enumeration of all possible DVP kernels (or functions). + * \note New features should be added either in existing ranges if applicable but + * always at the _end_ of a range. + * \ingroup group_kernels + */ +typedef enum _dvp_knode_e { + DVP_KN_INVALID = 0, /*!< An undefined kernel */ + + /*! + * \brief Debug Feature Base + * \note This is a placeholder enumeration, not a valid kernel + */ + DVP_KF_DEBUG_BASE = DVP_KN_FEATURE_BASE(DVP_KF_DEBUG), + + /*! + * Copies the input image to the output memory\n + * Configuration Structure: DVP_Transform_t + */ + DVP_KN_ECHO, + + /*! + * Writes an images to a file\n + * Configuration Structure: DVP_ImageDebug_t + */ + DVP_KN_IMAGE_DEBUG, + + /*! + * Writes a buffer to a file\n + * Configuration Structure: DVP_BufferDebug_t + */ + DVP_KN_BUFFER_DEBUG, + + /*! + * No Operation kernel. Used, typically during debug, to turn a kernel off from executing + * without modifying the remainder of the kernel node structure. This can be done by replacing + * the kernel function name with "DVP_KGM_NOOP".\n + * Configuration Structure: Not Applicable + */ + DVP_KN_NOOP, + + /*! + * \brief Color Conversion Feature Base + * \note This is a placeholder enumeration, not a valid kernel + */ + DVP_KF_COLOR_CONVERT_BASE = DVP_KN_FEATURE_BASE(DVP_KF_COLOR_CONVERT), + + /*! + * Converts FOURCC_UYVY or FOURCC_VYUY to FOURCC_Y800 image\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY or FOURCC_VYUY + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_XYXY_TO_Y800, + + /*! + * Converts FOURCC_YVYU or FOURCC_YUY2 format to FOURCC_Y800 image.\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_YVYU or FOURCC_YUY2 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_YXYX_TO_Y800, + + /*! + * Converts 1 plane 8 bit per pixel luma to FOURCC_UYVY\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_UYVY + */ + DVP_KN_Y800_TO_XYXY, + + /*! + * Converts FOURCC_UYVY format to 8 bits per pixels planar RGB using BT.601. (VLIB-API.Sec 58.0)\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_RGBP + */ + DVP_KN_UYVY_TO_RGBp, + + /*! + * Converts FOURCC_UYVY format to FOURCC_IYUV or FOURCC_YV12 format. Chroma planes are downsampled vertically. (VLIB-API.Sec 55.0)\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_IYUV or FOURCC_YV12 + */ + DVP_KN_UYVY_TO_YUV420p, + + /*! + * Converts FOURCC_UYVY format to FOURCC_YU16 or FOURCC_YV16 format. (VLIB-API.Sec 54.0)\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_YV16 or FOURCC_YU16 + */ + DVP_KN_UYVY_TO_YUV422p, + + /*! + * Converts FOURCC_UYVY format to FOURCC_YU24 or FOURCC_YV24 format. Chroma planes are doubled.\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_YV24 or FOURCC_YU24 + */ + DVP_KN_UYVY_TO_YUV444p, + + /*! + * Converts FOURCC_UYVY format to 1 plane 8 bit pixel packed BGR byte ordered 24 bit per pixel format (FOURCC_BGR) using BT.601\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_BGR + */ + DVP_KN_UYVY_TO_BGR, + + /*! + * Converts FOURCC_UYVY format to 1 plane 565 bit pixel packed BGR ordered format (FOURCC_RGB565) using BT.601 \n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_RGB565 + */ + DVP_KN_YUV422p_TO_RGB565, + + /*! + * Converts FOURCC_UYVY format to 3 plane HSV (Hue, Saturation, Value) 8 bit per plane format. (VLIB-API.Sec 56.0) \n + * Configuration Structure: DVP_Int2Pl_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output1] Image color type supported: FOURCC_Y16 + * \param [output2] Image color type supported: FOURCC_Y800 + * \param [output3] Image color type supported: FOURCC_Y800 + */ + DVP_KN_UYVY_TO_HSLp, + + /*! + * Converts FOURCC_UYVY format to 3 plane LAB D65 8 bit per pixel color space (VLIB-API.Sec 59.0)\n + * Configuration Structure: DVP_Int2Pl_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output1] Image color type supported: FOURCC_RGBA + * \param [output2] Image color type supported: FOURCC_RGBA + * \param [output3] Image color type supported: FOURCC_RGBA + */ + DVP_KN_UYVY_TO_LABp, + + /*! + * Converts FOURCC_IYUV or FOURCC_YV12 into FOURCC_UYVY. Chroma are doubled vertically\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_IYUV or FOURCC_YV12 + * \param [output] Image color type supported: FOURCC_UYVY + */ + DVP_KN_YUV420p_TO_UYVY, + + /*! + * Converts FOURCC_YU16 or FOURCC_YV16 into FOURCC_UYVY.\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_YV16 or FOURCC_YU16 + * \param [output] Image color type supported: FOURCC_UYVY + */ + DVP_KN_YUV422p_TO_UYVY, + + /*! + * Converts FOURCC_YU24 or FOURCC_YV24 into FOURCC_UYVY. Chroma are downsampled.\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_YU24 or FOURCC_YV24 + * \param [output] Image color type supported: FOURCC_UYVY + */ + DVP_KN_YUV444p_TO_UYVY, + + /*! + * Converts FOURCC_YU24 or FOURCC_YV24 into 8 bits per pixels planar RGB using BT.601.\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_YU24 or FOURCC_YV24 + * \param [output] Image color type supported: FOURCC_RGBP + */ + DVP_KN_YUV444p_TO_RGBp, + + /*! + * Converts FOURCC_NV12 into FOURCC_YU24 or FOURCC_YV24. Luma plane is half-scale downsampled. Output is 1/2w 1/2h from input.\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_NV12 + * \param [output] Image color type supported: FOURCC_YV24 or FOURCC_YU24 + */ + DVP_KN_NV12_TO_YUV444p, + + /*! + * Converts 1 plane RGB 888 FOURCC_BGR to FOURCC_UYVY\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_RGB888 or FOURCC_BGR + * \param [output] Image color type supported: FOURCC_UYVY + */ + DVP_KN_BGR3_TO_UYVY, + + /*! + * Converts 1 plane RGB 888 FOURCC_BGR to FOURCC_NV12\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_RGB888 or FOURCC_BGR + * \param [output] Image color type supported: FOURCC_NV12 + */ + DVP_KN_BGR3_TO_NV12, + + /*! + * Converts FOURCC_NV12 to UYVY.\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_NV12 + * \param [output] Image color type supported: FOURCC_UYVY + */ + DVP_KN_NV12_TO_UYVY, + + /*! + * Converts FOURCC_IYUV or FOURCC_YV12 into 8 bits per pixels planar RGB using BT.601.\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_IYUV or FOURCC_YV12 + * \param [output] Image color type supported: FOURCC_RGBP + */ + DVP_KN_YUV420p_TO_RGBp, + + /*! + * Converts 1 plane RGB 888 FOURCC_BGR to FOURCC_IYUV\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_RGB888 or FOURCC_BGR + * \param [output] Image color type supported: FOURCC_IYUV + */ + DVP_KN_BGR3_TO_IYUV, + + /*! + * \brief Predefined Filter Feature Base + * \note This is a placeholder enumeration, not a valid kernel + */ + DVP_KF_FILTER_BASE = DVP_KN_FEATURE_BASE(DVP_KF_FILTER), + + /*! + * Image Convolution of FOURCC_Y800 of data using the Sobel Gx and Gy operators\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_SOBEL_8, + + /*! + * Image Convolution of FOURCC_Y800 of data using the Scharr Gx and Gy operators\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_SCHARR_8, + + /*! + * Image Convolution of FOURCC_Y800 of data using the Scharr Gx and Gy operators\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_KROON_8, + + /*! + * Image Convolution of FOURCC_Y800 of data using the Prewitt Gx and Gy operators\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_PREWITT_8, + + /*! + * \brief Morphology Feature Base + * \note This is a placeholder enumeration, not a valid kernel + */ + DVP_KF_MORPH_BASE = DVP_KN_FEATURE_BASE(DVP_KF_MORPH), + + /*! + * Image Dilation using a 3x3 Cross Pattern : [0,1,0],[1,1,1],[0,1,0]\n + * Configuration Structure: DVP_Morphology_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Not applicable + */ + DVP_KN_DILATE_CROSS, + + /*! + * Image Dilation using a user specified 3x3 Mask pattern\n + * Configuration Structure: DVP_Morphology_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Image color type supported: FOURCC_Y800 + */ + DVP_KN_DILATE_MASK, + + /*! + * Image Dilation using a 3x3 Square pattern : [1,1,1],[1,1,1],[1,1,1]\n + * Configuration Structure: DVP_Morphology_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Not applicable + */ + DVP_KN_DILATE_SQUARE, + + /*! + * Image Erosion using a 3x3 Cross Pattern : [0,1,0],[1,1,1],[0,1,0]\n + * Configuration Structure: DVP_Morphology_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Not applicable + */ + DVP_KN_ERODE_CROSS, + + /*! + * Image Erosion using a user specified 3x3 Mask pattern\n + * Configuration Structure: DVP_Morphology_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Image color type supported: FOURCC_Y800 + */ + DVP_KN_ERODE_MASK, + + /*! + * Image Erosion using a 3x3 Square pattern : [1,1,1],[1,1,1],[1,1,1]\n + * Configuration Structure: DVP_Morphology_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Not applicable + */ + DVP_KN_ERODE_SQUARE, + + /*! + * \brief Canny Feature Base + * \note This is a placeholder enumeration, not a valid kernel + */ + DVP_KN_CANNY_BASE = DVP_KN_FEATURE_BASE(DVP_KF_CANNY), + + /*! + * Canny Image Smoothing (7x7 Image Convolution)\n + * Configuration Structure: DVP_ImageConvolution_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Image color type supported: FOURCC_Y800, signed + */ + DVP_KN_CANNY_IMAGE_SMOOTHING, + + /*! + * Canny 2D Gradient from FOURCC_Y800 to FOURCC_Y16 (VLIB-API.Sec 19.0)\n + * Configuration Structure: DVP_Canny2dGradient_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [outGradX] Image color type supported: FOURCC_Y16 + * \param [outGradY] Image color type supported: FOURCC_Y16 + * \param [outMag] Image color type supported: FOURCC_Y16 + */ + DVP_KN_CANNY_2D_GRADIENT, + + /*! + * Canny Non-Maximum Suppression from FOURCC_Y16 data to FOURCC_Y800 data)\n + * Configuration Structure: DVP_CannyNonMaxSuppression_t + * \param [inGradX] Image color type supported: FOURCC_Y16 + * \param [inGradY] Image color type supported: FOURCC_Y16 + * \param [inMag] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_CANNY_NONMAX_SUPPRESSION, + + /*! + * Canny Hysterisis Threshholding from FOURCC_Y800 edge map data to FOURCC_Y800 edge image\n + * Configuration Structure: DVP_CannyHystThresholding_t + * \param [inMag] Image color type supported: FOURCC_Y16 + * \param [inEdgeMap] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_CANNY_HYST_THRESHHOLD, + + /*! + * \brief Convert Feature Base + * \note This is a placeholder enumeration, not a valid kernel + */ + DVP_KN_CONVERT_BASE = DVP_KN_FEATURE_BASE(DVP_KF_CONVERT), + + /*! + * Converts an 8 bit planar image to 1 bit (stored in 8 bits) by down shifting all bytes by 7\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_THRESHOLD, + + /*! + * Converts a 8 bit to 16 bit per pixel or 16 bit to 8 bit per pixel planar image\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_UYVY + */ + DVP_KN_XSTRIDE_CONVERT, + + /*! + * Converts a 8 bit to 16 bit per pixel or 16 bit to 8 bit per pixel planar image with 8 bit shift\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_XSTRIDE_SHIFT, + + /*! + * \brief IIR Feature Base + * \note This is a placeholder enumeration, not a valid kernel + */ + DVP_KN_IIR_BASE = DVP_KN_FEATURE_BASE(DVP_KF_IIR), + + /*! + * Recursive First Order IIR Filter, Horizontal, FOURCC_Y800 input and output\n + * Configuration Structure: DVP_IIR_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [scratch] Image color type supported: FOURCC_Y800 + */ + DVP_KN_IIR_HORZ, + + /*! + * Recursive First Order IIR Filter, Vertical, FOURCC_Y800 input and output\n + * Configuration Structure: DVP_IIR_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [scratch] Image color type supported: FOURCC_Y800 + */ + DVP_KN_IIR_VERT, + + /*! + * \brief Nonmaximum Suppression Feature Base + * \note This is a placeholder enumeration, not a valid kernel + */ + DVP_KN_NONMAXSUPPRESS_BASE = DVP_KN_FEATURE_BASE(DVP_KF_NONMAXSUPPRESS), + + /*! + * Non-maximum suppression using a local neighborhood size of 3x3 on FOURCC_Y16 data\n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_NONMAXSUPPRESS_3x3_S16, + + /*! + * Non-maximum suppression using a local neighborhood size of 5x5 on FOURCC_Y16 data\n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_NONMAXSUPPRESS_5x5_S16, + + /*! + * Non-maximum suppression using a local neighborhood size of 7x7 on FOURCC_Y16 data\n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_NONMAXSUPPRESS_7x7_S16, + + /*! + * \brief Image Convolution Feature Base + * \note This is a placeholder enumeration, not a valid kernel + */ + DVP_KN_CONV_BASE = DVP_KN_FEATURE_BASE(DVP_KF_CONV), + + /*! + * Image Convolution using an arbitrary 3x3 matrix on FOURCC_Y800 data\n + * Configuration Structure: DVP_ImageConvolution_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Image color type supported: FOURCC_Y800 + */ + DVP_KN_CONV_3x3, + + /*! + * Image Convolution using an arbitrary 5x5 matrix on FOURCC_Y800 data\n + * Configuration Structure: DVP_ImageConvolution_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Image color type supported: FOURCC_Y800 + */ + DVP_KN_CONV_5x5, + + /*! + * Image Convolution using an arbitrary 7x7 matrix on FOURCC_Y800 data\n + * Configuration Structure: DVP_ImageConvolution_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Image color type supported: FOURCC_Y800 + */ + DVP_KN_CONV_7x7, + + /*! + * \brief Threshold Feature Base + * \note This is a placeholder enumeration, not a valid kernel + */ + DVP_KN_THR_BASE = DVP_KN_FEATURE_BASE(DVP_KF_THR), + + /*! + * Image Thresholding : {out[i] = (in[i] > thr) ? 255 : in[i]} for 8-bit input\n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_THR_GT2MAX_8, + + /*! + * Image Thresholding : {out[i] = (in[i] > thr) ? 65535 : in[i]} for 16-bit input\n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_THR_GT2MAX_16, + + /*! + * Image Thresholding : {out[i] = (in[i] > thr) ? thr : in[i]} for 8-bit input\n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_THR_GT2THR_8, + + /*! + * Image Thresholding : {out[i] = (in[i] > thr) ? thr : in[i]} for 16-bit input\n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_THR_GT2THR_16, + + /*! + * Image Thresholding : {out[i] = (in[i] <= thr) ? 0 : in[i]} for 8-bit input\n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_THR_LE2MIN_8, + + /*! + * Image Thresholding : {out[i] = (in[i] <= thr) ? 0 : in[i]} for 16-bit input\n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_THR_LE2MIN_16, + + /*! + * Image Thresholding : {out[i] = (in[i] <= thr) ? thr : in[i]} for 8-bit input\n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_THR_LE2THR_8, + + /*! + * Image Thresholding : {out[i] = (in[i] <= thr) ? thr : in[i]} for 16-bit input\n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_THR_LE2THR_16, + + /*! + * \brief Sobel Feature Base + * \note This is a placeholder enumeration, not a valid kernel + */ + DVP_KN_SOBEL_BASE = DVP_KN_FEATURE_BASE(DVP_KF_SOBEL), + /*! + * Image Sobel : 3x3 for 8-bit signed input\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_SOBEL_3x3_8s, + + /*! + * Image Sobel : 3x3 for 8-bit unsigned input\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_SOBEL_3x3_8, + + /*! + * Image Sobel : 3x3 for 16-bit signed input\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_SOBEL_3x3_16s, + + /*! + * Image Sobel : 3x3 for 16-bit unsigned input\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_SOBEL_3x3_16, + + /*! + * Image Sobel : 5x5 for 8-bit signed input\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_SOBEL_5x5_8s, + + /*! + * Image Sobel : 5x5 for 8-bit unsigned input\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_SOBEL_5x5_8, + + /*! + * Image Sobel : 5x5 for 16-bit signed input\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_SOBEL_5x5_16s, + + /*! + * Image Sobel : 5x5 for 16-bit unsigned input\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_SOBEL_5x5_16, + + /*! + * Image Sobel : 7x7 for 8-bit signed input\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_SOBEL_7x7_8s, + + /*! + * Image Sobel : 7x7 for 8-bit unsigned input\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_SOBEL_7x7_8, + + /*! + * Image Sobel : 7x7 for 16-bit signed input\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_SOBEL_7x7_16s, + + /*! + * Image Sobel : 7x7 for 16-bit unsigned input\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_SOBEL_7x7_16, + + /*! + * \brief Integral Image Feature Base + * \note This is a placeholder enumeration, not a valid kernel + */ + DVP_KN_INTEGRAL_BASE = DVP_KN_FEATURE_BASE(DVP_KF_INTEGRAL), + + /*! + * Computes a Integral Image over the FOURCC_Y800 data. FOURCC_Y32 output\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_RGBA + */ + DVP_KN_INTEGRAL_IMAGE_8, + + /*! + * Applies a given gamma mapping to an image and produces it as a new output. + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_GAMMA, + + DVP_KN_LOCAL_OPTIMIZED_BASE = DVP_KN_FEATURE_BASE(DVP_KF_OPTIMIZED),/*!< Used by Kernel Graph Managers to define a local optimized kernel set which combine multiple functions */ + + /*! + * \brief Used to ensure 32 bit enumeration across all cores and compilers\n + * \note This is a placeholder enumeration, not a valid kernel + */ + DVP_KN_MAXIMUM = 0x7FFFFFFF, +} DVP_KernelNode_e; + + +/*! \brief Handle to the DVP instance. + * \ingroup group_system + * \see DVP_KernelGraph_Init + */ +typedef size_t DVP_Handle; + +/*! + * \brief This structure contains variables need to capture performance data. + * \ingroup group_performance + */ +typedef struct _dvp_perf_t { + DVP_U32 numTimes; /*!< The number of times that performance information has been captured. */ + rtime_t tmpTime; /*!< Used to record the last start time */ + rtime_t minTime; /*!< Used to record the minimum time of execution */ + rtime_t maxTime; /*!< Used to record the maximum time of execution */ + rtime_t avgTime; /*!< Used to record the average time of execution */ + rtime_t sumTime; /*!< Used to record the total time of execution of all iterations */ + rtime_t rate; /*!< This is used to record the clock rate per second on the local core */ +} DVP_Perf_t; + +/*! + * Initialize the DVP_Perf_t structure. Used with automatic variables. + *
DVP_Perf_t perf = DVP_PERF_INIT;
+ * \ingroup group_performance + */ +#define DVP_PERF_INIT { 0, 0, MAX_RTIMER_T, 0, 0, 0, rtimer_freq() } + +/*! + * \brief This enumeration names the valid cores on OMAP 4,5,6 chips (not all are present or enabled on each generation). + * \ingroup group_system + */ +typedef enum _dvp_cores_e { + DVP_CORE_MIN = -1, + DVP_CORE_DSP = 0, /*!< On OMAP4 this is the Tesla C64T, on OMAP 6 this is the C66x */ + DVP_CORE_SIMCOP, /*!< On OMAP4 this is the SIMCOP, controlled by the APP M3 Core */ + DVP_CORE_MCU0, /*!< On OMAP4 this is the APP M3 Core, on OMAP5, this is one of the M4 cores */ + DVP_CORE_MCU1, /*!< On OMAP4 this is the SYS M3 Core, on OMAP5, this is one of the M4 cores */ + DVP_CORE_GPU, /*!< On OMAP4, this is an SGX 540, in PC builds, this will be your local GPU, if present. */ + DVP_CORE_EVE, /*!< On OMAP6 there will be an EVE */ + // CPU must be last in the list + DVP_CORE_CPU, /*!< On OMAP4, this is a Dual Cortex A9, in the PC build it will be your local CPU */ + DVP_CORE_MAX, +} DVP_Core_e; + +/*! \brief Used to initialize an array of DVP_U32 values which correspond to the DVP_CORE_MAX number of cores. + * \ingroup group_capacity + */ +#define DVP_CORE_LOAD_INIT { 0, 0, 0, 0, 0, 0 } + +/*! \brief Used to determine if a supplied value is within the valid range of DVP_Core_e. + * \ingroup group_system + */ +#define DVP_VALID_CORE(x) (DVP_CORE_MIN < (x) && (x) < DVP_CORE_MAX) + +/*! + * \brief This structure contains the metadata for each kernel node. + * \ingroup group_nodes + */ +typedef struct _dvp_knode_hdr_t { + DVP_ENUM kernel; /*!< Specific kernel to execute for this node */ + DVP_S32 affinity; /*!< This indicates that the programmer knows which core this function should execute on. This will supercede priority and load balancing */ + DVP_Error_e error; /*!< Used to hold the error status of this node */ + DVP_S32 configured; /*!< \private This is hint which indicates to the Kernel Graph Boss that it if true has already determined which core to execute this node on. */ + DVP_U32 mgrIndex; /*!< \private This will be filled in after the nodes are given to the kernel graph */ + DVP_U32 funcIndex; /*!< \private This will be filled in after the nodes are given to the kernel graph */ + DVP_Perf_t perf; /*!< \private Used to capture the performance of each node */ + DVP_U32 resv[2]; /*!< \private Used by M3 to store handle - Set to NULL only during creation */ +} DVP_KernelNodeHeader_t; + +/*! \brief Defines the size of the data region in a kernel node available to kernels for parameters. + * \ingroup group_nodes + */ +#define DVP_KNODE_DATA_SIZE (DVP_PAGE_SIZE-sizeof(DVP_KernelNodeHeader_t)) + +/*! + * \brief This structure specifies a single kernel function call and it's associated parameters plus overhead. + * \ingroup group_nodes + */ +typedef struct _dvp_knode_t2 { + DVP_KernelNodeHeader_t header; + DVP_U08 data[DVP_KNODE_DATA_SIZE]; /*!< cast your data structure to this array. \see dvp_knode_to */ +} DVP_KernelNode_t; + +/*! \brief This macro is used to cast the data section to a user's requested data structure type. + * \ingroup group_nodes + */ +#define dvp_knode_to(pNode, type) ((type *)&((pNode)->data[0])) + +/*! + * \brief This structure allows a user to specify a series of nodes which are called a section. + * \note This structure will currently stay on the HOST process space so no special allocator is required. + * The structure may be declared as an automatic stack structure in your process. + * \ingroup group_sections + */ +typedef struct _dvp_kernelgraphsection_t { + DVP_KernelNode_t *pNodes; /*!< The array of node structures */ + DVP_U32 numNodes; /*!< The number of nodes in the array */ + DVP_Perf_t perf; /*!< The performance information related to this section only */ + DVP_S32 coreLoad[DVP_CORE_MAX]; /*!< Used internally to store the local calculation of load due to this section on each DVP CORE */ + DVP_BOOL skipSection; /*!< A boolean to determine if the section should be skipped, defaults to false. */ +} DVP_KernelGraphSection_t; + +/*! + * \brief This data structure allows a user to specify multiple sections into a larger graph structure. + * The order field allows the users to specify which sections run in series or in parallel with other sections. + * \note This structure will currently stay on the HOST process space so no special allocator is required. + * The structure may be declared as an automatic stack structure in your process. + * \ingroup group_graphs + */ +typedef struct _dvp_kernelgraph_t { + DVP_KernelGraphSection_t *sections; /*!< The array of sections of the graph */ + DVP_U32 numSections; /*!< This is the length of sections, and order, individually. */ + DVP_U32 *order; /*!< The array of order declarations */ + DVP_Perf_t totalperf; /*!< This is the total performance of the entire graph */ +} DVP_KernelGraph_t; + +/*! \brief The maximum kernel name length. + * \ingroup group_kernels + */ +#define DVP_KERNEL_MAX (128) + +/*! + * \brief Defines which kernels a manager supports. + * This defines the entry for the kernel table each KGM must define in order to inform the + * the Kernel Graph Boss which kernel it supports. + * \ingroup group_kernels + */ +typedef struct _dvp_core_function_t { + char name[DVP_KERNEL_MAX]; /*!< The name of the kernel, used in debugging */ + DVP_KernelNode_e kernel; /*!< The enumerated name of the kernel */ + DVP_U32 load; /*!< \hidden The load value of this kernel */ +} DVP_CoreFunction_t; + +/*! + * \brief This data structure allows a user to query the status of the core. + * \ingroup group_system + */ +typedef struct _dvp_coreinfo_t +{ + DVP_BOOL enabled; /*!< The core state */ + DVP_BOOL libraries[DVP_KL_LIBRARY_MAX]; /*!< The list of kernel libraries enabled on this core. Use \ref DVP_KernelLibrary_e to index this array to get the boolean. */ + const DVP_CoreFunction_t *kernels; /*!< The list of kernel libraries enabled on this core */ + DVP_U32 numKernels; /*!< The number of kernerls enabled. */ +} DVP_CoreInfo_t; + +#endif // _DVP_TYPES_H_ diff --git a/include/linux/omap_rpc.h b/include/linux/omap_rpc.h new file mode 100644 index 0000000..d40d99a --- /dev/null +++ b/include/linux/omap_rpc.h @@ -0,0 +1,200 @@ +/* + * OMAP Remote Procedure Call Driver. + * + * Copyright(c) 2011 Texas Instruments. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Texas Instruments nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _OMAP_RPC_H_ +#define _OMAP_RPC_H_ + +#include + +#if defined(CONFIG_ION_OMAP) +#include +#endif + +#define OMAPRPC_IOC_MAGIC 'O' + +#define OMAPRPC_IOC_CREATE _IOW(OMAPRPC_IOC_MAGIC, 1, char *) +#define OMAPRPC_IOC_DESTROY _IO(OMAPRPC_IOC_MAGIC, 2) +#define OMAPRPC_IOC_IONREGISTER _IOWR(OMAPRPC_IOC_MAGIC, 3, \ + struct ion_fd_data) +#define OMAPRPC_IOC_IONUNREGISTER _IOWR(OMAPRPC_IOC_MAGIC, 4, \ + struct ion_fd_data) + +#define OMAPRPC_IOC_MAXNR (4) + +struct omaprpc_create_instance_t { + char name[48]; +}; + +struct omaprpc_channel_info_t { + char name[64]; +}; + +enum omaprpc_info_type_e { + /** The number of functions in the service instance */ + OMAPRPC_INFO_NUMFUNCS, + /** The symbol name of the function */ + OMAPRPC_INFO_FUNC_NAME, + /** The number of times a function has been called */ + OMAPRPC_INFO_NUM_CALLS, + /** The performance information releated to the function */ + OMAPRPC_INFO_FUNC_PERF, + + /** @hidden used to define the maximum info type */ + OMAPRPC_INFO_MAX +}; + +struct omaprpc_query_instance_t { + uint32_t info_type; /**< @see omaprpc_info_type_e */ + uint32_t func_index; /**< The index to querty */ +}; + +struct omaprpc_func_perf_t { + uint32_t clocks_per_sec; + uint32_t clock_cycles; +}; + +/** These core are specific to OMAP processors */ +enum omaprpc_core_e { + OMAPRPC_CORE_DSP = 0, /**< DSP Co-processor */ + OMAPRPC_CORE_SIMCOP, /**< Video/Imaging Co-processor */ + OMAPRPC_CORE_MCU0, /**< Cortex M3/M4 [0] */ + OMAPRPC_CORE_MCU1, /**< Cortex M3/M4 [1] */ + OMAPRPC_CORE_EVE, /**< Imaging Accelerator */ + OMAPRPC_CORE_REMOTE_MAX +}; + +struct omaprpc_instance_info_t { + uint32_t info_type; + uint32_t func_index; + union info { + uint32_t num_funcs; + uint32_t num_calls; + uint32_t core_index; /**< @see omaprpc_core_e */ + char func_name[64]; + struct omaprpc_func_perf_t perf; + } info; +}; + +enum omaprpc_cache_ops_e { + OMAPRPC_CACHEOP_NONE = 0, + OMAPRPC_CACHEOP_FLUSH, + OMAPRPC_CACHEOP_INVALIDATE, + + OMAPRPC_CACHEOP_MAX, +}; + +struct omaprpc_param_translation_t { + /** The parameter index which indicates which is the base pointer */ + uint32_t index; + /** The offset from the base address to the pointer to translate */ + ptrdiff_t offset; + /** The base user virtual address of the pointer to translate + (used to calc translated pointer offset). */ + size_t base; + /** The enumeration of desired cache operations for efficiency */ + uint32_t cacheOps; + /** Reserved field */ + size_t reserved; +}; + +enum omaprpc_param_e { + OMAPRPC_PARAM_TYPE_UNKNOWN = 0, + /** An atomic data type, 1 byte to architecture limit sized bytes */ + OMAPRPC_PARAM_TYPE_ATOMIC, + /** A pointer to shared memory. The reserved field must contain the + handle to the memory */ + OMAPRPC_PARAM_TYPE_PTR, + /** \hidden (Unsupported) A structure type. Will be architecure width + aligned in memory. */ + OMAPRPC_PARAM_TYPE_STRUCT, +}; + +struct omaprpc_param_t { + uint32_t type; /**< @see omaprpc_param_e */ + size_t size; /**< The size of the data */ + size_t data; /**< Either the pointer to the data or the data + itself, @see .type */ + size_t base; /**< If a pointer is in data, this is the base + pointer (if data has an offset from base). */ + size_t reserved; /**< Shared Memory Handle + (used only with pointers) */ +}; + +#define OMAPRPC_MAX_PARAMETERS (10) + +struct omaprpc_call_function_t { + /** The function to call */ + uint32_t func_index; + /** The number of parameters in the array. */ + uint32_t num_params; + /** The array of parameters */ + struct omaprpc_param_t params[OMAPRPC_MAX_PARAMETERS]; + /** The number of translations needed in the offsets array */ + uint32_t num_translations; + /** An indeterminate lenght array of offsets within payload_data to + pointers which need translation */ + struct omaprpc_param_translation_t translations[0]; +}; + +#define OMAPRPC_MAX_TRANSLATIONS (1024) + +struct omaprpc_function_return_t { + uint32_t func_index; + uint32_t status; +}; + + +#define OMAPRPC_DESC_EXEC_SYNC (0x0100) +#define OMAPRPC_DESC_EXEC_ASYNC (0x0200) +#define OMAPRPC_DESC_SYM_ADD (0x0300) +#define OMAPRPC_DESC_SYM_IDX (0x0400) +#define OMAPRPC_DESC_CMD (0x0500) +#define OMAPRPC_DESC_TYPE_MASK (0x0F00) +#define OMAPRPC_JOBID_DISCRETE (0) +#define OMAPRPC_POOLID_DEFAULT (0x8000) + +#define OMAPRPC_SET_FXN_IDX(idx) (idx | 0x80000000) +#define OMAPRPC_FXN_MASK(idx) (idx & 0x7FFFFFFF) + +/** This is actually a frankensteined structure of RCM */ +struct omaprpc_packet_t { + uint16_t desc; /**< @see RcmClient_Packet.desc */ + uint16_t msg_id; /**< @see RcmClient_Packet.msgId */ + uint16_t pool_id; /**< @see RcmClient_Message.poolId */ + uint16_t job_id; /**< @see RcmClient_Message.jobId */ + uint32_t fxn_idx; /**< @see RcmClient_Message.fxnIdx */ + int32_t result; /**< @see RcmClient_Message.result */ + uint32_t data_size; /**< @see RcmClient_Message.data_size */ + uint8_t data[0]; /**< @see RcmClient_Message.data pointer */ +} __packed; + +#endif /* _OMAP_RPC_H_ */ diff --git a/include/omaprpc/omaprpc.h b/include/omaprpc/omaprpc.h new file mode 100644 index 0000000..b9b8dc8 --- /dev/null +++ b/include/omaprpc/omaprpc.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _OMAPRPC_USR_H_ +#define _OMAPRPC_USR_H_ + +/*! \file + * \brief The User API of the OMAPRPC driver. + * \author Erik Rainey + * \defgroup group_omaprpc OMAPRPC Driver + */ + +#include +#if defined(LINUX) && defined(PANDA) +typedef size_t ptrdiff_t; +#include +#elif defined(ANDROID) +#include +#endif + +// forward definition +struct _omaprpc_t; + +/*! \brief The callback prototype used when the remote side restarts unexpectedly. + * \ingroup group_omaprpc + */ +typedef void (*omaprpc_endpoint_restarted_f)(struct _omaprpc_t *rpc, void *cookie); + +/*! \brief The OMAPRPC Context + * \ingroup group_omaprpc + */ +typedef struct _omaprpc_t { + int32_t device; /*!< \brief The file descriptor of the opened device */ + char dev_name[MAX_PATH]; /*!< \brief The local device node to open */ + struct omaprpc_create_instance_t create; /*!< \brief The remote server name to connect to */ + uint32_t retries; /*!< \brief The number of tries to re-open the driver after an unexpected restart */ + uint32_t num_funcs; /*!< \brief The number of supported functions on the endpoint */ + struct omaprpc_call_function_t *functions; /*!< \brief The array of supported functions on the endpoint */ + omaprpc_endpoint_restarted_f restart; /*!< \brief The function to call if the remote endpoint restarts unexpectedly. */ + void *cookie; /*!< \brief A user supplied context pointer to be passed to the restart callback */ +} omaprpc_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \brief This function opens the local device node which connects to a remote core with a particular service. + * \param [in] device_name The device to open. i.e.: "/dev/omaprpc-0" + * \param [in] server_name The name of the service to connect to. i.e.: "omaprpc-0" + * \param [in] numFuncs The number of functions that the service has. + * \ingroup group_omaprpc + */ +omaprpc_t *omaprpc_open(char *device_name, char *server_name, uint32_t numFuncs); + +/*! + * \brief This function closes an OMAPRPC device opened by omaprpc_open. + * \pre \ref omaprpc_open + * \param [in,out] rpm The pointer to the omaprpc_t pointer. This will be NULLed by + * this function. + * \ingroup group_omaprpc + */ +void omaprpc_close(omaprpc_t **rpm); + +/*! + * \brief This function registers a callback to be called if the remote endpoint restarts unexpectedly. + * \param rpc The handle to the OMAPRPC context. + * \param cookie A pointer to some user private context data. + * \param func The function to call when the restart occurs. + * \param retries The number of times to retry opening the driver after an unexpected restart. + * \ingroup group_omaprpc + */ +void omaprpc_restart_callback(omaprpc_t *rpc, void *cookie, omaprpc_endpoint_restarted_f func, uint32_t retries); + +/*! + * \brief This function calls a remote function and can get a status code + * from that operation. + * \param [in] rpc The handle to the OMARPPC context. + * \param [in] function The function descriptor used to call the remote function. + * \param [in] returned The return value from the called function. This can be NULL if you dont' care about the return value. + * \ingroup group_omaprpc + */ +bool_e omaprpc_call(omaprpc_t *rpc, struct omaprpc_call_function_t *function, struct omaprpc_function_return_t *returned); + +#if defined(OMAPRPC_USE_ION) +/*! + * \brief This function registers a piece of memory with OMAPRPC so that if + * this process dies, the kernel will still retain a handle to that memory, thus + * preventing the memory from being freed and removed from remote cores asynchronously. + * \note This is only required for ION memory. + * \param [in] rpc The handle to the OMAPRPC context. + * \param [in] memdevice The file descriptor of the opened "/dev/ion". + * \param [in] ptr The user virtual address of the pointer to register. + * \param [in] reserved The ION handle to the memory. + * \ingroup group_omaprpc + */ +#endif +bool_e omaprpc_register(omaprpc_t *rpc, int memdevice, void *ptr, void **reserved); + +#if defined(OMAPRPC_USE_ION) +/*! + * \brief This function unregisters a piece of memory with OMAPRPC and removes + * the reference in the kernel. + * \note This is only required for ION memory. + * \param [in] rpc The handle to the OMAPRPC context. + * \param [in] memdevice The file descriptor of the opened "/dev/ion". + * \param [in] ptr The user virtual address of the pointer to register. + * \param [in] reserved The ION handle to the memory. + * \ingroup group_omaprpc + */ +#endif +bool_e omaprpc_unregister(omaprpc_t *rpc, int memdevice, void *ptr, void **reserved); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/sosal/CThreaded.h b/include/sosal/CThreaded.h new file mode 100644 index 0000000..8c82f41 --- /dev/null +++ b/include/sosal/CThreaded.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CTHREADED_H_ +#define _CTHREADED_H_ + +/*! + * \file + * \brief The C++ Wrapper around thread_t's. + * \author Erik Rainey + */ + +#include + +/*! \brief The C function which launches the \ref CThreaded::RunThread */ +extern "C" thread_ret_t ThreadWrapper(void *arg); + +/*! + * \brief This class is a wrapper around the \ref thread_t API for C++ objects. + * \note When inheriting from CThreaded, always make it the FIRST class you subclass from, + * otherwise the \ref CThreaded::RunThread won't work. + * \ingroup group_threads + */ +class CThreaded { +protected: + thread_t m_handle; /*!< \brief The handle to the threads which runs \ref CThreaded::RunThread */ + mutex_t m_mutex; /*!< \brief The mutex which backs the Lock/Unlock method. */ + bool m_running; /*!< \brief A boolean to indicate whether the thread should be running or not. */ +public: + /*! \brief The constructor */ + CThreaded(); + + /*! \brief The deconstrctor */ + virtual ~CThreaded(); + + /*! \brief The lock method for protecting operations in the thread.*/ + virtual void Lock(); + + /*! \brief The unlock method for protecting operations in the thread. */ + virtual void Unlock(); + + /*! \brief The wrapping method which launches the \ref CThreaded::RunThread method in a thread. + * \param [in] subclassthis The pointer to a subclass instance of CThreaded. + */ + virtual bool StartThread(void *subclassthis); + + /*! \brief The method which causes the thread to shutdown asynchronously. + * \note This method must be overloaded by subclasses in order to stop threads which + * are waiting on external events or causes. + */ + virtual void Shutdown(); + + /*! \brief The interface to stop the \ref CThreaded::RunThread method. */ + virtual bool StopThread(); + + /*! \brief The method which will run in it's own thread when + * \ref CThreaded::StartThread is called. + */ + virtual thread_ret_t RunThread() = 0; +}; + +#endif + diff --git a/include/sosal/allocator.h b/include/sosal/allocator.h new file mode 100644 index 0000000..cb5b628 --- /dev/null +++ b/include/sosal/allocator.h @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_ALLOCATOR_H_ +#define _SOSAL_ALLOCATOR_H_ + +/*! + * \file allocator.h + * \brief The Allocator API. + * \author Erik Rainey + */ + +#include + +#if !defined(_SOSAL_ALLOCATOR_T_DEFINED) +/*! \brief Used to define a type which will be kept internally hidden. + * \ingroup group_allocator + */ +typedef uint32_t allocator_t; +#endif + +/*! + * \brief The list of supported allocation types. + * \ingroup group_allocators + */ +typedef enum _allocator_memory_type_e { + ALLOCATOR_MEMORY_TYPE_VIRTUAL, /*!< Plain Virtual Memory */ + ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED,/*!< TARGET_DVP_OMAP4 && (SOSAL_USE_ION || SOSAL_USE_TILER) */ + ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED, /*!< TARGET_DVP_OMAP4 && (SOSAL_USE_ION || SOSAL_USE_TILER) */ + ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED,/*!< TARGET_DVP_OMAP4 && (SOSAL_USE_ION || SOSAL_USE_TILER) */ + ALLOCATOR_MEMORY_TYPE_TILED_2D_CACHED, /*!< TARGET_DVP_OMAP4 && (SOSAL_USE_ION || SOSAL_USE_TILER) */ + ALLOCATOR_MEMORY_TYPE_GFX_2D_UNCACHED, /*!< TARGET_DVP_OMAP4 && SOSAL_USE_GRALLOC */ + ALLOCATOR_MEMORY_TYPE_VIRTUAL_SHARED, /*!< Shared Virtual Memory */ + ALLOCATOR_MEMORY_TYPE_MAX +} allocator_memory_type_e; + +/*! \brief The maximum number of dimensions to a single pointer. + * \todo Exand this to 4? + * \ingroup group_allocators + */ +#define SOSAL_ALLOCATOR_MAX_DIMS (3) + +/*! + * The allocator dimensions can be thought of in several ways, either a strict series of dimensional values, + * or a set of cartesian values, or an image descriptor. + * \ingroup group_allocators + */ +typedef struct _allocator_dimensions_t { + union { + int32_t dims[SOSAL_ALLOCATOR_MAX_DIMS]; + struct { + int32_t x; + int32_t y; + int32_t z; + //int32_t p; + } dim; + struct { + int32_t bpp; + int32_t width; + int32_t height; + //int32_t planes; + } img; + }; +} allocator_dimensions_t; + +/*! \brief The maximum number of dimensional pointers. + * \ingroup group_allocators + */ +#define SOSAL_ALLOCATOR_MAX_PTRS (4) + +/*! \brief If a native format of memory is not present, clients may use this structure + * to track allocated memory. It is preferable to use Native formats when + * possible to avoid needless meta-data redundancy. + * \ingroup group_allocators + */ +typedef struct _allocator_memory_t { + /*! A quick way to indicate whether the structure contains allocated memory */ + bool_e allocated; + /*! The memory type */ + allocator_memory_type_e memtype; + /*! The pointers to actual memory */ + ptr_t ptrs[SOSAL_ALLOCATOR_MAX_PTRS]; + /*! The number of pointers valid in ptrs */ + int32_t nptrs; + /*! The number of dimensions valid in each dims. Each pointer must have the same dimensionality. */ + int32_t ndims; + /*! The dimensions of each ptrs */ + allocator_dimensions_t dims[SOSAL_ALLOCATOR_MAX_PTRS]; + /*! The stride information of each pointer */ + allocator_dimensions_t strides[SOSAL_ALLOCATOR_MAX_PTRS]; + /*! The handle to each pointer */ + value_t hdls[SOSAL_ALLOCATOR_MAX_PTRS]; + /*! The shared memory descriptors (if shared) */ + int32_t fds[SOSAL_ALLOCATOR_MAX_PTRS]; +} allocator_memory_t; + +#if defined(SOSAL_USE_BO) +/*! \brief This the the private handle structure in the BO configuration. + * \ingroup group_allocators + */ +typedef struct _alloc_omap_bo_t { + void *bo; /*!< The pointer to the returned kernel data */ + int32_t dmabuf_fd; /*!< The file descriptor of the mapped memory */ +} alloc_omap_bo_t; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * Initializes the Allocator. + * \ingroup group_allocators + */ +allocator_t *allocator_init(); + +/*! + * Deinitializes the Allocator. + * \ingroup group_allocators + */ +void allocator_deinit(allocator_t **palloc); + +/*! + * \brief Allocates multiple multi-dimensional pointers in one call. +
+Usage: For a linear buffer:
+    allocator_calloc(t, 1, 2, {{elemSize, numElems}}, {ptrs}, {handles}, {strides});
+
+Usage: For a 3 plane image of 320x240 of 1 bpp each (like FOURCC_RGBP):
+    allocator_calloc(t, 3, 3, {{1,320,240},
+                             {1,320,240},
+                             {1,320,240}}, {ptrs}, {handles},  {strides});
+    Returns:
+    {ptrs}    = {%p, %p, %p}
+    {handles} = {%p, %p, %p}
+    {strides} = {{1,320,0},{1,320,0},{1,320,0}} if 1D, {{1,STRIDE,0},{1,STRIDE,0},{1,STRIDE,0}} if 2D
+Usage: For a 3 plane image of 320x240 of 1 bpp for the first plane, but 1/2 planes following (like YUV420):
+    allocator_calloc(t, 3, 3, {{1,320,240},
+                             {1,160,120},
+                             {1,160,120}}, {NULL, NULL, NULL}, {handles},  {strides});
+    Returns:
+    {ptrs}    = {%p, %p, %p}
+    {handles} = {%p, %p, %p}
+    {strides} = {{1,320,0},{1,320,0},{1,320,0}} if 1D, {{1,STRIDE,0},{1,STRIDE,0},{1,STRIDE,0}} if 2D
+Usage: For a 2 plane image of 320x240 of 1 bpp then 160x120 of 2 bpp (like NV12)
+    allocator_calloc(t, 2, 3, {{1,320,240},
+                             {2,160,120}}, {NULL, NULL}, {handles}, {strides});
+
+    Returns:
+    {ptrs}    = {%p, %p}
+    {handles} = {%p, %p}
+    {strides} = {{1,320,0},{2,320,0}} if 1D, {{1,STRIDE,0},{2,(other)STRIDE,0}} if 2D
+Generically:
+    allocator_calloc(type, planes, numDim, {{bpp, width, height},...}, {ptrs}, {handles},  {strides});
+
+Handles:
+    Generally the handles array will hold any internally used value which comes from underlying APIs that this API uses. They must be saved and given back with the free function.
+
+ * \param alloc The pointer to the allocator meta-data. + * \param memtype The type of memory to use. + * \param nptrs The number of pointers to allocate. + * \param ndims The number of dimensions each pointer will reference. + * \param dims The array of dimensional values. + * \param ptrs The array of pointers to set. + * \param hdls The array of handles to set. + * \param strides The array of stride information to set. + * \ingroup group_allocators + */ +bool_e allocator_calloc(allocator_t *alloc, + allocator_memory_type_e memtype, + int32_t nptrs, + int32_t ndims, + allocator_dimensions_t *dims, + ptr_t *ptrs, + value_t *hdls, + allocator_dimensions_t *strides); + +/*! + * \brief Frees memory allocated by the calloc function. + * \ingroup group_allocators + */ +bool_e allocator_free(allocator_t *alloc, + allocator_memory_type_e memtype, + int32_t nptrs, + ptr_t *ptrs, + value_t *hdls); + +/*! + * \brief Returns file descriptors to use in sharing memory. + * \ingroup group_allocators + */ +bool_e allocator_share(allocator_t *alloc, + allocator_memory_type_e memtype, + int32_t nptrs, + value_t *hdls, + int32_t *fds); + +/*! + * \brief Imports pre-shared piece of memory into this process space. + * \ingroup group_allocators + */ +bool_e allocator_import(allocator_t *alloc, + allocator_memory_type_e memtype, + int32_t nptrs, + int32_t ndims, + allocator_dimensions_t *dims, + ptr_t *ptrs, + value_t *hdls, + allocator_dimensions_t *strides, + int32_t *fds); + +/*! + * \brief Flushes memory from the CPU side cache, if supported by the supplied type. + * \param alloc + * \param mtype + * \param nptrs + * \param ndims + * \param dims + * \param ptrs + * \param hdls + * \ingroup group_allocators + */ +bool_e allocator_flush(allocator_t *alloc, + allocator_memory_type_e mtype, + int32_t nptrs, + int32_t ndims, + allocator_dimensions_t *dims, + ptr_t *ptrs, + value_t *hdls); + +/*! + * \brief Invalidate memory (flushes cache line) from the CPU cache, if supported by the supplied type. + * \param alloc + * \param mtype + * \param nptrs + * \param ndims + * \param dims + * \param ptrs + * \param hdls + * \ingroup group_allocators + */ +bool_e allocator_invalidate(allocator_t *alloc, + allocator_memory_type_e mtype, + int32_t nptrs, + int32_t ndims, + allocator_dimensions_t *dims, + ptr_t *ptrs, + value_t *hdls); + +/*! + * \brief Retrieves the underlying implementations device descriptor if supported by the supplied type. + * \param alloc + * \param mtype + * \ingroup group_allocators + */ +int allocator_get_device(allocator_t *alloc, allocator_memory_type_e mtype); + +/*! + * \brief Simple wrapper for allocator_calloc + * \param alloc + * \param memory + * \ingroup group_allocators + */ +bool_e allocator_memory_calloc(allocator_t *alloc, allocator_memory_t *memory); + +/*! + * \brief Simple wrapper for allocator_free + * \param alloc + * \param memory + * \ingroup group_allocators + */ +bool_e allocator_memory_free(allocator_t *alloc, allocator_memory_t *memory); + +/*! + * \brief Simple wrapper for allocator_share + * \param alloc + * \param memory + * \ingroup group_allocators + */ +bool_e allocator_memory_share(allocator_t *alloc, allocator_memory_t *memory); + +/*! + * \brief Simple wrapper for allocator_import + * \param alloc + * \param memory + * \ingroup group_allocators + */ +bool_e allocator_memory_import(allocator_t *alloc, allocator_memory_t *memory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/sosal/allocator_binder.h b/include/sosal/allocator_binder.h new file mode 100644 index 0000000..0ebed53 --- /dev/null +++ b/include/sosal/allocator_binder.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_BINDER_HELPER_H_ +#define _SOSAL_BINDER_HELPER_H_ + +/*! \file + * \brief The Android C++ wrappers for sharing SOSAL allocated memory over a Binder. + * \author Erik Rainey + */ + +#include + +#if defined(ANDROID) && defined(__cplusplus) + +#if defined(FROYO) || defined(GINGERBREAD) || defined(ICS) || defined(JELLYBEAN) +#include +#include +#include + +using android::Parcel; + +/*! \brief The C++ Namespace for SOSAL components. */ +namespace SOSAL { + +/*! \brief Writes a \ref allocator_memory_t meta-data structure to a parcel. + * \ingroup group_allocators + */ +void WriteMemoryToParcel(Parcel &parcel, allocator_memory_t *memory); + +/*! \brief Reads a \ref allocator_memory_t meta-data structure from a parcel. + * \ingroup group_allocators + */ +void ReadMemoryFromParcel(const Parcel &parcel, allocator_memory_t *memory); +}; + +#else // NDK + +#include + +#endif // IF MYDROID + +#endif // IF ANDROID && C++ + +#endif + diff --git a/include/sosal/bitfield.h b/include/sosal/bitfield.h new file mode 100644 index 0000000..3913301 --- /dev/null +++ b/include/sosal/bitfield.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_BITFIELD_H_ +#define _SOSAL_BITFIELD_H_ + +/*! + * \file bitfield.h + * \brief The Bitfield Type API. + * \author Erik Rainey + */ + +#include + +/*! \brief An extensible bitfield (more than architecture width). + * \ingroup group_bitfields + */ +typedef struct _bitfield_t { + uint32_t *fields; /*!< The bitfields array */ + uint32_t max; /*!< The maximum number of bits that can be set */ + uint32_t count; /*!< The current number of bits set */ +} bitfield_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief Initializes a preallocated \ref bitfield_t with a max number of bits + * \param b The pointer to the bitfield_t structure to initialize. + * \param max The maximum number of bit needed. + * \ingroup group_bitfields + */ +void bitfield_init(bitfield_t *b, uint32_t max); + +/*! \brief Deinitializes a \ref bitfield_t + * \param b The pointer to the bitfield_t structure to initialize. + * \ingroup group_bitfields + */ +void bitfield_deinit(bitfield_t *b); + +/*! \brief Lowers bit at index specified + * \param b The pointer to the bitfield_t structure to initialize. + * \param bit The bit to clear. + * \ingroup group_bitfields + */ +bool_e bitfield_rls(bitfield_t *b, uint32_t bit); + +/*! \brief Raises bit at index specific unless already raised. + * \param b The pointer to the bitfield_t structure to initialize. + * \param bit The pointer to the place to store an acquired bit. + * \ingroup group_bitfields + */ +bool_e bitfield_get(bitfield_t *b, uint32_t *bit); + +/*! \brief Returns the number of bits set + * \param b The pointer to the bitfield_t structure to initialize. + * \ingroup group_bitfields + */ +uint32_t bitfield_count(bitfield_t *b); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/sosal/btreelist.h b/include/sosal/btreelist.h new file mode 100644 index 0000000..6ef14ec --- /dev/null +++ b/include/sosal/btreelist.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +/*! + * \file btreelist.h + * \brief The Binary Search Tree Structure. + * \author Erik Rainey + */ + +/*! \brief The btreelistnode is both in a double link list of all nodes and + * in the binary tree structure of nodes + * \ingroup group_btreelists + */ +typedef struct btreelistnode { + struct btreelistnode *next; /*!< Next node in the double link list */ + struct btreelistnode *prev; /*!< Previous node in the double link list */ + struct btreelistnode *left; /*!< Left node in the binary search tree. */ + struct btreelistnode *right; /*!< Right node in the binary search tree. */ +} btreelistnode_t; + +/*! \brief A typedef of a compare function used to find a specific node in the tree. + * \ingroup group_btreelists + */ +typedef int (*btreelistnode_compare)(btreelistnode_t *node, value_t value); + +/*! \brief A typedef of a sorting function used to sort nodes in the double link list + * \ingroup group_btreelists + */ +typedef int (*btreelistnode_sort)(btreelistnode_t *node, btreelistnode_t *obj); + +/*! \brief A typedef of a printing function used to debug the nodes + * \ingroup group_btreelists + */ +typedef char *(*btreelistnode_print)(btreelistnode_t *node); + +/*! \brief The top level Binary Tree List structure + * \ingroup group_btreelists + */ +typedef struct btreelist { + btreelistnode_t *root; /*!< Top node in the binary tree */ + btreelistnode_t *head; /*!< First node in the double link list */ + btreelistnode_t *tail; /*!< Last node in the double link list */ + btreelistnode_t **array; /*!< Pointer to array of pointers to all nodes in the tree (unordered). */ + btreelistnode_compare compare; /*!< The supplied compare function. */ + btreelistnode_sort sort; /*!< The supplied sorting function. */ + btreelistnode_print print; /*!< The supplied printing function. */ + int32_t count; /*!< The number of nodes in the tree. */ +} btreelist_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief This creates a binary tree list with the supplied funtions. + * \param compfunc The user defined comparison function. + * \param sortfunc The user defined sorting function. + * \param printfunc The user defined printing function. + * \returns btreelist_t * + * \ingroup group_btreelists + */ +btreelist_t *btreelist_create(btreelistnode_compare compfunc, btreelistnode_sort sortfunc, btreelistnode_print printfunc); + +/*! \brief This destroys a binary tree list. + * \param btl The pointer to the binary tree list. + * \ingroup group_btreelists + * \pre \ref btreelist_create + */ +void btreelist_destroy(btreelist_t *btl); + +/*! \brief This adds a node to a binary tree list. + * \param btl The pointer to the binary tree list. + * \param btln The pointer to the binary tree node to add to the structure. + * \note the node must be preallocated elsewhere. + * \ingroup group_btreelists + */ +void btreelist_add(btreelist_t *btl, btreelistnode_t *btln); + +/*! \brief This finds a specific node in a binary tree list based on the + * supplied value which is passed to the compare function. + * \param btl The pointer to the binary tree list. + * \param value The value used to find the matching node in the btreelist. + * \ingroup group_btreelists + */ +btreelistnode_t *btreelist_find(btreelist_t *btl, value_t value); + +/*! \brief This finds and removes a node from the binary tree list based on a + * match to the supplied value via the compare method. + * \param btl The pointer to the binary tree list. + * \param value The value used to find and remove a matching node in the btreelist. + * \ingroup group_btreelists + */ +btreelistnode_t *btreelist_remove(btreelist_t *btl, value_t value); + +#ifdef __cplusplus +} +#endif + diff --git a/include/sosal/cache.h b/include/sosal/cache.h new file mode 100644 index 0000000..c102f8e --- /dev/null +++ b/include/sosal/cache.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_CACHE_H_ +#define _SOSAL_CACHE_H_ + +/*! + * \file cache.h + * \brief A Memory Caching Structure which can be used in front of a frequently + * read file or any high latency access data structure. + * \author Erik Rainey + */ + +#include +#include + +/*! \brief This function backs the cache with it's data source at the appropriate index. + * \ingroup group_cache + */ +typedef size_t (*cache_fill_f)(void *cookie, uint8_t *ptr, size_t size, size_t offset); + +/*! \brief This function writes a line back to the data source from the specified index + * \ingroup group_cache + */ +typedef size_t (*cache_commit_f)(void *cookie, uint8_t *ptr, size_t size, size_t offset); + +/*! \brief These policies change the default behavior of the cache. + * \ingroup group_cache + */ +typedef enum _cache_policy_e { + CACHE_POLICY_WRITE_THROUGH, /*!< Data is committed when written. */ + CACHE_POLICY_WRITE_BACK, /*!< Data is committed when aged out. */ +} cache_policy_e; + +/*! \brief The line data of the cache. + * \ingroup group_cache + */ +typedef struct _cache_line_t { + bool_e locked; + bool_e valid; + clock_t age; + size_t start_offset; + size_t end_offset; + uint8_t *data; +} cache_line_t; + +/*! \brief The top level structure of the cache. + * \ingroup group_cache + */ +typedef struct _cache_t { + cache_line_t *line; /*!< The pointer to the line data. */ + size_t numLines; /*!< The number of lines in the cache. */ + size_t lineSize; /*!< The size of each line in bytes. */ + cache_policy_e policy; /*!< The aging policy. */ + cache_fill_f fillLine; /*!< The line filling function. */ + cache_commit_f commitLine; /*!< The line committing function. */ + void *cookie; /*!< The user's private data to pass to the functions. */ + mutex_t mutex; /*!< The mutex which protects data access for the cache. */ +} cache_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief This function destroys a cache. All the lines will be committed or flushed + * before destruction. + * \param [in] cache The pointer to the cache metadata. + * \ingroup group_cache + * \pre \ref cache_create + */ +void cache_destroy(cache_t *cache); + +/*! \brief This method creates an in-memory cache for use with external high-latency + * sources. For example, this could be placed in front of a file or socket. + * \param [in] lineSize The size of each line in bytes. + * \param [in] numLines The number of lines in the cache. + * \param [in] policy The cache aging policy. + * \param [in] fill The cache filling function. + * \param [in] commit The line committing function. + * \param [in] cookie The private user data to pass into the supplied functions. + * \ingroup group_cache + */ +cache_t *cache_create(size_t lineSize, + size_t numLines, + cache_policy_e policy, + cache_fill_f fill, + cache_commit_f commit, + void *cookie); + +/*! \brief This functions reads data through the cache from the source. + * \param [in] cache The pointer to the cache metadata. + * \param [in] data The pointer to the buffer to read data into. + * \param [in] len The length of the data to read. + * \param [in] offset The offset in the cache to read from. + * \ingroup group_cache + */ +size_t cache_read(cache_t *cache, uint8_t *data, size_t len, size_t offset); + +/*! \brief This function writes data through the cache into the source. + * \param [in] cache The pointer to the cache metadata. + * \param [in] data The pointer to the buffer to write data from into the cache. + * \param [in] len The length of the data to write. + * \param [in] offset The offset in te cache to write the data to. + * \ingroup group_cache + */ +size_t cache_write(cache_t *cache, uint8_t *data, size_t len, size_t offset); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/sosal/debug.h b/include/sosal/debug.h new file mode 100644 index 0000000..40ee554 --- /dev/null +++ b/include/sosal/debug.h @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_DEBUG_H_ +#define _SOSAL_DEBUG_H_ + +#include + +/*! + * \file + * \brief The SOSAL Debugging Zone Definitions. + * \author Erik Rainey + * \details This is the manner of usage when debugging code. +\code +status = function(parameters); +if (status < 0) { +SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR: Call failed with error=%d\n", status); +} +\endcode +* or +\code +status = function(parameters); +SOSAL_ASSERT(status >= 0); +\endcode + */ + +#ifdef SOSAL_DEBUG + +/*! \brief A wrapper around a print. + * \ingroup group_sosal_debug + */ +#define SOSAL_ASSERT(conditional) if (!(conditional)) {\ + printf("SOSAL_ASSERT in %s@%u: %s\n", __FILE__, __LINE__, #conditional);\ +} + +#if defined(WIN32) && !defined(CYGWIN) +#include +#include +#include +/*! \brief An inline function which allows for variable arguments to the printing function + * the MS Compiler which does not allow variable arguments in macros. + * \param [in] conditional Typically a SOSAL Zone flag. + * \param [in] string The format string to print. + * \param [in] ... The variable arguments used to fill in the format string. + * \ingroup group_sosal_debug + */ +_inline void SOSAL_PRINT(int conditional, char *string, ...) { + if (conditional) + { + char format[255]; + va_list ap; + sprintf(format, "%08x: %s", GetCurrentThreadId(), string); + va_start(ap, string); + vprintf(format, ap); + va_end(ap); + } +} +#elif defined(SYSBIOS) +/*! \brief An inline function which allows for variable arguments to the printing function + * the TMS470 Compiler which does not allow variable arguments in macros. + * \param [in] conditional Typically a SOSAL Zone flag. + * \param [in] string The format string to print. + * \param [in] ... The variable arguments used to fill in the format string. + * \ingroup group_sosal_debug + */ +#include +#include // to enable vprintf() +inline void SOSAL_PRINT(int conditional, char *string, ...) { + if (conditional) + { + va_list ap; + va_start(ap, string); + vprintf(string, ap); + va_end(ap); + } +} +#else +#if (SOSAL_DEBUG == 2) && defined(ANDROID) +#include +/*! \brief A wrapper around a platform specific debugging API. + * \param [in] conditional Typically a SOSAL_ZONE_XXXX defintion. + * \param [in] string A format string + * \param [in] ... Variable arguments to match the format string. + * \ingroup group_sosal_debug + */ +#define SOSAL_PRINT(conditional, string, ...) if (conditional) { __android_log_print(ANDROID_LOG_DEBUG, #conditional, string, ## __VA_ARGS__); } +#else +/*! \brief A wrapper around a platform specific debugging API. + * \param [in] conditional Typically a SOSAL_ZONE_XXXX defintion. + * \param [in] string A format string + * \param [in] ... Variable arguments to match the format string. + * \ingroup group_sosal_debug + */ +#define SOSAL_PRINT(conditional, string, ...) if (conditional) { printf(#conditional ": " string, ## __VA_ARGS__); } +#endif + +#endif + +#ifndef SOSAL_ZONE_MASK +#define SOSAL_RUNTIME_DEBUG +/*! \brief The runtime SOSAL debugging mask. + * \ingroup group_sosal_mask + */ +extern uint32_t sosal_zone_mask; +#define SOSAL_ZONE_MASK sosal_zone_mask +#endif + +#else // ifdef SOSAL_DEBUG + +#define SOSAL_ASSERT(conditional, format, ...) {} +#define SOSAL_PRINT(conditional, format, ...) {} + +#endif // ifdef SOSAL_DEBUG + +#define SOSAL_BIT(x) (1 << (x)) +#define SOSAL_ZONE_ERROR (SOSAL_BIT(0) & SOSAL_ZONE_MASK) /**< Intended for error cases in all the code */ +#define SOSAL_ZONE_WARNING (SOSAL_BIT(1) & SOSAL_ZONE_MASK) /**< Intended for warning in any code */ +#define SOSAL_ZONE_API (SOSAL_BIT(2) & SOSAL_ZONE_MASK) /**< Intended for API tracing in any code */ +#define SOSAL_ZONE_CACHE (SOSAL_BIT(3) & SOSAL_ZONE_MASK) + +#define SOSAL_ZONE_EVENT (SOSAL_BIT(4) & SOSAL_ZONE_MASK) +#define SOSAL_ZONE_HASH (SOSAL_BIT(5) & SOSAL_ZONE_MASK) +#define SOSAL_ZONE_HEAP (SOSAL_BIT(6) & SOSAL_ZONE_MASK) +#define SOSAL_ZONE_HISTO (SOSAL_BIT(7) & SOSAL_ZONE_MASK) + +#define SOSAL_ZONE_LIST (SOSAL_BIT(8) & SOSAL_ZONE_MASK) +#define SOSAL_ZONE_MODULE (SOSAL_BIT(9) & SOSAL_ZONE_MASK) +#define SOSAL_ZONE_OPTIONS (SOSAL_BIT(10)& SOSAL_ZONE_MASK) +#define SOSAL_ZONE_QUEUE (SOSAL_BIT(11)& SOSAL_ZONE_MASK) + +#define SOSAL_ZONE_SEMA (SOSAL_BIT(12)& SOSAL_ZONE_MASK) +#define SOSAL_ZONE_SERIAL (SOSAL_BIT(13)& SOSAL_ZONE_MASK) +#define SOSAL_ZONE_THREAD (SOSAL_BIT(14)& SOSAL_ZONE_MASK) +#define SOSAL_ZONE_UINPUT (SOSAL_BIT(15)& SOSAL_ZONE_MASK) + +#define SOSAL_ZONE_VECTOR (SOSAL_BIT(16)& SOSAL_ZONE_MASK) +#define SOSAL_ZONE_INI (SOSAL_BIT(17)& SOSAL_ZONE_MASK) +#define SOSAL_ZONE_SOCKET (SOSAL_BIT(18)& SOSAL_ZONE_MASK) +#define SOSAL_ZONE_SHARED (SOSAL_BIT(19)& SOSAL_ZONE_MASK) + +#define SOSAL_ZONE_RPC (SOSAL_BIT(20)& SOSAL_ZONE_MASK) +#define SOSAL_ZONE_IMAGE (SOSAL_BIT(21)& SOSAL_ZONE_MASK) +#define SOSAL_ZONE_PIPE (SOSAL_BIT(22)& SOSAL_ZONE_MASK) +#define SOSAL_ZONE_BTREE (SOSAL_BIT(23)& SOSAL_ZONE_MASK) + +#define SOSAL_ZONE_MEM (SOSAL_BIT(24)& SOSAL_ZONE_MASK) +#define SOSAL_ZONE_TIMER (SOSAL_BIT(25)& SOSAL_ZONE_MASK) + +#define SOSAL_ZONE_EXTRA (SOSAL_BIT(31)& SOSAL_ZONE_MASK) +#define SOSAL_ZONE_ALWAYS (1) + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \brief This function will query the environment to find a mask variable. It will + * treat that mask value as a hexidecimal string. i.e. "0x10FE". + * \param [in] mask_name The string describing the environment variable name to query. + * \param [in] mask The poitner to the location to store the mask. + * \ingroup group_sosal_debug + */ +void debug_get_zone_mask(char *mask_name, uint32_t *mask); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/sosal/event.h b/include/sosal/event.h new file mode 100644 index 0000000..4357e32 --- /dev/null +++ b/include/sosal/event.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_EVENT_H_ +#define _SOSAL_EVENT_H_ + +/*! + * \file + * \brief A simple event mechanism. + * \author Erik Rainey + */ + +#include + +#ifdef POSIX +#if !defined(__timespec_defined) && !defined(ANDROID) && !defined(__QNX__) && !defined(CYGWIN) && !defined(DARWIN) +/*! Redefinition of the native timespec structure */ +struct timespec +{ + __time_t tv_sec; /*!< Seconds. */ + long int tv_nsec; /*!< Nanoseconds. */ +}; +#endif + +/*! + * \brief The SOSAL Event Data Type. + * In a POSIX environment, this wraps the pthread implementations of conditions and a mutex. + * \ingroup group_events + */ +struct _event_posix_t { + pthread_cond_t cond; /*!< The PThread Condition */ + pthread_condattr_t attr; /*!< The PThread Condition Attribute */ + pthread_mutex_t mutex; /*!< The PThread Mutex */ + bool_e autoreset; /*!< Indicates whether the event will auto-reset after signalling */ + bool_e set; /*!< The current event value */ +}; + +/*! \brief The SOSAL Event Type. + * \ingroup group_events + */ +typedef struct _event_posix_t event_t; + +#elif defined(SYSBIOS) + +#include + +#define SYSBIOS_SINGLE_EVENT_FLAG_MASK (1<<0) +#include +struct _event_sysbios_t { + mutex_t mutex; /*!< The PThread Mutex */ + bool_e autoreset; /*!< Indicates whether the event will auto-reset after signalling */ + bool_e set; /*!< The current event value */ + Event_Handle event_group; +}; + +typedef struct _event_sysbios_t event_t; + +#else + +/*! \brief In Windows this wraps the a HANDLE which is used in the Event API. + * \ingroup group_events + */ +typedef HANDLE event_t; + +#endif + +/*! \brief The longest time possible for an event to wait. + * \ingroup group_events + */ +#define EVENT_FOREVER (0xFFFFFFFF) + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * Initializes an event. + * \param [in] e The pointer to the event structure + * \param [in] autoreset Determine whether the event autoresets + * \return bool_e + * \ingroup group_events + */ +bool_e event_init(event_t *e, bool_e autoreset); + +/*! + * \brief Deinitializes an event. + * \param [in] e The pointer to the event structure + * \ingroup group_events + */ +bool_e event_deinit(event_t *e); + +/*! \brief Waits for an event to trigger for a timeout period. + * \param [in] e The pointer to the event. + * \param [in] timeout The period in milliseconds to wait for the timeout. + * \retval false_e The wait timed-out. + * \retval true_e The event triggered. + * \ingroup group_events + */ +bool_e event_wait(event_t *e, uint32_t timeout); + +/*! \brief Triggers the event. If the event is auto-resetting, the state will be reset + * once the function returns. If not, a call to event_reset is required. + * \param [in] e The pointer to the event. + * \ingroup group_events + */ +bool_e event_set(event_t *e); + +/*! \brief Resets an event to un-triggered. + * \param [in] e The pointer to the event. + * \ingroup group_events + */ +bool_e event_reset(event_t *e); + +// INTERNAL FUNCTIONS +typedef struct timespec tspec; +void milliseconds_from_now(tspec *time_spec, uint32_t milliseconds); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/sosal/fourcc.h b/include/sosal/fourcc.h new file mode 100644 index 0000000..2857b95 --- /dev/null +++ b/include/sosal/fourcc.h @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_FOURCC_H_ +#define _SOSAL_FOURCC_H_ + +/*! + * \file + * \brief The List of Color Spaces expressed as a combination of 4 character codes. + */ + +/*! \brief The list of supported FOURCC codes in the SOSAL. + * \see http://www.fourcc.org + * \ingroup group_fourcc + */ +enum _fourcc { + + FOURCC_NONE = 0, /*!< An invalid code */ +//#if !defined(WIN32) && !defined(CYGWIN) + // RIFF and AVI Container codes + FOURCC_RIFF = 0x46464952, /*!< AVI File Header Type */ + FOURCC_LIST = 0x5453494C, /*!< AVI List Code */ +//#endif + FOURCC_AVI = 0x20495641, /*!< AVI Code */ + FOURCC_HDRL = 0x6C726468, /*!< AVI List Chunk Type */ + FOURCC_MOVI = 0x69766F6D, /*!< AVI List Chunk Type */ + FOURCC_AVIH = 0x68697661, /*!< AVI List Header Type */ + FOURCC_STRL = 0x6C727473, /*!< AVI Stream List */ + FOURCC_STRH = 0x68727473, /*!< AVI Stream Header */ + FOURCC_STRF = 0x66727473, /*!< AVI Stread Format Header */ + FOURCC_VIDS = 0x73646976, /*!< AVI Video Format */ + FOURCC_JUNK = 0x4B4E554A, /*!< AVI Junk Section */ + + // YUV + + // interleaved + FOURCC_UYVY = 0x59565955, /*!< 4:2:2 Interleaved YUV Macropixel in u0,y0,v0,y1 order */ + FOURCC_YUY2 = 0x32595559, /*!< 4:2:2 Interleaved YUV Macropixel in y0,u0,y1,v0 order */ + FOURCC_YVYU = 0x55595659, /*!< 4:2:2 Interleaved YUV Macropixel in y0,v0,y1,u0 order */ + FOURCC_VYUY = 0x59555956, /*!< 4:2:2 Interleaved YUV Macropixel in v0,y0,u0,y1 order */ + + // planar + FOURCC_YUV9 = 0x39565559, /*!< 4:1:1 Planar YUV */ + FOURCC_YVU9 = 0x39555659, /*!< 4:1:1 Planar YVU */ + FOURCC_YV12 = 0x32315659, /*!< 4:2:0 Planar YVU */ + FOURCC_IYUV = 0x56555949, /*!< 4:2:0 Planar YUV */ + FOURCC_YV16 = 0x36315659, /*!< 4:2:2 Planar YVU */ + FOURCC_YU16 = 0x36315559, /*!< 4:2:2 Planar YUV (unoffical) */ + FOURCC_YV24 = 0x34325659, /*!< 4:4:4 Planar YVU (unoffical) */ + FOURCC_YU24 = 0x34325559, /*!< 4:4:4 Planar YUV (unoffical) */ + FOURCC_Y800 = 0x30303859, /*!< 8 bit Luma only */ + FOURCC_Y16 = 0x20363159, /*!< 16 bit Luma only */ + FOURCC_Y32 = 0x20323359, /*!< 32 bit Luma only */ + + // semi-planar + FOURCC_NV12 = 0x3231564E, /*!< Y Plane + UV Plane packed with 2x2 subsampling */ + FOURCC_NV21 = 0x3132564E, /*!< Y Plane + VU Plane packed with 2x2 subsampling */ + + // RGB + + FOURCC_RGB565 = 0x35424752, /*!< 5:6:5 Interleaved single plane RGB data. */ + FOURCC_BGR565 = 0x35524742, /*!< 5:6:5 Interleaved single plane BGR data. */ + + // interleaved + FOURCC_BGR = 0x33524742, /*!< 24 bit (3 Interleaved 8 bit channels) BGR (unofficial) in b0,g0,r0 order */ + FOURCC_RGB = 0x33424752, /*!< 24 bit (3 Interleaved 8 bit channels) RGB (unofficial) in r0,g0,b0 order */ + FOURCC_RGBA = 0x41424752, /*!< 32 bit (4 Interleaved 8 bit channels) RGBA in r0,g0,b0,a0 order */ + FOURCC_BGRA = 0x41524742, /*!< 32 bit (4 Interleaved 8 bit channels) BGRA in b0,g0,r0,a0 order */ + FOURCC_ARGB = 0x42475241, /*!< 32 bit (4 Interleaved 8 bit channels) ARGB in a0,r0,g0,b0 order */ + + // planar + FOURCC_RGBP = 0x50424752, /*!< 8 bit Planar RGB (unoffical) */ + + // HSL + // planar + FOURCC_HSLP = 0x504C5348, /*!< 8 bit planar HSL (unoffical) */ + + // BINARY + FOURCC_BIN1 = 0x314E4942, /*!< 1 bit (8 bits per byte) planar 'image' (unofficial) */ +}; + +#if defined(WIN32) || defined(UNDER_CE) || defined(CYGWIN) +/*! \brief The fourcc_t type which is fixed to a 32 bit representation. + * \ingroup group_fourcc + */ +typedef uint32_t fourcc_t; +#else +/*! \brief The fourcc_t type which is fixed to a 32 bit representation. + * \ingroup group_fourcc + */ +typedef uint32_t fourcc_t; +#endif + +/*! \brief A macro to cast a string into a fourcc_t code. + * \ingroup group_fourcc + */ +#define FOURCC_STRING(x) (*(fourcc_t *)x) + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief String to fourcc_t Code conversion routine to avoid Unaligned memory accesses. + * \param [in] string The string to convert to a FOURCC code. + * \ingroup group_fourcc + */ +fourcc_t strtofourcc(const char *string); + +/*! \brief Converts a FOURCC code to a 4 character string plus null. + * \param [in] code The FOURCC code to convert to a string. + * \note The string returned is a static character array. Multithreaded access is not + * guaranteed. + * \ingroup group_fourcc + */ +char *fourcctostr(fourcc_t code); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/sosal/fph.h b/include/sosal/fph.h new file mode 100644 index 0000000..a722f8d --- /dev/null +++ b/include/sosal/fph.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_FPH_H_ +#define _SOSAL_FPH_H_ + +/*! + * \file fph.h + * \brief The Fast Pointer Hash API. + * \author Erik Rainey + */ + +/*! \brief The recommended size of a FPH block. + * \ingroup group_fph + */ +#define FPH_BLOCK_SIZE (256) + +/*! \brief The recommended number of blocks in a FPH. + * \ingroup group_fph + */ +#define FPH_NUM_BLOCKS (256) + +/*! \brief Enables some math optimizations to make the hash faster but with a trade-off + * of more rigid size requirements. + * \ingroup group_fph + */ +#undef FPH_OPTIMIZED + +/*! \brief Enables or disabled metrics gathering. + * \ingroup group_fph + */ +#define FPH_METRICS + +#include + +/*! + * \brief The key/value pair structure for a Fast Pointer Hash. + * \ingroup group_fph + */ +typedef struct _fph_kv_t +{ + /*! The key used to access this value pair */ + ptr_t key; + /*! The value which is stored at the hashed location */ + ptr_t value; +} fph_kv_t; + +/*! \brief The function type for the hashing functions for the Fast Pointer Hash. + * \ingroup group_fph + */ +typedef value_t (*fph_key_f)(void *fph, ptr_t value); + +/*! + * \brief The Fast Pointer Hash data structure. + * \ingroup group_fph + */ +typedef struct _fph_t +{ + fph_kv_t *hash; /*!< Pointer to the raw array of value pairs */ + size_t blockSize; /*!< The initialized number of blocks in the hash */ + size_t numBlocks; /*!< The initialized size of each block */ + size_t numElem; /*!< The total number of elements in the hash */ + fph_key_f keyFunc; /*!< The pointer to the hashing function */ +#ifdef FPH_METRICS + uint32_t *collisions; /*!< The total number of collisions in each block of the hash */ + uint32_t *length; /*!< The current number of items in each block of the hash */ + uint32_t numReplacements; /*!< The number of times any value pair has been replaced */ + uint32_t numPtrs; /*!< The total number of pointers in the hash */ + uint32_t numMisses; /*!< The number of misses, pointers which could not be remembered */ +#endif +} fph_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \brief Initializes the Fast Pointer Hash. + * \param [in] numBlocks The number of blocks in the hash. + * \param [in] blockSize The size of each block (count * sizeof(ptr_t)). + * \param [in] keyFunc A user provided hashing function to generate indexes into the hash. + * \note If you write your own hashing function, you'll need to use the numBlocks and blockSize in the hash structure. + * \ingroup group_fph + */ +fph_t *fph_init(size_t numBlocks, size_t blockSize, fph_key_f keyFunc); + +/*! + * \brief Deinitializes the Fast Pointer Hash data structures. + * \param [in] fph The pointer to the fast pointer hash data structure. + * \pre \ref fph_init + * \ingroup group_fph + */ +void fph_deinit(fph_t *fph); + +/*! + * \brief Retrieves the value at the desired key location. + * \param [in] fph The pointer to the Fast Pointer Hash. + * \param [in] k The key + * \param [out] v The pointer to the location to store the value. + * \ingroup group_fph + */ +int fph_get(fph_t *fph, ptr_t k, ptr_t *v); + +/*! + * \brief Clears the value at the location indicated by the key. + * \param [in] fph The pointer to the Fast Pointer Hash. + * \param [in] k The key. + * \ingroup group_fph + */ +int fph_clr(fph_t *fph, ptr_t k); + +/*! + * \brief Sets the key/value pair in the hash. + * \param [in] fph The pointer to the Fast Pointer Hash. + * \param [in] k The key + * \param [in] v The value + * \ingroup group_fph + */ +int fph_set(fph_t *fph, ptr_t k, ptr_t v); + +#ifdef __cplusplus +} +#endif + +#endif // _FPH_H_ diff --git a/include/sosal/hash.h b/include/sosal/hash.h new file mode 100644 index 0000000..57dc9c1 --- /dev/null +++ b/include/sosal/hash.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_HASH_H_ +#define _SOSAL_HASH_H_ + +/*! + * \file + * \brief A Hash Table implementation which is an array of lists. + * \author Erik Rainey + */ + +#include +#include + +/*! \brief The key value pair which is the data storage of the hash. + * \ingroup group_hashes + */ +typedef struct _record_t { + value_t key; /*!< The key used to index the hash */ + value_t value; /*!< The value */ +} record_t; + +/*! \brief These define the key depth. + * \ingroup group_hashes + */ +typedef enum _hash_sizes { + HASH_SIZE_SMALL = 8, /*!< Uses an 8 bit indexable table. */ + HASH_SIZE_MEDIUM = 12, /*!< Uses a 12 bit indexable table. */ + HASH_SIZE_LARGE = 16, /*!< Uses a 16 bit indexable table. */ +} hash_size_e; + +/*! \brief The hashing function which generates the indexing into the list array. + * \param [in] numElem The number of elements in the hash table. + * \param [in] key The key to use to generate the index in the table. + * \ingroup group_hashes + */ +typedef value_t (*hash_func_f)(size_t numElem, value_t key); + +/*! \brief The hash meta data structure. + * \ingroup group_hashes + */ +typedef struct _hash { + hash_size_e size; /*!< \brief The indexing table bit depth. */ + size_t numTotalElem; /*!< \brief The number of total elements in the hash. */ + size_t numActiveSlots; /*!< \brief The number of active slots in the hash. */ + size_t numSlots; /*!< \brief The number of slots in the table. */ + hash_func_f keyFunc; /*!< \brief The function pointer to the hashing function. */ + list_t **bucket; /*!< \brief The key indexed table of all lists of elements. */ +} hash_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief The function which initializes the hash. + * \param [in] size The enumerated size of the bitdepth of the table. 8, 12, or 16. + * \param [in] keyFunc the pointer to the custom keygen function is one is desired. + * The default implementation will be used if NULL is given. + * \ingroup group_hashes + */ +hash_t *hash_init(hash_size_e size, hash_func_f keyFunc); + +/*! + * \brief This function sets a value into the hash using the key. + * \param [in] h The hash. + * \param [in] key The keying value. + * \param [in] value the pointer to the value to store. If NULL, any existing value is removed from the hash. + * \ingroup group_hashes + */ +void hash_set(hash_t *h, value_t key, value_t value); + +/*! + * \brief This function retrieves a value from the hash using the key. + * \param [in] h The hash. + * \param [in] key The keying value. + * \param [out] value The pointer to the location to store the value. + * \ingroup group_hashes + */ +bool_e hash_get(hash_t *h, value_t key, value_t *value); + +/*! + * \brief This function returns each value contained in itself. + * \param [in] h The hash. + * \param [out] value the pointer to the location to store the value removed from the hash. Passing NULL will reset the cleaner. + * \return Returns the number of active elements in the hash. If called successively, this + * function will "drain" the hash. + * \ingroup group_hashes + */ +size_t hash_clean(hash_t *h, value_t *value); + +/*! + * \brief This function returns the number of actual entries in the hash (including the collisions). + * \param [in] h The hash. + * \return Returns the number of elements in the hash. A -1 indicates an error. + * \ingroup group_hashes + */ +size_t hash_length(hash_t *h); + +/*! + * \brief This function prints a description of the hash. + * \param [in] h The hash. + * \param [in] printElems Give 1 or 0 to choose to print the elements of the hash or not. + * \ingroup group_hashes + */ +void hash_print(hash_t *h, bool_e printElems); + +/*! + * \brief Deinitializes the hash. + * \param [in] h The hash to deinitialize. + * \ingroup group_hashes + */ +void hash_deinit(hash_t *h); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/sosal/heap.h b/include/sosal/heap.h new file mode 100644 index 0000000..6044cdf --- /dev/null +++ b/include/sosal/heap.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_HEAP_H_ +#define _SOSAL_HEAP_H_ + +/*! \file + * \brief A simple heap allocator. + * \author Erik Rainey + */ + +#include +#include + +/*! \brief The basic unit of an allocation. + * \ingroup group_heaps + */ +typedef struct _block_t { + size_t size; /*!< \brief The number of bytes in the block */ + void *data; /*!< \brief The pointer to the block data */ +} block_t; + +/*! \brief A heap_t is a set of list_t's of block_t's which manage the heap. + * \ingroup group_heaps + */ +typedef struct _heap_t { + void *raw; /*!< \brief This is the raw pointer to the memory area */ + list_t used; /*!< \brief This is the sorted list of all used blocks */ + list_t free; /*!< \brief This is the sorted list of all free blocks */ + list_t spare; /*!< \brief This is the sorted list of all spare blocks (not free and not used) */ + block_t *blocks; /*!< \brief The list of raw blocks (unsorted) */ + node_t *nodes; /*!< \brief The list of raw nodes (unlisted) */ + void *data; /*!< \brief This is the raw pointer to the heap area */ + size_t maxBlocks; /*!< \brief The maximum number of blocks that can created. */ + size_t align; /*!< \brief The alignment size in bytes of the allocations */ + size_t bytesUsed; /*!< \brief Counts all the used bytes */ + size_t bytesFree; /*!< \brief Counts all the free bytes */ + size_t bytesTotal; /*!< \brief This is the total for all the bytes in the heap. This includes the overhead sections */ + bool_e cleanPolicy; /*!< \brief This determines if the block is cleaned during frees */ + bool_e coalescePolicy;/*!< \brief This determines if the blocks will be coalesced during free operations */ + mutex_t mutex; /*!< \brief The access mutex */ +} heap_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \brief This function takes a pointer to a flat area and a byte count, creating a heap. + * It will 32bit align both the heap and the number of bytes. + * IE if you give it an odd pointer and an odd number of bytes + * you will have a less effective size of heap. + * \note Be sure you give this function 32bit aligned pointers and + * byte counts. + * \param [in] heap The pointer to the heap meta-data. + * \param [in] buffer The begining of the heap + * \param [in] size The size of buffer in the heap + * \param [in] p2align Pointer to align + * \ingroup group_heaps + */ +bool_e heap_init(heap_t *heap, void *buffer, size_t size, uint32_t p2align); + +/*! + * \brief Deconstructor of the heap. + * \param [in] heap The pointer to the heap meta-data. + * \post Set your heap pointer to NULL. + * \pre \ref heap_init + * \ingroup group_heaps + */ +void heap_deinit(heap_t *heap); + +/*! + * \brief Allocates a block of memory. + * \param heap The pointer to the heap meta-data. + * \param num_bytes The number of bytes requested (this will be internally rounded up) + * \return Returns the allocated pointer or NULL if not enough memory existed or some internal error prevents allocation. + * \note This will always return an aligned pointer. + * \pre \ref heap_init + * \post \ref heap_free + * \ingroup group_heaps + */ +void *heap_alloc(heap_t *heap, size_t num_bytes); + +/*! + * \brief Frees a buffer within the heap. + * \param heap The pointer to the heap meta-data. + * \param pointer The pointer to free + * \return Returns true if the memory was freed, false otherwise. + * \pre heap_allocate + * \pre heap_deinit + * \ingroup group_heaps + */ +bool_e heap_free(heap_t *heap, void *pointer); + +/*! + * \brief Checks to see if the buffer exists inside this heap area. + * \param heap Specified heap to check + * \param addr The address to check + * \return Returns a boolean, true if on the user heap, false otherwise. + * \pre heap_allocate + * \ingroup group_heaps + */ +bool_e heap_valid(heap_t *heap, void *addr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/sosal/histogram.h b/include/sosal/histogram.h new file mode 100644 index 0000000..b0e25a9 --- /dev/null +++ b/include/sosal/histogram.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_HISTOGRAM_H_ +#define _SOSAL_HISTOGRAM_H_ + +/*! \file + * \brief The Histogram API. + * \author Erik Rainey + */ + +#include + +/*! \brief A histogram with a fix number of bins. + * \ingroup group_histograms + */ +typedef struct _histogram_t { + uint32_t *bins; /*!< \brief The array of bins */ + uint32_t numBins; /*!< \brief The number of bins */ + int32_t binRange; /*!< \brief The range of each bin. */ + int32_t min; /*!< \brief The minimum value of the histogram */ + int32_t max; /*!< \brief The maximum value of the histogram */ +} histogram_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief This initializes the histogram to a set number of bins and a min/max. + * \param [in,out] histogram The histogram meta data. + * \param [in] bins The number of bins needed for the histogram. + * \param [in] min The minimum range the histogram covers. + * \param [in] max The maximum range the histogram covers. + * \ingroup group_histograms + */ +bool_e histogram_init(histogram_t *histogram, uint32_t bins, int32_t min, int32_t max); + +/*! \brief This de-initializes the histogram. + * \param [in] histogram The pointer to the histogram meta-data. + * \ingroup group_histograms + */ +void histogram_deinit(histogram_t *histogram); + +/*! \brief This increments the histogram bin which this value classifies into. + * \param [in] histogram The pointer to the histogram meta-data. + * \param [in] value The value to classify. + * \ingroup group_histograms + */ +void histogram_inc(histogram_t *histogram, int32_t value); + +/*! \brief This gets the bin count in which the value would be added. + * \param [in] histogram The pointer to the histogram meta-data. + * \param [in] value The value to use to get the bin count. + * \ingroup group_histograms + */ +uint32_t histogram_get(histogram_t *histogram, int32_t value); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/sosal/image.h b/include/sosal/image.h new file mode 100644 index 0000000..edf455e --- /dev/null +++ b/include/sosal/image.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_IMAGE_H_ +#define _SOSAL_IMAGE_H_ + +/*! \file + * \brief The SOSAL Image API. + * \author Erik Rainey + */ + +#include +#include + +/*! \brief The \ref image_t plane definition. + * \ingroup group_image_t + */ +typedef struct _plane_t { + uint8_t *ptr; /**< Plane Data Pointer */ + uint32_t xdim; /**< Plane x dimension in pixels */ + uint32_t ydim; /**< Plane y dimension in pixels */ + uint32_t xscale; /**< Plane x scale */ + uint32_t yscale; /**< Plane y scale */ + int32_t xstride; /**< Plane x stride between pixels in bytes */ + int32_t ystride; /**< Plane y stride between pixels in bytes */ + int32_t xstep; /**< Plane x step between pixels, if macro pixel, then > 1 */ + uint32_t numBytes;/**< Number of bytes in the plane */ +} plane_t; + +/*! \brief The definition of a multiplanar, multidimensional image. + * \ingroup group_image_t + */ +typedef struct _image_t { + fourcc_t color; /*!< \brief Color space. \see fourcc_t */ + plane_t plane[4]; /*!< \brief Plane information */ + uint32_t numPlanes; /*!< \brief This indicates the active number of planes */ +} image_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief This computes the pixel pointer at the given co-ordinates. + * \param [in] img The image pointer + * \param [in] p The plane index + * \param [in] x The x dimension + * \param [in] y The y dimension + * \pre \ref image_allocate + * \pre \ref image_back + * \ingroup group_image_t + */ +#define image_pixel(img, p, x, y) &img->plane[p].ptr[(img->plane[p].ystride*(y/img->plane[p].yscale))+(img->plane[p].xstride*(x/img->plane[p].xscale))] + +/*! \brief This function is used to determine if an image_t can be made of a particular format. + * \param [in] color The desired format. + * \ingroup group_image_t + */ +bool_e image_query_format(fourcc_t color); + +/*! \brief Frees an image and destroys the pointer. + * \param [in,out] pimg The pointer to the image_t pointer. This will be NULLed by the function. + * \pre \ref image_unback + * \ingroup group_image_t + */ +void image_free(image_t **pimg); + +/*! \brief Allocates an image meta-data structure with the given attributes. + * \param [in] width Width in pixels. + * \param [in] height Height in pixels. + * \param [in] color The FOURCC color code. + * \pre \ref image_query_format To determine if the format is possible. + * \post \ref image_back + * \ingroup group_image_t + * \retval NULL The allocation failed. + */ +image_t *image_allocate(uint32_t width, uint32_t height, fourcc_t color); + +/*! \brief This function will fill the image with the data in a, b, or c based + * on the format of the image. + * \param [in] img The pointer to the image. + * \param [in] a Most formats will use this field. FOURCC_Y800 will only use this field. + * \param [in] b Most formats will use this field. + * \param [in] c Most formats will use this field. + * \pre \ref image_back + * \ingroup group_image_t + */ +void image_fill(image_t *img, uint8_t a, uint8_t b, uint8_t c); + +/*! \brief This functions copies an image from source to destintation. + * \note If a conversion is required, some conversion will occur. See \iref image_convert for details. + * \param [out] dst Destination image. Must be pre-allocated. + * \param [in] src Source image. + * \pre \ref image_back + * \ingroup group_image_t + */ +uint32_t image_copy(image_t *dst, image_t *src); + +/*! \brief This function will convert one image format into another if it supports this. + * \param [out] dst The Destination image, must be pre-allocated. + * \param [in] src The source image. + * \pre \ref image_back + * \ingroup group_image_t + */ +void image_convert(image_t *dst, image_t *src); + +/*! \brief This function prints the meta-data of the image. + * \param [in] img The image to print. + * \pre \ref image_back + * \ingroup group_image_t + */ +void image_print(image_t *img); + +/*! \brief This function "backs" an an image meta-data structure with actual memory. + * \param [in] img The image to "back". + * \pre \ref image_allocate + * \post \ref image_unback + * \ingroup group_image_t + */ +bool_e image_back(image_t *img); + +/*! \brief This function removes the memory "backing" the image meta-data structure. + * \param [in] img The image to "unback". + * \pre \ref image_back + * \post \ref image_free + * \ingroup group_image_t + */ +void image_unback(image_t *img); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/sosal/ini.h b/include/sosal/ini.h new file mode 100644 index 0000000..81dc9a4 --- /dev/null +++ b/include/sosal/ini.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_INI_H_ +#define _SOSAL_INI_H_ + +/*! + * \file + * \brief A simple INI parser. + * \author Erik Rainey + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief INI parser callback used when the \ref ini_parse encounters a triple. + * \param [in] arg The user private data. + * \param [in] section The string describing the section. + * \param [in] variable The string describing the variable. + * \param [in] value The string describing the value. + * \ingroup group_ini + */ +typedef void (*ini_callback_f)(void *arg, char *section, char *variable, char* value); + +/*! \brief A list of capitalizations in INI files. + * \ingroup group_ini + */ +enum _ini_chars_e { + INI_NATURAL, /*!< Returns characters as they appear in the INI file. */ + INI_LOWER, /*!< Returns characters as lower case only */ + INI_UPPER, /*!< Returns characters as upper case only */ +}; + +/*! \brief Formal type definition for character capitalization types. + * \ingroup group_ini + */ +typedef enum _ini_chars_e ini_chars_e; + +/*! + * \brief This function will take the input buffer and parse out INI formatted variable/value pairs. + * \param [in] buffer The input characters, usually read from a file. + * \param [in] len the length of the buffer. + * \param [in] callback The callback function to give the parsed sction, variable and value set to. + * \param [in] char_case The enumerated value of which capitalization scheme is used. + * \param [in] arg A pointer that will be passed to the callback function. This can be used to hold a private structure or cookie. + * \ingroup group_ini + */ +int ini_parse(char *buffer, size_t len, ini_callback_f callback, ini_chars_e char_case, void *arg); + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/include/sosal/list.h b/include/sosal/list.h new file mode 100644 index 0000000..60cdcac --- /dev/null +++ b/include/sosal/list.h @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_LIST_H_ +#define _SOSAL_LIST_H_ + +/*! \file + * \brief The SOSAL Double Link List API. + * \author Erik Rainey + */ + +#include + +typedef uint32_t score_t; +#define MAX_SCORE (0xFFFFFFFF) +#define MIN_SCORE (0) + +/*! \brief The unit of a list_t. Typically a pointer is placed + * in the value field. + * \ingroup group_lists + */ +typedef struct _node_t{ + struct _node_t *next; /*!< \brief The next node in the list */ + struct _node_t *prev; /*!< \brief The previous node in the list */ + value_t data; /*!< \brief The generic value in this node */ +} node_t; + +/*! \brief The List meta-data. + * \ingroup group_lists + */ +typedef struct _list_t { + node_t *head; + node_t *tail; +} list_t; + +/*! + * \brief This type of function evaluates two nodes and returns some form of + * comparison between the two. + * \param [in] a The first node. + * \param [in] b The second node. + * \retval 0 when a = b or b == NULL + * \retval 1 when a > b + * \revtal (-1) when a < b + * \note How the comparison works is up to the implementor. + * \ingroup group_lists + */ +typedef int (*node_compare_f)(node_t *a, node_t *b); + +/*! + * \brief This type of function rates a node against another another node to + * produce a score which is used to evaluate the current node. This is usually + * use for a best-fit algorithm. + * \param [in] current The node to anaylize + * \param [in] best The node which is determined to be the best. + * \return Returns a score which rates the evaluations. + * \ingroup group_lists + */ +typedef score_t (*node_rate_f)(node_t *current, node_t *best); + +/*! + * \brief This prints the value of a node in a list. + * \param [in] node The node to print. + * \ingroup group_lists + */ +typedef void (*node_print_f)(node_t *node); + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief This creates a node from a data value. + * \param [in] data The value to place in the node. + * \return Returns a node pointer. + * \retval NULL Indicates a memory allocation failed. + * \post \ref node_destroy + * \ingroup group_lists + */ +node_t *node_create(value_t data); + +/*! \brief This destroys a node. + * \param [in] node The node to destroy. + * \return Returns the internal value_t. + * \pre \ref node_create + * \post Set your node pointer to NULL + * \ingroup group_lists + */ +value_t node_destroy(node_t *node); + +/*! \brief This creates a list + * \return Returns a list meta-data structure. + * \retval NULL indicates an error in allocation. + * \post list_destroy + * \ingroup group_lists + */ +list_t *list_create(void); + +/*! \brief Destroys a list. + * \param [in] list The list to destroy. + * \pre \ref list_create + * \post Set your list pointer to NULL. + * \ingroup group_lists + * \note This will remove all nodes and destroy them. + */ +void list_destroy(list_t *list); + +/*! \brief Appends a node to the tail of the list. + * \param [in] list The list to modify + * \param [in] node The node to add. + * \pre \ref list_create + * \ingroup group_lists + */ +void list_append(list_t *list, node_t *node); + +/*! \brief Removes the node at the tail of the list. + * \param [in] list The list to modify. + * \return Returns the node which was at the tail of the list. + * \retval NULL if the tail was empty. + * \pre \ref list_append or list_insert + * \post \ref node_destroy + * \ingroup group_lists + */ +node_t *list_trim(list_t *list); + +/*! \brief This puts a node at the head of the list. + * \param [in] list The list to modify. + * \param [in] node The node to add to the head. + * \pre \ref list_create + * \ingroup group_lists + */ +void list_push(list_t *list, node_t *node); + +/*! \brief This removes a node at the head of the list. + * \param [in] list + * \return Returns the node at the head of the list. + * \retval NULL if the list is empty. + * \pre \ref list_create + * \post \ref node_destroy + * \ingroup group_lists + */ +node_t *list_pop(list_t *list); + +/*! \brief This inserts in the order based on some sorting algorithm + * \param [in] list The list to insert into. + * \param [in] node The node to insert. + * \param [in] compare The function to determine the comparision. + * \return Returns node pointer inserted. + * \pre \ref list_create + * \ingroup group_lists + * \note A list which uses unsorted access like \ref list_append, \ref list_trim + * or \ref list_push and \ref list_pop should not use the insert as the + * nodes are unsorted and the insert depends on ordering. + */ +node_t *list_insert(list_t *list, + node_t *node, + node_compare_f compare, + bool_e sortAscending); + +/*! \brief This removes the node supplied from the list. + * \param [in] list The list to modify. + * \param [in] node The node to remove. + * \return Returns the node. + * \pre \ref list_create + * \post \ref node_destroy + * \ingroup group_lists + * \note Base on the pointer of node, not the value. + */ +node_t *list_extract(list_t *list, node_t *node); + +/*! \brief This removes the first node in which the compare function returns 0 + * \param [in] list The list to modify + * \param [in] node The node which contains the value to search for. + * \param [in] compare The function which determines the comparisions. + * \return Returns the node removed from the list. + * \retval NULL if no node matched. + * \pre \ref list_create + * \post \ref node_destroy + * \ingroup group_lists + */ +node_t *list_remove_match(list_t *list, + node_t *node, + node_compare_f compare); + +/*! \brief This finds a node within the list based on some sorting algorithm + * \param [in] list The list to modify + * \param [in] node The node which contains the value to search for. + * \param [in] compare The function which determine the comparisions. + * \return Returns the found node. + * \retval NULL if the node was not found. + * \pre \ref list_create + * \post \ref node_destroy + * \ingroup group_lists + */ +node_t *list_search(list_t *list, + node_t *node, + node_compare_f compare); + +/*! \brief This finds the node which has the best score aginst the supplied node. + * \param [in] list The list to rate. + * \param [in] node The node to rate against. + * \param [in] rate The rating function. + * \return Returns the node which best fits the rating function. + * \retval NULL if no node is found. + * \pre \ref list_create + * \ingroup group_lists + */ +node_t *list_score(list_t *list, + node_t *node, + node_rate_f rate); + +/*! \brief This computes the list's length. + * \param [in] list The list to query. + * \return Returns the size_t number of items in the list. + * \retval 0 if there are no items. + * \pre \ref list_create + * \ingroup group_lists + */ +size_t list_length(list_t *list); + +/*! \brief This prints all the nodes in the list using the supplied function. + * \param [in] list The list to print. + * \param [in] print The printing function. + * \pre \ref list_create + * \ingroup group_lists + */ +void list_print(list_t *list, node_print_f print); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/sosal/module.h b/include/sosal/module.h new file mode 100644 index 0000000..2fbff0a --- /dev/null +++ b/include/sosal/module.h @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_MODULE_H_ +#define _SOSAL_MODULE_H_ + +/*! \file + * \brief The SOSAL Module API. + * \author Erik Rainey + */ + +#include + +#define SOSAL_MODULE_API + +#if defined(ANDROID) || defined(LINUX) || defined(CYGWIN) || defined(DARWIN) || defined(__QNX__) + +#define POSIX_DL +#undef WIN32_DL +#undef SYSBIOS_SL + +#include +#if defined(CYGWIN) +#ifndef RTLD_LOCAL +#define RTLD_LOCAL (0) +#endif +#endif + +#elif defined(WIN32) + +#undef POSIX_DL +#define WIN32_DL +#undef SYSBIOS_SL + +#elif defined(SYSBIOS) + +#undef POSIX_DL +#undef WIN32_DL +#define SYSBIOS_SL + +#else // Unknown version + +#undef POSIX_DL +#undef WIN32_DL +#undef SYSBIOS_SL + +#endif // OSes + +#if defined(POSIX_DL) + +/*! \brief The module handle. + * \ingroup group_modules + */ +typedef void *module_t; + +/*! \brief The symbol handle. + * \ingroup group_modules + */ +typedef void *symbol_t; +#if defined(DARWIN) +#define MODULE_NAME(name) "lib"name".dylib" +#elif defined(CYGWIN) +#define MODULE_NAME(name) "lib"name".dll.a" +#else // QNX, LINUX +#define MODULE_NAME(name) "lib"name".so" +#endif +#define PATH_DELIM "/" +#define FMT_MODULE_T "%p" +#if defined(__QNX__) +#define MODULE_PATH PATH_DELIM"usr"PATH_DELIM"lib"PATH_DELIM +#else +#define MODULE_PATH "" +#endif +#define MODULE_EXPORT + +#elif defined(WIN32_DL) + +/*! \brief The module handle. + * \ingroup group_modules + */ +typedef HMODULE module_t; + +/*! \brief The symbol handle. + * \ingroup group_modules + */ +typedef FARPROC symbol_t; +#define MODULE_NAME(name) name".dll" +#define PATH_DELIM "\\" +#define MODULE_PATH "C:"PATH_DELIM"Windows"PATH_DELIM"system32"PATH_DELIM +#define FMT_MODULE_T "%p" +#define MODULE_EXPORT __declspec(dllexport) + +#elif defined(SYSBIOS_SL) + +#define MODULE_NAME(name) name +#define PATH_DELIM "_" +#define MODULE_PATH "" +#define FMT_MODULE_T "%p" +#define MODULE_EXPORT static + +/*! \brief A generic function pointer. + * \ingroup group_modules + */ +typedef void (*function_f)(void); + +/*! \brief A function is a symbol too. + * \ingroup group_modules + */ +typedef function_f symbol_t; + +/*! \brief Ties a function with a symbol name. + * \ingroup group_modules + */ +typedef struct _static_function_t { + char name[MAX_PATH]; + function_f func_ptr; +} static_function_t; + +/*! \brief Describes the static linking table of a module. + * \ingroup group_modules + */ +typedef struct _static_module_table_t { + char name[MAX_PATH]; + uint32_t numFunctions; + static_function_t *functions; +} static_module_table_t; + +/*! \brief A module in SYSBIOS is a static module. + * \ingroup group_modules + */ +typedef static_module_table_t *module_t; + +#else // No implementation + +#undef SOSAL_MODULE_API + +#endif // implementations + +#if defined(SOSAL_MODULE_API) + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief This function loads a module from the file system or from a static table. + * \param [in] filename The name of the module to load. + * \return Returns the handle to the module. + * \retval 0 if the module was not found. + * \post \ref module_unload + * \ingroup group_modules + * \note Clients should use \ref MODULE_NAME to generically load modules. + */ +module_t module_load(const char *filename); + +/*! \brief This function tries to get the handle to a symbol from a + * module. + * \param [in] mod The handle to the module. + * \return Returns the symbol handle which can be cast into a function pointer. + * \retval NULL if no such symbol exists. + * \pre \ref module_load + * \post \ref module_unload + * \ingroup group_modules + * \note Typically only "C" functions are loaded. However this will + * load any symbol name, which means if you know the managling + * mechanism, other symbols are accessible. + */ +symbol_t module_symbol(module_t mod, const char *symbol_name); + +/*! \brief This returns a pointer to an error string. + * \return Returns the error string. + * \ingroup group_modules + */ +char *module_error(); + +/*! \brief This function unloads a module. + * \param [in] mod The module to unload. + * \pre \ref module_load + * \ingroup group_modules + * \note The HLOS will typically keep an internal reference count, keeping + * the module in memory after the unload is called. + */ +void module_unload(module_t mod); + +#ifdef __cplusplus +} +#endif + +#endif // SOSAL_MODULE_API + +#endif // _SOSAL_MODULE_H_ + diff --git a/include/sosal/mutex.h b/include/sosal/mutex.h new file mode 100644 index 0000000..e6ac3ae --- /dev/null +++ b/include/sosal/mutex.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_MUTEX_H_ +#define _SOSAL_MUTEX_H_ + +/*! \file + * \brief The SOSAL Mutex API. + * \author Erik Rainey + */ + +#include + +#ifdef POSIX + +/*! \brief On POSIX system we wrap pthread_mutex_t. + * \ingroup group_mutexes + */ +typedef pthread_mutex_t mutex_t; +#define MUTEX_INITIAL PTHREAD_MUTEX_INITIALIZER + +#elif defined(SYSBIOS) + +#include +/*! \brief On SYSBIOS we wrap the GateMutexPri as it implements priority + * inheritance to protect against priority inversion. + * \ingroup group_mutexes + */ +typedef struct TIMM_OSAL_MUTEX { + GateMutexPri_Handle gate; + IArg key; +} TIMM_OSAL_MUTEX; + +/*! \brief Wrap another mutex thinly on SYSBIOS. + * \ingroup group_mutexes + */ +typedef TIMM_OSAL_MUTEX mutex_t; +#define MUTEX_INITIAL {0,0} + +#else +typedef CRITICAL_SECTION mutex_t; +#define MUTEX_INITIAL {0} +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief Initializes the mutex value. + * \param [in] m The pointer to the mutex. + * \post \ref mutex_deinit + * \ingroup group_mutexes + */ +void mutex_init(mutex_t *m); + +/*! \brief Deinitializes the mutex. + * \param [in] m The pointer to the mutex. + * \pre \ref mutex_init + * \ingroup group_mutexes + */ +void mutex_deinit(mutex_t *m); + +/*! \brief This locks access to the mutex and causes this thread to block if + * already acquired. + * \param [in] m The pointer to the mutex. + * \pre \ref mutex_init + * \post \ref mutex_unlock + * \ingroup group_mutexes + */ +void mutex_lock(mutex_t *m); + +/*! \brief This unlocks access to the mutex and causes other threads which + * were block to unblock. + * \param [in] m The pointer to the mutex. + * \pre \ref mutex_lock + * \post \ref mutex_deinit + * \ingroup group_mutexes + */ +void mutex_unlock(mutex_t *m); + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus + +namespace SOSAL { + /*! \brief The SOSAL C++ which wraps the mutex to permit "auto" locking by + * using C++'s autoinstancing and destruction of objects in a scope. + * \ingroup group_mutexes. + */ + class AutoLock { + private: + mutex_t *m_lock; + public: + /*! \brief A grabs the lock */ + AutoLock(mutex_t *m) { + m_lock = m; + mutex_lock(m_lock); + } + /*! \brief Releases the lock. + * \note This is called automatically by the compiler. + */ + ~AutoLock() { + mutex_unlock(m_lock); + } + }; +} +#endif + +#endif + diff --git a/include/sosal/options.h b/include/sosal/options.h new file mode 100644 index 0000000..10bf9b5 --- /dev/null +++ b/include/sosal/options.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_OPTIONS_H_ +#define _SOSAL_OPTIONS_H_ + +/*! \file + * \brief An interface to construct command line arguments. + * \author Erik Rainey + * \details This is used mainly to process the argc and argv of the main function. + * \code + int bob = 0; + option_t opts[] = {{OPTION_TYPE_INT. &bob, sizeof(int), "-b", "--bob", "Sets the bob variable"}}; + int main(int argc, char *argv[]) { + options_process(argc, argv, opts, dimof(opts)); + printf("bob=%i\n", bob); + } + * \endcode + */ + +#include + +/*! \brief The list of option types. + * \ingroup group_options + */ +typedef enum _option_type_e { + OPTION_TYPE_BOOL, /*!< \brief A boolean type */ + OPTION_TYPE_INT, /*!< \brief A integer type */ + OPTION_TYPE_HEX, /*!< \brief A hexidecimal integer */ + OPTION_TYPE_FLOAT, /*!< \brief A float number */ + OPTION_TYPE_STRING, /*!< \brief A string type */ +} option_type_e; + +/*! \brief The option structure which indicates how to parse the command line arguments. + * \ingroup group_options + */ +typedef struct _option_t { + option_type_e type; /*!< \brief The type of the argument. */ + void *datum; /*!< \brief The pointer to variable of the type specified. */ + size_t size; /*!< \brief The size of the buffer pointed to by datum */ + const char *short_switch; /*!< \brief The string which callers can use for easy access */ + const char *long_switch; /*!< \brief The string which callers can use for pedantic access */ + const char *description; /*!< \brief The string printed during a "usage" call. */ +} option_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief This function processes the argument list based on the opts array. + * \param [in] argc The number of arguments passed from main. + * \param [in] argv The array of arguments passed to main. + * \param [in] opts The option descriptions array. + * \param [in] numOpts The number of options in the opts array. + * \return Returns the number of arguments processed.s + * \ingroup group_options + */ +size_t option_process(int argc, char *argv[], option_t *opts, size_t numOpts); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/sosal/pipe.h b/include/sosal/pipe.h new file mode 100644 index 0000000..6f28498 --- /dev/null +++ b/include/sosal/pipe.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_PIPE_H_ +#define _SOSAL_PIPE_H_ + +/*! \file + * \brief The SOSAL Pipe API. + * \author Erik Rainey + */ + +#include + +/*! \brief A pipe construct. + * \ingroup group_pipes + */ +typedef struct _pipe_t { + int fd[2]; /*!< The read and write descriptors */ +} pipe_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief Closes a pipe + * \param [in] pp The pointer to the pointer to the pipe_t data + * \ingroup group_pipes + */ +void pipe_close(pipe_t **pp); + +/*! \brief Opens a pipe + * \param [in] name Opens a named pipe + * \ingroup group_pipes + */ +pipe_t *pipe_open(char *name); + +/*! \brief Reads from a pipe. + * \param [in] p The pipe context. + * \param [out] data The buffer to read data into. + * \param [in] len The length of the data buffer. + * \ingroup group_pipes + */ +uint32_t pipe_read(pipe_t *p, uint8_t *data, size_t len); + +/*! \brief Writes to a pipe + * \param [in] p The pipe context. + * \param [in] data The buffer to write from. + * \param [in] len The length of the data buffer. + * \ingroup group_pipes + */ +uint32_t pipe_write(pipe_t *p, uint8_t *data, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/sosal/profiler.h b/include/sosal/profiler.h new file mode 100644 index 0000000..fa40628 --- /dev/null +++ b/include/sosal/profiler.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_PROFILER_H_ +#define _SOSAL_PROFILER_H_ + +/*! \file + * \brief The SOSAL Profiling API + * \author Erik Rainey + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief The profiling data structure. + * \ingroup group_profilers + */ +typedef struct _profiler_t { + uint32_t numTimes; /**< \brief Internally used to help calculate the timing info. */ + rtime_t tmpTime; /**< \brief Used to record the last start time. After \ref profiler_stop, this contains the last session time. */ + rtime_t minTime; /**< \brief Used to record the minimum time of execution */ + rtime_t maxTime; /**< \brief Used to record the maximum time of execution */ + rtime_t avgTime; /**< \brief Used to record the average time of execution */ + rtime_t sumTime; /**< \brief Used to record the total time of execution of all iterations */ + rtime_t rate; /**< \brief This is used to record the clock rate per second on the local core */ +} profiler_t; + +/*! \brief Clears the profiling data structure and initializes it to known good values. + * \param [in,out] pprof The pointer to the profiling data structure. + * \ingroup group_profilers + */ +void profiler_clear(profiler_t *pprof); + +/*! \brief Starts a profiling session. + * \param [in,out] pprof The pointer to the profiling data structure. + * \ingroup group_profilers + */ +void profiler_start(profiler_t *pprof); + +/*! \brief Stops a profiling session and updates the profiling data structure. + * \param [in,out] pprof The pointer to the profiling data structure. + * \ingroup group_profilers + */ +void profiler_stop(profiler_t *pprof); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/sosal/pyuv.h b/include/sosal/pyuv.h new file mode 100644 index 0000000..a9a9fc7 --- /dev/null +++ b/include/sosal/pyuv.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _PYUV_H_ +#define _PYUV_H_ + +/*! \file + * \brief The SOSAL PYUV interfacing module for naming files. + * \author Erik Rainey + * \see http://dsplab.diei.unipg.it/pyuv_raw_video_sequence_player_original_one + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief Gets the extension which the supplied FOURCC code would use. + * \param [in] fourcc The \ref _fourcc code. + * \return Returns a pointer to an extension. + * \ingroup group_pyuv + */ +char *PYUV_GetFileExtension(fourcc_t fourcc); + +/*! \brief Gets the name of the color space from the FOURCC code. + * \param [in] fourcc The \ref _fourcc code. + * \return Returns a pointer to a color space name. + * \ingroup group_pyuv + */ +char *PYUV_GetColorSpaceName(fourcc_t fourcc); + +/*! \brief Gets the FOURCC code which co-relates to the name and ext provided. + * \param [in] name The name of the color space. + * \param [in] ext The extension of the file. + * \return Returns the FOURCC code. + * \ingroup group_pyuv + */ +fourcc_t PYUV_GetColorSpace(char *name, char *ext); + +/*! \brief Constructs a filename based on the parameters supplied to the + * function which allows the pYUV player to load the RAW file appropriately. + * \param [out] filename The final filename. + * \param [in] path The path to place the file in. + * \param [in] name The short name of the file. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] fps The frame rate of the RAW sequence. + * \param [in] fourcc The FOURCC format of the data. + * \ingroup group_pyuv + */ +void PYUV_GetFilename(char *filename, + char *path, + char *name, + unsigned int width, + unsigned int height, + unsigned int fps, + fourcc_t fourcc); +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/sosal/queue.h b/include/sosal/queue.h new file mode 100644 index 0000000..308f4e2 --- /dev/null +++ b/include/sosal/queue.h @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_QUEUE_H_ +#define _SOSAL_QUEUE_H_ + +/*! \file + * \brief The SOSAL Queues API. + * \author Erik Rainey + */ + +#include +#include +#include +#include + +/*! \brief The queue data structure + * \see queue_create + * A queue is a ring buffer with \ref mutex_t protection and two + * \ref event_t to indicate read and write access. + * \ingroup group_queues + */ +typedef struct _queue_t { + bool_e active; + bool_e popped; + ring_t *ringb; + size_t msgSize; + size_t numMsgs; + size_t msgCount; + mutex_t access; + event_t readEvent; + event_t writeEvent; +} queue_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief Creates a queue with a default number of message of a set size. Once + * created, this can not be changed. + * \returns queue_t * + * \retval NULL Could not create the queue. + * \param [in] numMsgs The number of messages to hold in the ring buffer. + * \param [in] msgSize The size in bytes of the message. + * \ingroup group_queues + */ +queue_t *queue_create(size_t numMsgs, size_t msgSize); + +/*! \brief Destroys a queue. + * \note The queue will be popped, which removes all listeners, then + * deleted, which will destroy all message in the queue. + * \param q The queue to destroy. + * \ingroup group_queues + */ +void queue_destroy(queue_t *q); + +/*! \brief Allows the client to write data unto the queue. If blocking is enabled + * the function will block until space is available in the queue. + * \param q The queue to used. + * \param blocking If true, blocking could occur if no space is available. + * \param datum A pointer to a message to write into the ring buffer. + * \returns bool_e + * \retval true_e If data was successfully written. + * \retval false_e If any error occurred. + * \ingroup group_queues + */ +bool_e queue_write(queue_t *q, bool_e blocking, void *datum); + +/*! \brief Allows a client to read data out of the queue. If blocking is enabled + * the function will block until data is available to be read. + * \param q The queue to used. + * \param blocking If true, blocking could occur if no space is available. + * \param datum A pointer to a location to write the message in the ring buffer to. + * \returns bool_e + * \retval true_e If data was successfully read. + * \retval false_e If any error occurred (When not blocking it could indicate + * that no data is ready). + * \ingroup group_queues + */ +bool_e queue_read(queue_t *q, bool_e blocking, void *datum); + +/*! \brief Enables read and write events on the queue. Waiting listeners may + * get events depending on the data state of the queue. + * \param q The queue to affect. + * \ingroup group_queues + */ +void queue_enable(queue_t *q); + +/*! \brief Disables read and write events on the queue. No listeners will be + * signalled after this is called. You must re-enable later to get events + * again. + * \see queue_enable + * \param q The queue to affect. + * \ingroup group_queues + */ +void queue_disable(queue_t *q); + +/*! \brief Forcibly sets the read and write events but causes \ref false_e to be + * returned from read or write functions. This removes listeners and + * preserves the data in the queue. + * \param q The queue to affect. + * \ingroup group_queues + */ +void queue_pop(queue_t *q); + +/*! \brief Returns the queue to a normal state from \ref queue_pop. Listeners + * will get appropriate events after this call. This call may cause some + * listeners to signal. + * \param q The queue to affect. + * \ingroup group_queues + */ +void queue_unpop(queue_t *q); + +/*! \brief Returns the number of used slots in the ring buffer. + * \returns size_t The number of units in the ring buffer. + * \param q The queue to query. + * \ingroup group_queues + */ +size_t queue_length(queue_t *q); + +/*! \brief Reallocates the internal ring buffer and resets the \ref event_t for + * read and write access. + * \param q The queue to affect. + * \ingroup group_queues + */ +queue_t *queue_reset(queue_t *q); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/sosal/ring.h b/include/sosal/ring.h new file mode 100644 index 0000000..85baae8 --- /dev/null +++ b/include/sosal/ring.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_RING_H_ +#define _SOSAL_RING_H_ + +/*! \file + * \brief The SOSAL Ring Buffer API. + * \author Erik Rainey + */ + +#include + +/*! \brief The ring buffer data structure. + * \ingroup group_rings + */ +typedef struct _ring_t{ + size_t totalNumBytes; /*!< Total number of bytes in a ring buffer. */ + size_t numBytesUsed; /*!< The number of bytes filled with data */ + size_t numBytesFree; /*!< The number of empty bytes */ + uint8_t *start; /*!< alwars points to the first item in the linear array */ + uint8_t *end; /*!< always points to the last item in the linear array */ + uint8_t *front; /*!< always points to the first item in the ring */ + uint8_t *back; /*!< always points to the last item in the ring */ +} ring_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize a ring buffer + * This function allocates a ring buffer and it's control structure as well + * as initializing it's control structure's member variables. + * \param [in] totalSize This describes the total number of bytes to allocate + * for the ring buffer. + * \return Returns a pointer to the control structure on success or NULL + * on failure. + * \post \ref ring_destroy + * \ingroup group_rings + */ +ring_t *ring_create(size_t totalSize); + +/** + * \brief This function destroy's the ring buffer and it's control structure. + * \param [out] rb The pointer to the ring buffer's control structure. + * \pre \ref ring_create + * \ingroup group_rings + */ +void ring_destroy(ring_t *rb); + +/** + * \brief Write len bytes of data to a ring buffer rb + * + * \param [in,out] rb the ring buffer to write data to. + * \param [in] b pointer to the data to be written. + * \param [in] len The desired length to write. + * \return Returns the number of bytes written to the ring buffer. If zero, + * no bytes were written. + * \pre \ref ring_create + * \ingroup group_rings + */ +size_t ring_write(ring_t *rb, uint8_t *b, size_t len); + +/** + * \brief Read len bytes of data from a ring buffer rb + * \param [in,out] rb the ring buffer to read data from. + * \param [out] b pointer to the output data buffer. + * \param [in] len The desired length read, can be considered the max len read + * \return Returns the number of bytes read from the ring buffer. If zero, + * no bytes were read. + * \pre \ref ring_create + * \ingroup group_rings + */ +size_t ring_read(ring_t *rb, uint8_t *b, size_t len); + +/** + * This function prints the values of the control structure as well as the + * values of the ring buffer as well. Do not use on large buffers! + * \param [in] rb The pointer to the control structure of the ring buffer + * \pre \ref ring_create + * \ingroup group_rings + */ +void ring_print(ring_t *rb); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/sosal/rpc_socket.h b/include/sosal/rpc_socket.h new file mode 100644 index 0000000..fa04c39 --- /dev/null +++ b/include/sosal/rpc_socket.h @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _RPC_SOCKET_H_ +#define _RPC_SOCKET_H_ + +/*! \file + * \brief The SOSAL Remote Procedure Call API over Sockets. + * \author Erik Rainey + */ + +#include +#include +#include + +#define SOSAL_RPC_SOCKET_API + +#if defined(SYSBIOS) +#undef SOSAL_RPC_SOCKET_API +#endif + +#if defined(SOSAL_RPC_SOCKET_API) + +/*! \brief + * \ingroup group_rpc_sockets + */ +typedef struct _rpc_socket_item_t { + uint32_t length; + uint32_t type; /**< @see rpc_socket_item_type_e */ + uint32_t sizeElement; + uint32_t numElements; + void *item; // this element is not in the actual packet data +} rpc_socket_item_t; + +/*! \brief + * \ingroup group_rpc_sockets + */ +#define RPC_SOCKET_ITEM_HEADER_SIZE (sizeof(rpc_socket_item_t)-sizeof(void *)) + +/*! \brief + * \ingroup group_rpc_sockets + */ +typedef struct _rpc_client_t { + uint32_t ipaddr; + uint16_t port; + socket_t *server; +} rpc_client_t; + +/*! \brief + * \ingroup group_rpc_sockets + */ +typedef bool_e (*rpc_server_function_f)(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns); + +/*! \brief + * \ingroup group_rpc_sockets + */ +typedef struct _rpc_server_t { + socket_t *server; + thread_t handle; + uint16_t port; + void *arg; + rpc_server_function_f *functions; + uint32_t numFunctions; + bool_e running; +} rpc_server_t; + +/*! \brief + * \ingroup group_rpc_sockets + */ +typedef struct _rpc_socket_header_t { + uint32_t length; + uint32_t function; + uint32_t direction; + uint32_t numItems; +} rpc_socket_header_t; + +/*! \brief + * \ingroup group_rpc_sockets + */ +typedef enum _rpc_socket_direction_e { + RPC_SOCKET_CALLING, + RPC_SOCKET_RETURN +} rpc_socket_direction_e; + +/*! \brief + * \ingroup group_rpc_sockets + */ +typedef enum _rpc_socket_item_type_e { + RPC_SOCKET_TYPE_INT8, + RPC_SOCKET_TYPE_UINT8, + RPC_SOCKET_TYPE_INT16, + RPC_SOCKET_TYPE_UINT16, + RPC_SOCKET_TYPE_INT32, + RPC_SOCKET_TYPE_UINT32, + RPC_SOCKET_TYPE_INT64, + RPC_SOCKET_TYPE_UINT64, + RPC_SOCKET_TYPE_STRING +} rpc_socket_item_type_e; + +/*! \brief Indicates the maximum number of items in a packet + * \ingroup group_rpc_sockets + */ +#define RPC_SOCKET_MAX_ARGS (10) + +/*! \brief Indicates the maximum size of an item's data + * \ingroup group_rpc_sockets + */ +#define RPC_SOCKET_MAX_DATA (128) + +/*! \brief The maximum size of an RPC packet. + * \note Large data should not be sent over RPC command packets. It should be + * arranged over a secondary connection. + * \ingroup group_rpc_sockets + */ +#define RPC_SOCKET_MAX_PACKET (sizeof(rpc_socket_header_t) + (RPC_SOCKET_MAX_ARGS * (RPC_SOCKET_ITEM_HEADER_SIZE + RPC_SOCKET_MAX_DATA))) + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief This initializes a server thread with a preset set of + * functions. The thread is not started until \ref rpc_socket_server_start is + * called. + * \param [in] hostname The hostname of the server. + * \param [in] port The port to serve the server on. + * \param [in] arg The user private data. + * \param [in] functions The list of functions serve. + * \param [in] numFunctions The number of functions in the list. + * \return Returns the handle to the RPC server. + * \retval NULL Indicates that the server did not start. + * \post \ref rpc_socket_server_deinit + * \ingroup group_rpc_sockets + */ +rpc_server_t *rpc_socket_server_init(char *hostname, uint16_t port, void *arg, + rpc_server_function_f *functions, + uint32_t numFunctions); + +/*! \brief This deinitializes a server thread. + * \param [in] server The server to deinitialize. + * \pre \ref rpc_socket_server_init + * \ingroup group_rpc_sockets + */ +void rpc_socket_server_deinit(rpc_server_t *server); + +/*! \brief This starts the server thread running. + * \param [in] server The server to start. + * \return Returns a bool_e. + * \retval true_e Indicates that the server started, false_e otherwise. + * \pre \ref rpc_socket_server_init + * \post \ref rpc_socket_server_stop + * \ingroup group_rpc_sockets + */ +bool_e rpc_socket_server_start(rpc_server_t *server); + +/*! \brief This stops the server thread. + * \param [in] server The server to stop. + * \pre \ref rpc_socket_server_start + * \post \ref rpc_socket_server_deinit + * \ingroup group_rpc_sockets + */ +void rpc_socket_server_stop(rpc_server_t *server); + +/*! \brief This connects a client to an RPC server. + * \param [in] hostname The name of the server. + * \param [in] port The port number of the server. + * \return Returns the client structure. + * \retval NULL if the client could not connect. + * \post \ref rpc_socket_client_call + * \ingroup group_rpc_sockets + * \note + */ +rpc_client_t *rpc_socket_client_start(char *hostname, uint16_t port); + +/*! \brief This calls a remote procedure call on the server. + * \param [in] client The handle to the client context. + * \param [in] function The index of the function to call. + * \param [in] items The list of parameters to the function. + * \param [in] numItems The number of items in the list of items. + * \param [in] rets The list of return values from the function. + * \param [in] numRets The number of items in the return list of items. + * \return Returns bool_e. + * \retval true_e if the function was called. + * \retval fasle_e an error occurred. + * \pre \ref rpc_socket_client_start + * \ingroup group_rpc_sockets + * \note Remember, you are making an RPC over the network. You can not pass + * logically pass memory pointers! + */ +bool_e rpc_socket_client_call(rpc_client_t *client, uint32_t function, + rpc_socket_item_t *items, uint32_t numItems, + rpc_socket_item_t *rets, uint32_t numRets); + +/*! \brief This stops the client. + * \param [in] client The client to stop. + * \pre \ref rpc_socket_client_start + * \ingroup group_rpc_sockets + */ +void rpc_socket_client_stop(rpc_client_t *client); + +/*! \brief Determines the length needed in the packed for this item. + * \param [in] items The item to compute length on. + * \ingroup group_rpc_sockets + */ +void rpc_socket_item_length(rpc_socket_item_t *item); + +#ifdef __cplusplus +} +#endif + +#endif // SOSAL_RPC_SOCKET_API + +#endif + diff --git a/include/sosal/rtimer.h b/include/sosal/rtimer.h new file mode 100644 index 0000000..b113f49 --- /dev/null +++ b/include/sosal/rtimer.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_RTIMER_H_ +#define _SOSAL_RTIMER_H_ + +/*! \file + * \brief The SOSAL High Resolution Timer API. + * \author Erik Rainey + */ + +#include + +#if defined(ANDROID) || defined(LINUX) || defined(__QNX__) || defined(CYGWIN) || defined(DARWIN) +#define POSIX_TIMER +#undef WIN32_TIMER +#undef BIOS_TIMER +#elif defined(WIN32) +#undef POSIX_TIMER +#define WIN32_TIMER +#undef BIOS_TIMER +#elif defined(SYSBIOS) +#undef POSIX_TIMER +#undef WIN32_TIMER +#define BIOS_TIMER +#endif + +#if defined(POSIX_TIMER) +/*! On POSIX environments, 64 bit is needed. + * \ingroup group_rtimers + */ +typedef uint64_t rtime_t; +#define MAX_RTIMER_T ((rtime_t)0xFFFFFFFFFFFFFFFFULL) +#define FMT_RTIMER_T FMT_UINT64_T +#endif + +#if defined(WIN32_TIMER) +/*! On WIN32 environments, 64 bit is needed. + * \ingroup group_rtimers + */ +typedef LONGLONG rtime_t; +#define MAX_RTIMER_T 0xFFFFFFFFFFFFFFFF +#define FMT_RTIMER_T "%I64d" +#endif + +#if defined(BIOS_TIMER) +/*! On SYSBIOS environments, 64 bit is needed. + * \ingroup group_rtimers + */ +typedef unsigned long long rtime_t; +#define MAX_RTIMER_T ((rtime_t)0xFFFFFFFFFFFFFFFFULL) +#define FMT_RTIMER_T FMT_UINT64_T +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief Gets the current time. + * \return Returns the current time. + * \ingroup group_rtimers + */ +rtime_t rtimer_now(); + +/*! \brief Gets the frequency of the timer. + * \return returns the frequency of the timer. + * \ingroup group_rtimers + */ +rtime_t rtimer_freq(); + +/*! \brief Converts the rtime_t to microseconds. + * \param [in] t The rtime_t to convert. + * \return Returns an rtime_t scaled into microseconds. + * \ingroup group_rtimers + */ +rtime_t rtimer_to_us(rtime_t t); + +/*! \brief Converts the rtimer_t from an externally supplied rate + * into microseconds. + * \param [in] t The time to convert. + * \param [in] rate The external rate. + * \return Returns an rtime_t which is converted. + * \ingroup group_rtimers + */ +rtime_t rtimer_from_rate_to_us(rtime_t t, rtime_t rate); + +/*! \brief Converts the rtime_t to seconds. + * \param [in] t The rtime_t to convert. + * \return Returns an rtime_t converted into seconds in a double. + * \ingroup group_rtimers + */ +double rtimer_to_sec(rtime_t); + +/*! \brief Converts the rtimer_t from an externally supplied rate + * into seconds. + * \param [in] t The time to convert. + * \param [in] rate The external rate. + * \return Returns an rtime_t which is converted into a double in seconds. + * \ingroup group_rtimers + */ +double rtimer_from_rate_to_sec(rtime_t, rtime_t rate); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/sosal/semaphore.h b/include/sosal/semaphore.h new file mode 100644 index 0000000..b788fda --- /dev/null +++ b/include/sosal/semaphore.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_SEMAPHORE_H_ +#define _SOSAL_SEMAPHORE_H_ + +/*! \file + * \brief The SOSAL Semaphore API. + * \author Erik Rainey + */ + +#include + +#if defined(POSIX) + +/*! \brief On POSIX systems this wraps sem_t. + * \ingroup group_semaphores + */ +typedef sem_t semaphore_t; + +#elif defined(SYSBIOS) + +#include +#include +/*! \brief On BIOS systems this wraps Semaphore_Handle. + * \ingroup group_semaphores + */ +typedef Semaphore_Handle semaphore_t; + +#elif defined(WIN32) + +/*! \brief On Windows systems this wraps a HANDLE. + * \ingroup group_semaphores + */ +typedef HANDLE semaphore_t; + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief This function creates a semaphore. + * \param [in] s The pointer to a structure to store the semaphore. + * \param [in] count The initial count to give the semaphore + * \param [in] shared Indicates if the semaphore is to be shared across processes. + * \return Returns a bool_e. + * \retval true_e Indicates that the semaphore was created. + * \retval false_e indicates that the semaphore was not created. + * \post \ref semaphore_delete + * \ingroup group_semaphores + */ +bool_e semaphore_create(semaphore_t *s, uint32_t count, bool_e shared); + +/*! \brief This function deletes a created semaphore. + * \param [in] s The storage location of the semaphore. + * \return Returns a bool_e. + * \retval true_e The semaphore was destroyed. + * \retval false_e The semaphore was not destroyed. + * \pre \ref semaphore_create + * \post Free the pointer if allocated, if an automatic, do nothing. + * \ingroup group_semaphores + */ +bool_e semaphore_delete(semaphore_t *s); + +/*! \brief This function decreases the current count. This is used by + * threads or processes after a protected operation is done. + * \param [in] s The pointer to the semaphore structure. + * \return Returns a bool_e. + * \retval true_e if posted. + * \retavl false_e if an error occurred. + * \pre \ref semaphore_wait + * \ingroup group_semaphores + */ +bool_e semaphore_post(semaphore_t *s); + +/*! \brief This function blocks until the current count of the semaphore is the + * desired count. If the current count is less than or equal to desired count + * then enters the semaphore increasing it's count. + * \param [in] s The pointer to the semaphore structure. + * \return Returns a bool_e. + * \retval true_e The semaphore was acquired. + * \retval false_e The semaphore was not acquired. + * \pre \ref semaphore_create + * \ingroup group_semaphores + */ +bool_e semaphore_wait(semaphore_t *s); + +/*! \brief This function tries to grab the semaphore. If + * the current count is not the count, the function returns and does not block. + * If the current count is less than or equal to the desired count then the + * semaphore is acquired. + * \param [in] s The pointer to the semaphore structure. + * \return Returns a bool_e. + * \retval true_e The semaphore was acquired. + * \retval false_e The semaphore was not acquired. + * \pre \ref semaphore_create + * \ingroup group_semaphores + */ +int semaphore_trywait(semaphore_t *s); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/sosal/serial.h b/include/sosal/serial.h new file mode 100644 index 0000000..9ad8bc1 --- /dev/null +++ b/include/sosal/serial.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_SERIAL_H_ +#define _SOSAL_SERIAL_H_ + +/*! \file + * \brief The SOSAL Serial API. + * \author Erik Rainey + */ + +#include + +#if defined(ANDROID) || defined(LINUX) || defined(DARWIN) || defined(__QNX__) +#define POSIX_SERIAL +#define SOSAL_SERIAL_API +#elif defined(CYGWIN) || defined(WIN32) +#include +#undef POSIX_SERIAL +#define SOSAL_SERIAL_API +#elif defined(SYSBIOS) +#undef POSIX_SERIAL +#undef SOSAL_SERIAL_API +#endif + +#ifdef POSIX_SERIAL +/*! \brief On POSIX systems this wraps a FILE pointer. + * \ingroup group_serial + */ +typedef FILE* serial_t; +#elif defined(WIN32) +/*! \brief On Windows systems this wraps a HANDLE. + * \ingroup group_serial + */ +typedef HANDLE serial_t; +#endif + +#if defined(SOSAL_SERIAL_API) + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief This function opens a serial port. + * \param [in] number The port number. + * \return Returns the handle to the serial port. + * \retval 0 if the port could not be opened. + * \post \ref serial_close + * \ingroup group_serial + */ +serial_t serial_open(uint32_t number); + +/*! \brief This function closes a serial port. + * \param [in] ser The serial port handle. + * \pre \ref serial_open + * \ingroup group_serial + */ +void serial_close(serial_t ser); + +/*! \brief This function reads data from a serial port. + * \param [in] ser The serial port handle. + * \param [in] buffer The buffer to read the data into. + * \param [in] numBytes The number of bytes to read into buffer. + * \return Returns the number of bytes read from the serial port. + * \retval 0 No data was read. + * \pre \ref serial_open + * \post \ref serial_close + * \ingroup group_serial + */ +size_t serial_read(serial_t ser, uint8_t *buffer, size_t numBytes); + +/*! \brief This function writes data to a serial port. + * \param [in] ser The serial port handle. + * \param [in] buffer The buffer to write the data from. + * \param [in] numBytes The number of bytes to write from buffer. + * \return Returns the number of bytes written to the serial port. + * \retval 0 No data was written. + * \pre \ref serial_open + * \post \ref serial_close + * \ingroup group_serial + */ +size_t serial_write(serial_t ser, uint8_t *buffer, size_t numBytes); + +#ifdef __cplusplus +} +#endif + +#endif // SOSAL_SERIAL_API + +#endif // FILE lock + diff --git a/include/sosal/shared.h b/include/sosal/shared.h new file mode 100644 index 0000000..25a6953 --- /dev/null +++ b/include/sosal/shared.h @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_SHARED_H_ +#define _SOSAL_SHARED_H_ + +/*! \file + * \brief The SOSAL Shared Memory API. + * \author Erik Rainey + */ +#include + +#if defined(ANDROID) && (defined(FROYO) || defined(GINGERBREAD) || defined(ICS)) +#undef SHM_SYSVIPC +#undef SHM_QNX +#define SHM_ASHMEM +// Use Asynchronous Shared Memory +#include +#include +#include +#include +#include +#elif defined(ANDROID) // NDK +#undef SHM_SYSVIPC +#undef SHM_QNX +#define SHM_ASHMEM +#include +#elif defined(LINUX) || defined(DARWIN) +#undef SHM_ASHMEM +#undef SHM_QNX +#define SHM_SYSVIPC +// Use SYS V Shared Memory API +#include +#include +#elif defined(__QNX__) +#undef SHM_ASHMEM +#undef SHM_SYSVIPC +#define SHM_QNX +#include +#include +#elif defined(WIN32) || defined(CYGWIN) +#undef SHM_ASHMEM +#undef SHM_QNX +#undef SHM_SYSVIPC +// Use Shared Memory File API +#include +#endif + +/*! \brief The method to identify each shared memory block from each other. + * \ingroup group_shared + */ +typedef int32_t unique_t; + +/*! \brief The structure which maintains the information about the memory sharing. + * \ingroup group_shared + */ +typedef struct _shared_t { + unique_t un; /*!< \brief The unique identifier of this block */ + size_t size; /*!< \brief The size of the block in bytes. */ + void *data; /*!< \brief The pointer to the data buffer */ +#ifdef SHM_SYSVIPC + int shmid; /*!< \brief The shared memory identifier */ + int shmflags; /*!< \brief The shared memory flags */ + key_t key; /*!< \brief The key used to access the shared memory */ +#endif +#if defined(SHM_ASHMEM) || defined(SHM_QNX) + int fd; /*!< \brief The file descriptor used to share the memory */ + void *reserved; +#endif +#if defined(WIN32) || defined(CYGWIN) + HANDLE mapfile; /*!< \brief The file handle to the MAPPED memory */ + TCHAR name[MAX_PATH]; /*!< \brief The name of the shared data */ +#endif +} shared_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief This function allocates shared memory. If the unique identifier + * already exists, the memory is mapped into your memory space. + * \param [in] un The unique identifier. + * \param [in] size The bytes size of the memory aread needed. + * \return Returns the shared_t memory handle. + * \retval NULL if the shared memory failed to allocate. + * \post \ref shared_free + * \ingroup group_shared + */ +shared_t *shared_alloc(unique_t un, size_t size); + +/*! \brief This function frees shared memory. If there are multiple clients + * still open after this free is called, the memory will not be actually freed. + * \param [in] pshm The pointer to the shared memory handle. + * \pre \ref shared_alloc + * \ingroup group_shared + */ +void shared_free(shared_t **pshm); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/sosal/socket.h b/include/sosal/socket.h new file mode 100644 index 0000000..2a344ff --- /dev/null +++ b/include/sosal/socket.h @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_SOCKET_H_ +#define _SOSAL_SOCKET_H_ + +/*! \file + * \brief The SOSAL Socket API. + * \author Erik Rainey + */ + +#include + +/*! \brief This creates 32 address on little endian machines. + * \ingroup group_sockets + */ +#define IP4_ADDR(a,b,c,d) ((d << 0) | (c << 8) | (b << 16) | (a << 24)) + +#define SOSAL_SOCKET_API + +#if defined(ANDROID) || defined(LINUX) || defined(DARWIN) || defined(__QNX__) || defined(CYGWIN) +#define POSIX_SOCKETS +#undef WIN32_SOCKETS +#include +#include +#include +#include +#include +#include +#include +#include +#define SOCKET_IP_ANY INADDR_ANY +#elif defined(WIN32) +#include +#include +#undef POSIX_SOCKETS +#define WIN32_SOCKETS +#define SOCKET_IP_ANY 0 +#if defined(WIN32) && !defined(CYGWIN) +typedef SSIZE_T ssize_t; +#endif +#elif defined(SYSBIOS) +#undef POSIX_SOCKETS +#undef WIN32_SOCKETS +#undef SOSAL_SOCKET_API +#endif + +/*! \brief This serializes the unit into the serializing buffer if the buffer has room. + * \param [in,out] buffer The serialized buffer. + * \param [in] offset The offset in the buffer to start + * \param [in] len the length of the buffer. + * \param [in] unit The unit to write into the serialized buffer. + * \ingroup group_sockets + */ +#define SERIALIZE_UNIT(buffer, offset, len, unit) { \ + if ((offset + sizeof(unit)) < len) { \ + memcpy(&buffer[offset], &unit, sizeof(unit)); \ + offset += sizeof(unit); \ + } \ +} + +/*! \brief This unserializes the unit from the serializing buffer to the unit. + * \param [in] buffer The serialized buffer. + * \param [in] offset The offset in the buffer to start + * \param [in] len the length of the buffer. + * \param [in] unit The unit to read from the serialized buffer. + * \ingroup group_sockets + */ +#define UNSERIALIZE_UNIT(buffer, offset, len, unit) { \ + if ((offset + sizeof(unit)) < len) { \ + memcpy(&unit, &buffer[offset], sizeof(unit)); \ + offset += sizeof(unit); \ + } \ +} + +/*! \brief This serializes the pointer into the serializing buffer if the buffer has room. + * \param [in,out] buffer The serialized buffer. + * \param [in] offset The offset in the buffer to start + * \param [in] len the length of the buffer. + * \param [in] ptr The pointer to serialize from into the buffer. + * \param [in] ptrlen The length of the ptr to serialize. + * \ingroup group_sockets + */ +#define SERIALIZE_ARRAY(buffer, offset, len, ptr, ptrlen) { \ + if ((offset + ptrlen) < len) { \ + memcpy(&buffer[offset], ptr, ptrlen); \ + offset += ptrlen; \ + } \ +} + +/*! \brief This unserializes the pointer from the serializing buffer. + * \param [in] buffer The serialized buffer. + * \param [in] offset The offset in the buffer to start + * \param [in] len the length of the buffer. + * \param [in] ptr The pointer to unserialize from the buffer. + * \param [in] ptrlen The length of the ptr to unserialize. + * \ingroup group_sockets + */ +#define UNSERIALIZE_ARRAY(buffer, offset, len, ptr, ptrlen) { \ + if ((offset + ptrlen) < len) { \ + memcpy(ptr, &buffer[offset], ptrlen); \ + offset += ptrlen; \ + } \ +} + +/*! \brief The definition of a local address. + * \ingroup group_sockets + */ +#define SOCKET_IP_LOCAL IP4_ADDR(127,0,0,1) + +#if defined(SOSAL_SOCKET_API) + +/*! \brief The socket structure which maintains the HLOS specific information. + * \ingroup group_sockets + */ +typedef struct _socket_t { + bool_e is_server; /*!< \brief The socket is a server endpoint */ +#if defined(POSIX_SOCKETS) + int sock; /*!< \brief The socket handle */ + int connected; /*!< \brief The connected socket handle. */ + struct sockaddr_in server_address; /*!< \brief The server address used to run the server connection. */ + struct sockaddr_in client_address; /*!< \brief The client address used to connect to the server. */ + socklen_t sin_size; /*!< \brief The socket input size */ +#elif defined(WIN32_SOCKETS) + SOCKET sock; /*!< \brief The socket handle */ + SOCKET connected; /*!< \brief The connected socket handle */ + struct sockaddr_in server_address; /*!< \brief The server address used to run the server connection */ + struct sockaddr_in client_address; /*!< \brief The client address used to connect to the server. */ + int sin_size; /*!< \brief The socket input size */ +#endif + ssize_t bytesRecv; /*!< \brief The number of bytes received on the socket */ + ssize_t bytesSend; /*!< \brief The number of bytes sent on the socket. */ +} socket_t; + +/*! \brief The type of socket connection. + * \ingroup group_sockets + */ +typedef enum _socket_type_e { + SOCKET_TCP, /*!< \brief Makes a TCP/IP connection */ + SOCKET_UDP, /*!< \brief Makes a UDP/IP connection */ +} socket_type_e; + + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief Converts the string hostname to an ipaddress stored in the return value. + * \param [in] string The string of the hostname to convert. + * \return Return the IP address in a uint32_t. + * \ingroup group_sockets + */ +uint32_t socket_hostname(char *string); + +/*! \brief Creates the server socket, binds and listens to the port, but does not yet accept connections. + * \param [in] ipaddr The IP address. + * \param [in] port The IP port. + * \param [in] type The type of connection requested. + * \param [in] isServer Indicates that this socket will be a server style connection if true_e. + * \post \ref socket_connect + * \ingroup group_sockets + */ +socket_t *socket_init(uint32_t ipaddr, uint16_t port, socket_type_e type, bool_e isServer); + +/*! \brief A blocking call waiting for a server/client connection. + * \param [in] socket The socket handle. + * \retval true_e Returned when the connection is complete. + * \retval false_e Returned when the connection failed. + * \pre \ref socket_init + * \ingroup group_sockets + */ +bool_e socket_connect(socket_t *socket); + +/*! \brief This sends data over a connected socket. + * \param [in] socket The socket handle. + * \param [in] data The data to send over the socket. + * \param [in] len The length of data to send from data. + * \retval true_e The data was sent correctly. + * \retval false_e The data was not sent correctly. + * \pre \ref socket_connect + * \post \ref socket_disconnect + * \ingroup group_sockets + */ +bool_e socket_send(socket_t *socket, uint8_t *data, size_t len); + +/*! \brief This receives data over the socket. + * \param [in] socket The socket handle. + * \param [in] data The data to received over the socket. + * \param [in] len The length of data to receive over the socket. + * \retval true_e The data was received correctly. + * \retval false_e The data was not received correctly. If the connection + * was lost this will be returned. + * \pre \ref socket_connect + * \ingroup group_sockets + */ +bool_e socket_recv(socket_t *socket, uint8_t *data, size_t len); + +/*! \brief This disconnects a socket from the remote side. + * \param [in] socket The socket handle. + * \pre \ref socket_connect + * \ingroup group_sockets + */ +void socket_disconnect(socket_t *socket); + +/*! \brief This prints information about a socket. + * \param [in] socket The socket handle. + * \ingroup group_sockets + */ +void socket_info(socket_t *socket); + +/*! \brief This deinitializes the socket. + * \param [in] socket The socket handle. + * \pre \ref socket_init + * \ingroup group_sockets + */ +void socket_deinit(socket_t *socket); + +#ifdef __cplusplus +} +#endif + +#endif // SOSAL_SOCKET_API + +#endif + diff --git a/include/sosal/sosal.h b/include/sosal/sosal.h new file mode 100644 index 0000000..f6116a2 --- /dev/null +++ b/include/sosal/sosal.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_H_ +#define _SOSAL_H_ + +/*! + * \file + * \brief The top level Simple Operating System Abstraction Layer header. + * \author Erik Rainey + * \defgroup group_threadpools SOSAL Threadpool + * \defgroup group_rtimers SOSAL RTimer + * \defgroup group_image_t SOSAL Image + * \defgroup group_threads SOSAL Thread + * \defgroup group_modules SOSAL Module + * \defgroup group_mutexes SOSAL Mutex + * \defgroup group_serial SOSAL Serial Ports + * \defgroup group_events SOSAL Events + * \defgroup group_semaphores SOSAL Semaphore + * \defgroup group_uinput SOSAL User Input + * \defgroup group_lists SOSAL List + * \defgroup group_rings SOSAL Ring + * \defgroup group_queues SOSAL Queue + * \defgroup group_hashes SOSAL Hash + * \defgroup group_options SOSAL Command-line Options + * \defgroup group_cache SOSAL Cache + * \defgroup group_vectors SOSAL Vector + * \defgroup group_bitfields SOSAL Bitfield + * \defgroup group_fph SOSAL Fast Pointer Hash + * \defgroup group_ini SOSAL INI Parser + * \defgroup group_profilers SOSAL Profiler + * \defgroup group_sockets SOSAL Sockets + * \defgroup group_rpc_sockets SOSAL RPC Sockets + * \defgroup group_shared SOSAL Shared Memory + * \defgroup group_pipes SOSAL Pipe + * \defgroup group_btreelists SOSAL Binary Tree List + * \defgroup group_allocators SOSAL Allocators + * \defgroup group_pyuv SOSAL PYUV + * \defgroup group_sosal_debug SOSAL Debugging + * \defgroup group_fourcc SOSAL FOURCC Codes + * \defgroup group_unittest SOSAL Unit Tests + * \defgroup group_histograms SOSAL Histogram + * \defgroup group_heaps SOSAL Heaps + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(ANDROID) +#include +#endif + +#ifdef SOSAL_UNITTEST +#include +#endif + +#endif // _SOSAL_H_ diff --git a/include/sosal/status.h b/include/sosal/status.h new file mode 100644 index 0000000..e58c3ad --- /dev/null +++ b/include/sosal/status.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_STATUS_H_ +#define _SOSAL_STATUS_H_ + +/*! \file + * \brief + * \author Erik Rainey + */ + +/*! \brief The error code type for SOSAL. + * \ingroup group_status + */ +typedef enum _sosal_error_e { + STATUS_BASE = -600, + STATUS_NO_MAPPING = STATUS_BASE+1, /**< Failed to map memory */ + STATUS_NOT_ENOUGH_MEMORY = STATUS_BASE+2, /**< Returned when there is not sufficient memory to run */ + STATUS_INVALID_PARAMETER = STATUS_BASE+3, /**< One of the supplied parameters is invalid */ + STATUS_INVALID_STATE = STATUS_BASE+4, /**< The component is in the wrong state to take this action */ + STATUS_NOT_IMPLEMENTED = STATUS_BASE+5, /**< Requested parameter is not implemented */ + STATUS_NO_RESOURCES = STATUS_BASE+6, /**< Not enough resource to complete action, not explicity memory related */ + STATUS_TIMEDOUT = STATUS_BASE+7, /**< A timed event has expired */ + STATUS_CATASTROPHIC = STATUS_BASE+8, /**< Usually a hardware error */ + STATUS_FAILURE = STATUS_BASE+9, /**< Generic failure code */ + STATUS_END_OF_FILE = STATUS_BASE+10,/**< End of file reached while reading */ + STATUS_FILE_NOT_FOUND = STATUS_BASE+11,/**< The system cannot find the file specified */ + STATUS_SUCCESS = 1, /**< Success! */ + } status_e; + + /*! \brief A Co-relation structure for long cores to status_e. + * \ingroup group_status + */ + typedef struct _status_corelation_e { + status_e status; /*!< The \ref status_e code */ + long code; /*!< The system code */ + } status_to_error; + + + /*! \brief Used to check for passing codes */ +#define STATUS_PASSED(x) (x == STATUS_SUCCESS) + /*! \brief Used to check for failing codes */ +#define STATUS_FAILED(x) (x < STATUS_SUCCESS) + +/*! \brief This function converts a status_e code to a platform specific code. + * \ingroup group_status + */ +long status_convert(status_e status); + +#endif + diff --git a/include/sosal/thread.h b/include/sosal/thread.h new file mode 100644 index 0000000..1b76370 --- /dev/null +++ b/include/sosal/thread.h @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_THREAD_H_ +#define _SOSAL_THREAD_H_ + +/*! \file + * \brief The threading interface for SOSAL. + * \author Erik Rainey + */ + +#include + +#ifdef POSIX +/*! \brief In POSIX environments, this is a typedef of the pthread construct. + * \ingroup group_threads + */ +typedef pthread_t thread_t; + +/*! \brief The return type for threads. + * \ingroup group_threads + */ +typedef void * thread_ret_t; +#define THREAD_FMT "%lu" +#define THREAD_RET_FMT "%p" + +#elif defined(SYSBIOS) + +#include +#include +#include +typedef int thread_ret_t; +#define SYSBIOS_DEFAULT_PRIORITY (5) +/* + * The default value of 0 means that the module config defaultStackSize is used. + */ +#define SYSBIOS_DEFAULT_STASK_SIZE (0) //(64 * 1024) +//#define JOIN_SEMAPHORE +#ifndef JOIN_SEMAPHORE +typedef struct _thread_ack_sysbios_t ack_t; +struct _thread_ack_sysbios_t { + event_t* exit_event_ack; /*!< Event used for join notification */ + ack_t* next; +}; +#endif + +typedef thread_ret_t (*thread_f)(void *arg); +struct _thread_sysbios_t { + Task_Handle thread_hdl; /*!< SYSBIOS thread handle */ +#ifdef JOIN_SEMAPHORE + semaphore_t* join_semaphore; /*!< Semapfor used for join control */ + mutex_t* join_mutex; /*!< Mutex used for protection of join_number update */ + uint32_t join_number; /*!< Counter of join users */ +#else + event_t* exit_event; /*!< Event used for thread exit notification */ + ack_t* pAckList; /*!< List of clients waiting for thread join */ +#endif +/* void* stack_ptr; */ /*!< Pointer to stack of SYSBIOS thread */ + void* client_arg; /*!< Client arguments for thread main func */ + thread_f client_func; /*!< Client thread main func */ + uint32_t exit_code; /*!< Client thread main func exit code*/ + bool_e bTaskReady; /*!< Set, when task main func is done */ +}; +typedef struct _thread_sysbios_t* thread_t; + + +#define THREAD_FMT "%lu" +#define THREAD_RET_FMT "%d" + +#elif defined(WIN32) || !defined(CYGWIN) + +/*! \brief In Windows environments, this is a typedef of the Thread HANDLE. + * \ingroup group_threads + */ +typedef HANDLE thread_t; + +/*! \brief The return type for threads. + * \ingroup group_threads + */ +typedef DWORD thread_ret_t; +#define THREAD_FMT "%lu" +#define THREAD_RET_FMT "%d" + +#endif + +#define assign_thread_ret(r, x, typex) r = (thread_ret_t)((typex)(value_t)r + x) + +#ifndef SYSBIOS +/*! \brief The thread function pointer. + * \ingroup group_threads + */ +typedef thread_ret_t (*thread_f)(void *arg); +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Creates a new thread which executes the provided function with the provided argument. + * \ingroup group_threads + */ +thread_t thread_create(thread_f func, void *arg); + +#ifdef POSIX + +/** + * \brief Causes a thread to return. + * \ingroup group_threads + */ +void thread_return(thread_ret_t r); + +/** + * \brief Used to exit from a thread. + * \ingroup group_threads + */ +#define thread_exit(r) thread_return((thread_ret_t)r); return NULL + +#else + +/** + * \brief Used to exit from a thread. + * \ingroup group_threads + */ +#define thread_exit(r) return (r) + +#endif + +/** + * \brief Used to wait for the provided thread to exit. + * \ingroup group_threads + */ +thread_ret_t thread_join(thread_t t); + +/** + * \brief Causes the current thread to sleep for the supplied number of milliseconds. + * \ingroup group_threads + */ +void thread_msleep(int milliseconds); + +/** + * \brief Moves the thread to the next CPU. Used to distribute load over all CPUs in the system as more threads launch. + * \ingroup group_threads + */ +void thread_nextaffinity(); + +bool_e thread_unittest(int argc, char *argv[]); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/sosal/threadpool.h b/include/sosal/threadpool.h new file mode 100644 index 0000000..152bc0c --- /dev/null +++ b/include/sosal/threadpool.h @@ -0,0 +1,125 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_THREADPOOL_H_ +#define _SOSAL_THREADPOOL_H_ + +/*! \file + * \brief Threadpools allow an abstraction around a series of N worker threads attached to + * a queue of work per thread. + * \author Erik Rainey + */ + +#include +#include +#include +#include +#include + +// forward typedef +struct _threadpool_worker_t; + +/*! \brief The function pointer to the worker function. + * \param [in] worker The per-thread worker data structure. + * \retval false_e Indicates that the worker failed to process data or had some other + * error. + * \ingroup group_threadpools + */ +typedef bool_e (*threadpool_f)(struct _threadpool_worker_t *worker); + +/*! \brief The structure given to each threadpool worker during execution. + * \ingroup group_threadpools + */ +typedef struct _threadpool_worker_t { + queue_t *queue; /*!< \brief The work queue */ + thread_t handle; /*!< \brief The handle to the worker thread */ + uint32_t index; /*!< \brief The index of this worker in the pool */ + bool_e active; /*!< \brief Indicates whether this worker is currently operating. */ + threadpool_f function; /*!< \brief The worker function */ + void *arg; /*!< \brief The user argument to the thread */ + void *data; /*!< \brief The user data pointer */ + struct _threadpool_t *pool; /*!< \brief Pointer to the top level structure. */ + profiler_t perf; /*!< \brief Performance capture variable. */ +} threadpool_worker_t; + +/*! \brief The internal structure for tracking a threadpool. + * \ingroup group_threadpools + */ +typedef struct _threadpool_t { + uint32_t numWorkers; /*!< \brief The number of threads in the pool */ + uint32_t numWorkItems; /*!< \brief The maximum number of threads in the queue */ + uint32_t sizeWorkItem; /*!< \brief Unit size of a work item */ + int32_t numCurrentItems; /*!< \brief The number of corrent items in the queue */ + threadpool_worker_t *workers; /*!< \brief The array of workers */ + uint32_t nextWorkerIndex; /*!< \brief The next index to submit work to */ + semaphore_t sem; /*!< \brief The semaphore which protect access to the work queues */ + event_t completed; /*!< \brief The event which indicates that all work is completed */ +} threadpool_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \brief This function destroys a threadpool. It will NOT wait for completion. + * \param [in] pool The pointer to the threadpool_t returned by \ref threadpool_create. + * \pre \ref threadpool_create + * \note The user must set the pointer to NULL after this function. + * \ingroup group_threadpools + */ +void threadpool_destroy(threadpool_t *pool); + +/*! + * \brief This function creates a threadpool for a supplied number of threads. + * \param [in] numThreads How many threads to distribute the work around to. + * \param [in] numWorkItems How deep to make the work queues. + * \param [in] sizeWorkItem How large each work item is. + * \param [in] worker The function which implements the workers. + * \param [in] arg A user supplied global memory pointer for each thread. + * \ingroup group_threadpools + */ +threadpool_t *threadpool_create(uint32_t numThreads, uint32_t numWorkItems, size_t sizeWorkItem, threadpool_f worker, void *arg); + +/*! + * \brief This function issues work to the threapool to be completed. This will return when the + * work has been put into the queues but not necessarily when the work is + * complete. + * \param [in] pool The pointer to the threadpool_t returned by \ref threadpool_create. + * \param [in] workitems An array of work pointers. + * \param [in] numWorkItems A count of the number of work pointers in the workitems array. + * \ingroup group_threadpools + * \pre \ref threadpool_create + * \post \ref threadpool_complete + */ +bool_e threadpool_issue(threadpool_t *pool, void *workitems[], uint32_t numWorkItems); + +/** + * \brief This function will get the status of the threadpool work queues. If set + * to blocking, this will return once all workers have completed. + * \param [in] pool The pointer to the threadpool_t returned by \ref threadpool_create. + * \param [in] blocking Set to true_e for synchronous and false_e for the + * current status (polling mode). + * \ingroup group_threadpools + * \retval true_e Work has completed + * \retval false_e Work has not yet completed. + */ +bool_e threadpool_complete(threadpool_t *pool, bool_e blocking); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/sosal/types.h b/include/sosal/types.h new file mode 100644 index 0000000..d3e5911 --- /dev/null +++ b/include/sosal/types.h @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_TYPES_H_ +#define _SOSAL_TYPES_H_ + +#include +#include +#include +#include +#include // this defines the standard types +#include +#include +#include +#include + +#if defined(WIN32) && !defined(CYGWIN) +#define snprintf _snprintf +#endif + +#if defined(ANDROID) || defined(LINUX) || defined(DARWIN) || defined(__QNX__) || defined(CYGWIN) +#include +#include +#include +#include +#include +#include +#define POSIX +#elif defined(WIN32) +#undef POSIX +#elif defined(SYSBIOS) +#undef POSIX +/*! SYSBIOS lacks a ssize_t definition */ +typedef signed long ssize_t; +#ifndef ARCH_32 +// for SYSBIOS - currently support 32 bit architectures... +#define ARCH_32 +#endif +#else +#error Unsupported HLOS! +#endif + +// DEFINES for using different types in PRINTF +#if defined(WIN32) && !defined(CYGWIN) +#define FMT_SIZE_T "%lu" +#define FMT_SSIZE_T "%ld" +#elif defined(SYSBIOS) +#define FMT_SIZE_T "%lu" +#define FMT_SSIZE_T "%ld" +#elif defined(ANDROID) +#define FMT_SIZE_T "%zu" +#define FMT_SSIZE_T "%ld" +#else +#define FMT_SIZE_T "%zu" +#define FMT_SSIZE_T "%zd" +#endif + +#if defined(ANDROID) || defined(SYSBIOS) +// these platforms only currently support 32 bit architectures... +#ifndef ARCH_32 +#define ARCH_32 +#endif +#endif + +/*! A C boolean work-a-like + * \see true_e + */ +enum _bool_e { + false_e = 0, /*!< FALSE */ +}; + +/*! The boolean type for C */ +typedef enum _bool_e bool_e; + +/*! True is defined as NOT false_e + * \see bool_e + */ +#define true_e (bool_e)(!false_e) + +/*! The basic pointer type on all systems. This grows with the bit depth of the architecture. */ +typedef void *ptr_t; + +/*! The basic interchangable value holder on any system. This grows with the bit depth of the architecture. */ +typedef size_t value_t; + +/*! \brief To be used inline with a printing function for the formating string + * of a value_t. +\code +printf("Value="FMT_VALUE_T"\n", value); +\endcode + */ +#ifdef SYSBIOS +/* + * SYSBIOS supports next conversion specifiers + * d, i, u, x, o, p, c, s, f and l as length modifier + */ +#define FMT_VALUE_T "%lu" +#else +#define FMT_VALUE_T "%zu" +#endif + +#if defined(ARCH_32) +#define FMT_CONST "%u" +#define FMT_INT64_T "%lld" +#define FMT_UINT64_T "%llu" +#define FMT_HEX64_T "%llx" +/** Used to specify in a format string a unsigned 64 bit value of a certain number of digits */ +#define FMT_U64(d) "%"#d"llu" +#elif defined(ARCH_64) +#define FMT_CONST "%lu" +#define FMT_INT64_T "%ld" +#define FMT_UINT64_T "%lu" +#define FMT_HEX64_T "%lx" +/** Used to specify in a format string a unsigned 64 bit value of a certain number of digits */ +#define FMT_U64(d) "%"#d"lu" +#else +#error message("You must define your ARCH_XX size, either 32 or 64 bits.") +#endif + +#ifndef dimof +/*! Returns the number of elements in an array of items */ +#define dimof(x) (sizeof(x)/sizeof(x[0])) +#endif + +#ifndef STRINGERIZE +/*! A wrapper around the stringerizer macro */ +#define STRINGERIZE(x) #x +#endif + +#ifndef MAX_PATH +/*! \brief Maximum file system path value (common across many HLOS, but not maximal on each) */ +#define MAX_PATH (255) +#endif + +#ifndef SOSAL_PAGE_SIZE +#if defined(LINUX) && defined(PAGE_SIZE) +/*! \brief Used to reference the system page size */ +#define SOSAL_PAGE_SIZE PAGE_SIZE +#else +/*! \brief Used to define the system page size if not defined */ +#define SOSAL_PAGE_SIZE (4096) +#endif +#endif + +#if defined(WIN32) +/*! \brief Used to define the compiler trick to cause structure packing */ +#define PACKED_STRUCT(x) +#else +/*! \brief Used to define the compiler trick to cause structure packing */ +#define PACKED_STRUCT(x) __attribute__((aligned(x))) +#endif + +#endif diff --git a/include/sosal/uinput.h b/include/sosal/uinput.h new file mode 100644 index 0000000..b8b66a7 --- /dev/null +++ b/include/sosal/uinput.h @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_UINPUT_H_ +#define _SOSAL_UINPUT_H_ + +/*! \file + * \brief The SOSAL User Input API. + * \author Erik Rainey + */ + +#include + +#define _UINPUT_T_FUNCS +#define _UINPUT_FEATURE + +#if defined(PLAYBOOK) +// Pegasus touch panel is fixed to 1280x768 +#define UINPUT_MAX_TOUCH_X (SCREEN_DIM_X + 200) // 1280 +#define UINPUT_MAX_TOUCH_Y (SCREEN_DIM_Y + 48) // 768 +#elif defined(BLAZE) || defined(SDP) || defined(BLAZE_TABLET) +// These duplicate a Synaptics Touchpad on Blaze +#define UINPUT_MAX_TOUCH_X (SCREEN_DIM_X * 4) // ~3411 on Blaze +#define UINPUT_MAX_TOUCH_Y (SCREEN_DIM_Y * 4) // ~1918 on Blaze +#elif defined(SYSBIOS) +#undef _UINPUT_FEATURE +#undef _UINPUT_T_FUNCS +#else +#ifndef SCREEN_DIM_X +#undef _UINPUT_FEATURE +#undef _UINPUT_T_FUNCS +#endif +#define UINPUT_MAX_TOUCH_X (SCREEN_DIM_X) +#define UINPUT_MAX_TOUCH_Y (SCREEN_DIM_Y) +#endif + +/*! \brief A generic key code. + * \ingroup group_uinput + */ +typedef uint16_t code_t; + +/*! \brief A generic key press state. + * \ingroup group_uinput + */ +typedef enum _input_key_state_e { + INPUT_KEY_STATE_UP = 0, /*!< \brief The key has been let go. */ + INPUT_KEY_STATE_DOWN, /*!< \brief The key has been pressed. */ + INPUT_KEY_STATE_REPEAT /*!< \brief The key is repeating */ +} input_key_state_e; + +/*! \brief A generic key operation. + * \ingroup group_uinput + */ +typedef struct _input_key_t { + code_t code; /*!< \brief The key code */ + input_key_state_e state; /*!< \brief the key state. */ +} input_key_t; + +/*! \brief A generic mouse movement. + * \ingroup group_uinput + */ +typedef struct _input_mouse_t { + int32_t dx; /*!< \brief The change in movement along the x axis */ + int32_t dy; /*!< \brief The change in movement along the y axis */ +} input_mouse_t; + +/*! \brief A generic touchscreen pointer descriptor. + * \ingroup group_uinput + */ +typedef enum _input_ts_type_e { + INPUT_TS_FINGER, /*!< \brief The touch was generated by a finger. */ + INPUT_TS_PEN, /*!< \brief The touch was generated by a pen. */ +} input_ts_type_e; + +/*! \brief A generic touchscreen event. + * \ingroup group_uinput + */ +typedef struct _input_ts_t { + input_ts_type_e type; /*!< \brief The type of stylus */ + uint32_t tracking_id; /*!< \brief The id assigned to each stylus */ + int32_t location_x; /*!< \brief Distances from top left origin in x */ + int32_t location_y; /*!< \brief Distance from top left origin in y */ + uint32_t pressure; /*!< \brief An indication of the pressure used to generate the touch. */ + uint32_t major_width; /*!< \brief The presses major axis width */ + uint32_t minor_width; /*!< \brief The presses minor axis width */ + float orientation; /*!< \brief A value in between [0, 1] which corresponds to [0, 2*pi] */ +} input_ts_t; + +/*! \brief A generic joystick event. + * \ingroup group_uinput + */ +typedef struct _input_joy_t { + uint8_t vx; /*!< \brief Assume [0-255] Range, Fuzz=4, Flat=8 */ + uint8_t vy; /*!< \brief Assume [0-255] Range, Fuzz=4, Flat=8 */ +} input_joy_t; + +/*! \brief An input type list. + * \ingroup group_uinput + */ +typedef enum _input_type_t { + INPUT_TYPE_KEY, /*!< \brief A keyboard input event */ + INPUT_TYPE_MOUSE, /*!< \brief A mouse input event */ + INPUT_TYPE_TOUCH, /*!< \brief A touchscreen event */ + INPUT_TYPE_JOYSTICK, /*!< \brief A joystick event */ + INPUT_TYPE_MAX, +} input_type_e; + +/*! \brief A data structure which describes the input event. + * \ingroup group_uinput + */ +typedef struct _input_t { + input_type_e type; /*!< \brief The \ref input_type_e which indicates how to read the union */ + union { + input_key_t key; /*!< \brief All 2-state keys should be pass here (keybd, mice, joy buttons) */ + input_mouse_t mouse; /*!< \brief All relative mouse movements will be placed in here */ + input_ts_t touch; /*!< \brief All touch events will be placed in here. */ + input_joy_t joy; /*!< \brief All joystick relative movements will be placed here. */ + } data; /*!< \brief The union of all input type data */ +} input_t; + +#ifdef _UINPUT_FEATURE +#if defined(ANDROID) || defined(LINUX) +#include +#include +#include +#include +#include +#include +#include + +/*! \brief The user input device on Linux system wraps /dev/uinput. + * \ingroup group_uinput + */ +typedef struct _uinput_t { + struct uinput_user_dev uud; /*!< \brief the user input user device structure */ + int ufile; /*!< \brief the handle to the /dev/uinput driver */ +} uinput_t; + +#elif defined(WIN32) || defined(CYGWIN) + +#include +/*! \brief The user input device on Windows hooks the Window of the process. + * \ingroup group_uinput + */ +typedef struct _uinput_t { + HWND hWindow; /**< We use the window hook to deliver events */ +} uinput_t; + +#elif defined(DARWIN) +#undef _UINPUT_T_FUNCS // no support yet for input on Mac +#elif defined(__QNX__) +#define _UINPUT_T_FUNCS // skeletal support +#include +#include +#include + +/*! \brief On QNX systems, the user input events are routed through screen. + * \ingroup group_uinput + */ +typedef struct _uinput_t { + screen_context_t context; + screen_display_t display; +} uinput_t; + +#endif +#endif + +#ifdef _UINPUT_T_FUNCS + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief Opens the user input device. + * \param [in] dev_name The name of the device to open. + * \return Returns a handle to the user input device. + * \retval NULL is returned when device could not be opened. + * \post \ref uinput_close + * \ingroup group_uinput + */ +uinput_t *uinput_open(char *dev_name); + +/*! \brief Sends an input event to the user input device. + * \param [in] u The handle to the user input device. + * \param [in] i The input event to send. + * \return Returns a bool_e. + * \retval true_e if the event was sent + * \retval false_e if the event was not sent. + * \pre \ref uinput_open + * \post \ref uinput_close after all events have been sent. + * \ingroup group_uinput + */ +bool_e uinput_send(uinput_t *u, input_t *i); + +/*! \brief Closes the user input device. + * \param [in] u The handle to the user input device. + * \return Returns a bool_e. + * \retval true_e if the device was closed. + * \retval false_e if the device was not closed or an error occurred. + * \pre \ref uinput_open + * \ingroup group_uinput + */ +bool_e uinput_close(uinput_t *u); + +#ifdef __cplusplus +} +#endif + +#endif // _UINPUT_T_FUNCS + +#endif diff --git a/include/sosal/unittest.h b/include/sosal/unittest.h new file mode 100644 index 0000000..96015f9 --- /dev/null +++ b/include/sosal/unittest.h @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_UNITTEST_H_ +#define _SOSAL_UNITTEST_H_ + +/*! + * \file + * \brief The unit test interface for SOSAL. + * \author Erik Rainey + */ + +#include + +/*! \brief A function pointer to a unit test. + * \param [in] argc The number of arguments. + * \param [in] argv The array of arguments. + * \ingroup group_unittest + */ +typedef bool_e (*unittest_f)(int argc, char *argv[]); + +/*! \brief A descriptor of a unit test. + * \ingroup group_unittest + */ +typedef struct _unittest_t { + char name[MAX_PATH]; /*!< Name of the unit test */ + unittest_f test; /*!< Function pointer to the unit test */ + bool_e noArgs; /*!< Indicates whether the unit test requires arguments. */ +} unittest_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e allocator_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e cache_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e event_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e thread_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e queue_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e hash_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e option_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e heap_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e list_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e histogram_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e ini_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e fourcc_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e threadpool_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e shared_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e socket_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e rpc_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e module_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e uinput_unittest(int argc, char *argv[]); + +/*! \brief + * \param [in] argc + * \param [in] argv + * \ingroup group_unittest + */ +bool_e btreelist_unittest(int argc, char *argv[]); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/sosal/vector.h b/include/sosal/vector.h new file mode 100644 index 0000000..a4e45b4 --- /dev/null +++ b/include/sosal/vector.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOSAL_VECTOR_H_ +#define _SOSAL_VECTOR_H_ + +/*! \file + * \brief A Set of simple vector functions. + */ + +#include + +/*! \brief The storage for a 4D vector. + * \ingroup group_vectors + */ +typedef union _vector_t { + /*! \brief 4D point representation */ + struct { + float x; /*!< \brief x dimension */ + float y; /*!< \brief y dimension */ + float z; /*!< \brief z dimension */ + float t; /*!< \brief time dimension */ + } p; + /*! \brief 4D dimensional representation */ + struct { + float width; /*!< \brief pixel width */ + float height; /*!< \brief pixel height */ + float depth; /*!< \brief pixel depth */ + float age; /*!< \brief time */ + } dim; + float v[4]; /*!< \brief plain array of floats */ +} vector_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief a = a + b. + * \param [in,out] a Source and destination vector. + * \param [in] b Additive Vector. + * \ingroup group_vectors + */ +void vector_add(vector_t *a, vector_t *b); + +/*! \brief Multiplies each element in a by b and puts it back in a. + * \param [in,out] a Source and destination vector. + * \param [in] b Scalar value + * \group group_vectors + */ +void vector_scale(vector_t *a, float b); + +/*! \brief a = 1/a. + * \param [in,out] a Source and destination vector. + * \ingroup group_vectors + */ +void vector_inverse(vector_t *a); + +/*! \brief Computes the square root of the sum of squares of the components. + * \param [in] v The vector to calculate a magnitude from. + * \ingroup group_vectors + */ +float vector_mag(vector_t *v); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/win32/stdint.h b/include/win32/stdint.h new file mode 100644 index 0000000..fd54ac0 --- /dev/null +++ b/include/win32/stdint.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This is a compatibilty file for Windows Builds ONLY + +#if (defined(WIN32) || defined(UNDER_CE)) && !defined(CYGWIN) + +#include + +#ifndef __attribute__ +#define __attribute__(x) +#endif + +#ifndef unused +#define unused +#endif + +#ifndef restrict +#define restrict +#endif + +#ifndef _STDINT_H // this is the Standard C99 header define lock +#define _STDINT_H + +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed int int32_t; +typedef signed long long int64_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +#endif + +#endif + diff --git a/libraries/Android.mk b/libraries/Android.mk new file mode 100644 index 0000000..63ae413 --- /dev/null +++ b/libraries/Android.mk @@ -0,0 +1,89 @@ +include $(call all-subdir-makefiles) + +VISION_ROOT ?= $(TI_HW_ROOT)/vision +-include $(VISION_ROOT)/libraries/Android.mk + +ifneq (,$(findstring vlib,$(VISION_LIBRARIES))) +DVP_FEATURES += -DDVP_USE_VLIB +DVP_INCLUDES += $(VISION_ROOT)/libraries/protected/vlib/include +endif + +ifneq (,$(findstring rvm,$(VISION_LIBRARIES))) +DVP_FEATURES += -DDVP_USE_RVM +DVP_INCLUDES += $(VISION_ROOT)/libraries/protected/rvm/include +ifneq (,$(findstring rvm_sunex,$(VISION_LIBRARIES))) +DVP_INCLUDES += $(VISION_ROOT)/libraries/protected/rvm_sunex/include +endif +endif + +ifneq (,$(findstring tismo,$(VISION_LIBRARIES))) +DVP_FEATURES += -DDVP_USE_TISMO +DVP_INCLUDES += $(VISION_ROOT)/libraries/protected/tismo/include +endif + +ifneq (,$(findstring orb,$(VISION_LIBRARIES))) +DVP_FEATURES += -DDVP_USE_ORB +DVP_INCLUDES += $(VISION_ROOT)/libraries/protected/orb/include +endif + +ifneq (,$(findstring imglib,$(VISION_LIBRARIES))) +DVP_FEATURES += -DDVP_USE_IMGLIB +DVP_INCLUDES += $(VISION_ROOT)/libraries/protected/imglib/include +endif + +ifneq (,$(findstring dsplib,$(VISION_LIBRARIES))) +DVP_FEATURES += -DDVP_USE_DSPLIB +DVP_INCLUDES += $(DVP_ROOT)/libraries/public/dsplib/include +endif + +ifneq (,$(findstring ar,$(VISION_LIBRARIES))) +DVP_FEATURES += -DDVP_USE_AR +DVP_INCLUDES += $(VISION_ROOT)/libraries/protected/ar/include +endif + +ifneq (,$(findstring xtr_ll,$(VISION_LIBRARIES))) +DVP_FEATURES += -DDVP_USE_XTR +DVP_INCLUDES += $(VISION_ROOT)/libraries/protected/xtr_ll/include +endif + +ifneq (,$(findstring vrun,$(VISION_LIBRARIES))) +DVP_FEATURES += -DDVP_USE_VRUN +DVP_INCLUDES += $(DVP_ROOT)/libraries/public/vrun/include +endif + +ifneq (,$(findstring dei,$(VISION_LIBRARIES))) +DVP_FEATURES += -DDVP_USE_DEI +DVP_INCLUDES += $(VISION_ROOT)/libraries/protected/dei/include +endif + +ifneq (,$(findstring dsplib,$(VISION_LIBRARIES))) +DVP_FEATURES += -DDVP_USE_DSPLIB +DVP_INCLUDES += $(VISION_ROOT)/libraries/protected/dsplib/include +endif + +ifneq (,$(findstring orb,$(VISION_LIBRARIES))) +DVP_FEATURES += -DDVP_USE_ORB +DVP_INCLUDES += $(VISION_ROOT)/libraries/protected/orb/include +endif + +ifneq (,$(findstring imgfilter,$(VISION_LIBRARIES))) +DVP_FEATURES += -DDVP_USE_IMGFILTER +DVP_INCLUDES += $(DVP_TOP)/libraries/public/imgfilter/include +endif + +ifneq (,$(findstring yuv,$(VISION_LIBRARIES))) +DVP_FEATURES += -DDVP_USE_YUV +DVP_INCLUDES += $(DVP_TOP)/libraries/public/yuv/include +endif + +ifeq ($(TARGET_SCPU),C64T) +ifneq (,$(findstring c6xsim,$(VISION_LIBRARIES))) +DVP_FEATURES += -DVLIB_TARGET_C6XSIM -DSIMULATION -DTMS320C64PX -DLITTLE_ENDIAN_HOST +DVP_INCLUDES += $(VISION_ROOT)/libraries/protected/c6xsim/include +endif +endif + +# All the DVP_LIBRARIES should be set by now +$(info VISION_LIBRARIES = $(VISION_LIBRARIES)) +$(info DVP_FEATURES = $(DVP_FEATURES)) + diff --git a/libraries/concerto.mak b/libraries/concerto.mak new file mode 100644 index 0000000..5e6931b --- /dev/null +++ b/libraries/concerto.mak @@ -0,0 +1,59 @@ + +# If vision folder root is defined scan it for algorithms. +ifdef VISION_ROOT +$(info Including VISION Folder in Build for DVP) +DIRECTORIES:=$(VISION_ROOT)/libraries +NO_TARGETS:=1 +include $(VISION_ROOT)/concerto/rules.mak +NO_TARGETS:= + +# Define the location to add to LDIRS if you want VISION algos +VISION_LIB := $(VISION_ROOT)/out/$(TARGET_OS)/$(TARGET_CPU) + +# Add each algo present to the DVP_FEATURES and INC paths +ifneq (,$(findstring vlib,$(VISION_LIBRARIES))) +DVP_FEATURES += DVP_USE_VLIB +DVP_INC += $(VISION_ROOT)/libraries/protected/vlib/include +endif + +ifneq (,$(findstring rvm,$(VISION_LIBRARIES))) +DVP_FEATURES += DVP_USE_RVM +DVP_INC += $(VISION_ROOT)/libraries/protected/rvm/include +ifneq (,$(findstring rvm_sunex,$(VISION_LIBRARIES))) +DVP_INC += $(VISION_ROOT)/libraries/protected/rvm_sunex/include +endif +endif + +ifneq (,$(findstring tismo,$(VISION_LIBRARIES))) +DVP_FEATURES += DVP_USE_TISMO +DVP_INC += $(VISION_ROOT)/libraries/protected/tismo/include +endif + +ifneq (,$(findstring imglib,$(VISION_LIBRARIES))) +DVP_FEATURES += DVP_USE_IMGLIB +DVP_INC += $(VISION_ROOT)/libraries/protected/imglib/include +endif + +ifneq (,$(findstring ar,$(VISION_LIBRARIES))) +DVP_FEATURES += DVP_USE_AR +DVP_INC += $(VISION_ROOT)/libraries/protected/ar/include +endif + +ifneq (,$(findstring dei,$(VISION_LIBRARIES))) +DVP_FEATURES += DVP_USE_DEI +DVP_INC += $(VISION_ROOT)/libraries/protected/dei/include +endif + +ifneq (,$(findstring orb,$(VISION_LIBRARIES))) +DVP_FEATURES += DVP_USE_ORB +DVP_INC += $(VISION_ROOT)/libraries/protected/orb/include +endif + +ifeq ($(TARGET_SCPU),C64T) +ifneq (,$(findstring c6xsim,$(VISION_LIBRARIES))) +DVP_FEATURES += VLIB_TARGET_C6XSIM SIMULATION TMS320C64PX LITTLE_ENDIAN_HOST +DVP_INC += $(VISION_ROOT)/libraries/protected/c6xsim/include +endif +endif +endif + diff --git a/libraries/public/Android.mk b/libraries/public/Android.mk new file mode 100644 index 0000000..5053e7d --- /dev/null +++ b/libraries/public/Android.mk @@ -0,0 +1 @@ +include $(call all-subdir-makefiles) diff --git a/libraries/public/dsplib/Android.mk b/libraries/public/dsplib/Android.mk new file mode 100644 index 0000000..65e9161 --- /dev/null +++ b/libraries/public/dsplib/Android.mk @@ -0,0 +1,16 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +VISION_LIBRARIES += dsplib + diff --git a/libraries/public/dsplib/concerto.mak b/libraries/public/dsplib/concerto.mak new file mode 100644 index 0000000..9b40e90 --- /dev/null +++ b/libraries/public/dsplib/concerto.mak @@ -0,0 +1,24 @@ + +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_CPU),ARM) + +# DSPLIB is only present on the OMAP platform. +VISION_LIBRARIES += dsplib +DVP_FEATURES += DVP_USE_DSPLIB +DVP_INC += $(DVP_ROOT)/libraries/public/dsplib/include + +endif + diff --git a/libraries/public/dsplib/include/dsplib/Test_DSPLIB.h b/libraries/public/dsplib/include/dsplib/Test_DSPLIB.h new file mode 100644 index 0000000..87ef70a --- /dev/null +++ b/libraries/public/dsplib/include/dsplib/Test_DSPLIB.h @@ -0,0 +1,880 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef TEST_DSPLIB +#define MAXARRAYSIZE 128 +DVP_S16 buffer_x[MAXARRAYSIZE]= +{ + 0x5A0A, 0xCD7B, 0x8397, 0xA5BC, 0xB196, 0x963C, 0x61C8, 0xE43A, + 0x1C8B, 0x55F2, 0x32B9, 0xB3DD, 0xE468, 0x64CE, 0x3F29, 0x2815, + 0x99CB, 0x813E, 0xCAB7, 0xE031, 0xE954, 0x8AF2, 0x9943, 0x2780, + 0x8DC1, 0x2C18, 0xA0EA, 0x6371, 0x9033, 0x2F1F, 0xF36D, 0xB972, + 0x5B46, 0x9837, 0x6009, 0x7354, 0x7CBB, 0xCB4E, 0x4D5F, 0x90E4, + 0x27B1, 0xCBF3, 0xD4CD, 0xCA53, 0xD3A7, 0xDD56, 0xEF72, 0x866E, + 0x637B, 0x6CE5, 0x084D, 0x3A65, 0xCA8D, 0x45D0, 0x8A5D, 0xB246, + 0x031B, 0xBC84, 0xB401, 0x9DC2, 0xB285, 0xE273, 0x6C99, 0xE626, + 0x3D8A, 0x5E49, 0x0742, 0xDAE3, 0x7488, 0x5DF7, 0x36BD, 0xA466, + 0xBE5F, 0x8DAB, 0x6647, 0xCF7F, 0x8A8D, 0xBFF5, 0x3E81, 0x867D, + 0x1CD2, 0x1103, 0xF7C9, 0x8B0F, 0xAE8D, 0x03A4, 0x22BE, 0x7CC3, + 0x739C, 0x9D08, 0xC9DF, 0xB2AA, 0x155F, 0x2D3D, 0x80AC, 0xD731, + 0x9654, 0x0273, 0x9582, 0x5C69, 0xBC3B, 0xB957, 0x3641, 0x293F, + 0x3533, 0x94DA, 0x1E69, 0xE5A3, 0xD45A, 0xC82B, 0x8758, 0xFAC3, + 0x7ED0, 0x3E98, 0x4E2C, 0x3C10, 0xDED3, 0x0110, 0x3666, 0xD178, + 0x9683, 0xD6E3, 0x3A24, 0x22E9, 0xFC9F, 0xCD7F, 0x3DE5, 0x2133, +}; + +DVP_S16 buffer_y[MAXARRAYSIZE] = +{ + 0x6DE5, 0xD5F3, 0x86A9, 0x8805, 0x8695, 0x54AF, 0xE1AD, 0x5BEE, + 0x856E, 0x8261, 0x0052, 0xA09D, 0xCBAE, 0x9EF8, 0x01F5, 0x52E1, + 0xE2D5, 0xC8A4, 0x55F7, 0xB8A8, 0x1121, 0x6813, 0xE576, 0xBCE3, + 0x1112, 0xB2B4, 0x4070, 0x4C3F, 0x5407, 0xF997, 0x9346, 0xD36C, + 0xDFDE, 0x428A, 0xB497, 0x7E59, 0x5157, 0x6DBD, 0x20E0, 0x23F5, + 0x0D70, 0x34BE, 0x8481, 0x744F, 0xD429, 0x4CBC, 0xC51A, 0xBE15, + 0x9F01, 0xD327, 0x8468, 0xF118, 0x3D36, 0x8B2D, 0xF0EC, 0x4CA5, + 0xEDE8, 0xCE3D, 0x3A04, 0xF5AC, 0x5EB5, 0x2187, 0x7BCE, 0x077C, + 0xFCFD, 0xDF80, 0xC98B, 0xE564, 0xE27F, 0xE342, 0xB89A, 0xF7D3, + 0x4F39, 0xBA12, 0xF418, 0x0337, 0x6F4B, 0x13D7, 0x4B05, 0x54A1, + 0x2394, 0x5020, 0xFC80, 0x913E, 0x8252, 0x889D, 0x1FE9, 0xEBDE, + 0x96A4, 0x07DD, 0x959E, 0x80B0, 0x56EB, 0xF72D, 0xA67D, 0xCFC3, + 0xBD24, 0x437E, 0x08C7, 0xE546, 0xFC8E, 0x7F3E, 0x5B7A, 0x85A7, + 0x5609, 0xCF9D, 0xFB15, 0x6ED7, 0x9BF4, 0x3289, 0x5037, 0x0443, + 0x9B2D, 0x1E91, 0x0DE0, 0x60DB, 0xF474, 0xAC45, 0x0A2D, 0xBFCE, + 0x4848, 0x8093, 0x577F, 0x75CB, 0x2727, 0x898B, 0xF1D3, 0x2781, +}; +#define NX (256) +#define NH (24) +#define NR (100) +#define PAD (16) + +const DVP_S16 FIR_x[NX + 2*PAD] = +{ + 0x76E2, 0x8B0E, 0x4A09, 0xBA35, 0xEB22, 0xE6EB, 0x8CCF, 0xDF71, // Beginning + 0xAACF, 0x3CE2, 0xADDA, 0x3E77, 0x8CA7, 0x6C43, 0x0F68, 0xCCF6, // PAD + + 0x5A0A, 0xCD7B, 0x8397, 0xA5BC, 0xB196, 0x963C, 0x61C8, 0xE43A, + 0x1C8B, 0x55F2, 0x32B9, 0xB3DD, 0xE468, 0x64CE, 0x3F29, 0x2815, + 0x99CB, 0x813E, 0xCAB7, 0xE031, 0xE954, 0x8AF2, 0x9943, 0x2780, + 0x8DC1, 0x2C18, 0xA0EA, 0x6371, 0x9033, 0x2F1F, 0xF36D, 0xB972, + 0x5B46, 0x9837, 0x6009, 0x7354, 0x7CBB, 0xCB4E, 0x4D5F, 0x90E4, + 0x27B1, 0xCBF3, 0xD4CD, 0xCA53, 0xD3A7, 0xDD56, 0xEF72, 0x866E, + 0x637B, 0x6CE5, 0x084D, 0x3A65, 0xCA8D, 0x45D0, 0x8A5D, 0xB246, + 0x031B, 0xBC84, 0xB401, 0x9DC2, 0xB285, 0xE273, 0x6C99, 0xE626, + 0x3D8A, 0x5E49, 0x0742, 0xDAE3, 0x7488, 0x5DF7, 0x36BD, 0xA466, + 0xBE5F, 0x8DAB, 0x6647, 0xCF7F, 0x8A8D, 0xBFF5, 0x3E81, 0x867D, + 0x1CD2, 0x1103, 0xF7C9, 0x8B0F, 0xAE8D, 0x03A4, 0x22BE, 0x7CC3, + 0x739C, 0x9D08, 0xC9DF, 0xB2AA, 0x155F, 0x2D3D, 0x80AC, 0xD731, + 0x9654, 0x0273, 0x9582, 0x5C69, 0xBC3B, 0xB957, 0x3641, 0x293F, + 0x3533, 0x94DA, 0x1E69, 0xE5A3, 0xD45A, 0xC82B, 0x8758, 0xFAC3, + 0x7ED0, 0x3E98, 0x4E2C, 0x3C10, 0xDED3, 0x0110, 0x3666, 0xD178, + 0x9683, 0xD6E3, 0x3A24, 0x22E9, 0xFC9F, 0xCD7F, 0x3DE5, 0x2133, + 0x6DE5, 0xD5F3, 0x86A9, 0x8805, 0x8695, 0x54AF, 0xE1AD, 0x5BEE, + 0x856E, 0x8261, 0x0052, 0xA09D, 0xCBAE, 0x9EF8, 0x01F5, 0x52E1, + 0xE2D5, 0xC8A4, 0x55F7, 0xB8A8, 0x1121, 0x6813, 0xE576, 0xBCE3, + 0x1112, 0xB2B4, 0x4070, 0x4C3F, 0x5407, 0xF997, 0x9346, 0xD36C, + 0xDFDE, 0x428A, 0xB497, 0x7E59, 0x5157, 0x6DBD, 0x20E0, 0x23F5, + 0x0D70, 0x34BE, 0x8481, 0x744F, 0xD429, 0x4CBC, 0xC51A, 0xBE15, + 0x9F01, 0xD327, 0x8468, 0xF118, 0x3D36, 0x8B2D, 0xF0EC, 0x4CA5, + 0xEDE8, 0xCE3D, 0x3A04, 0xF5AC, 0x5EB5, 0x2187, 0x7BCE, 0x077C, + 0xFCFD, 0xDF80, 0xC98B, 0xE564, 0xE27F, 0xE342, 0xB89A, 0xF7D3, + 0x4F39, 0xBA12, 0xF418, 0x0337, 0x6F4B, 0x13D7, 0x4B05, 0x54A1, + 0x2394, 0x5020, 0xFC80, 0x913E, 0x8252, 0x889D, 0x1FE9, 0xEBDE, + 0x96A4, 0x07DD, 0x959E, 0x80B0, 0x56EB, 0xF72D, 0xA67D, 0xCFC3, + 0xBD24, 0x437E, 0x08C7, 0xE546, 0xFC8E, 0x7F3E, 0x5B7A, 0x85A7, + 0x5609, 0xCF9D, 0xFB15, 0x6ED7, 0x9BF4, 0x3289, 0x5037, 0x0443, + 0x9B2D, 0x1E91, 0x0DE0, 0x60DB, 0xF474, 0xAC45, 0x0A2D, 0xBFCE, + 0x4848, 0x8093, 0x577F, 0x75CB, 0x2727, 0x898B, 0xF1D3, 0x2781, + + 0xCC91, 0xC1DA, 0x2F0A, 0x933F, 0xE304, 0x8432, 0x7602, 0x4CB3, // Ending + 0xE3A0, 0xFA3F, 0x73BA, 0x6F6D, 0xB144, 0xAB32, 0x5C31, 0x7D9D // PAD +}; + +const DVP_S16 FIR_h[2*NH + 2*PAD] = +{ + 0x76E2, 0x8B0E, 0x4A09, 0xBA35, 0xEB22, 0xE6EB, 0x8CCF, 0xDF71, // Beginning + 0xAACF, 0x3CE2, 0xADDA, 0x3E77, 0x8CA7, 0x6C43, 0x0F68, 0xCCF6, // PAD + + 0x5A0A, 0xCD7B, 0x8397, 0xA5BC, 0xB196, 0x963C, 0x61C8, 0xE43A, + 0x1C8B, 0x55F2, 0x32B9, 0xB3DD, 0xE468, 0x64CE, 0x3F29, 0x2815, + 0x99CB, 0x813E, 0xCAB7, 0xE031, 0xE954, 0x8AF2, 0x9943, 0x2780, + 0x8DC1, 0x2C18, 0xA0EA, 0x6371, 0x9033, 0x2F1F, 0xF36D, 0xB972, + 0x5B46, 0x9837, 0x6009, 0x7354, 0x7CBB, 0xCB4E, 0x4D5F, 0x90E4, + 0x27B1, 0xCBF3, 0xD4CD, 0xCA53, 0xD3A7, 0xDD56, 0xEF72, 0x866E, + + 0xCC91, 0xC1DA, 0x2F0A, 0x933F, 0xE304, 0x8432, 0x7602, 0x4CB3, // Ending + 0xE3A0, 0xFA3F, 0x73BA, 0x6F6D, 0xB144, 0xAB32, 0x5C31, 0x7D9D // PAD +}; + +short FFT_x[2*NX + 2*PAD] = +{ +/* Input Number: 0 */ + 0x393D, 0x144A, 0x0F1F, -0x72ED, -0x5689, -0x64C1, 0x6193, 0x54CD, + 0x7E16, -0x2016, -0x6AEF, 0x4922, -0x5368, 0x0897, 0x54EB, 0x0084, + + 0x1FAE, 0x1489, 0x1EC9, -0x6F5E, 0x5BE8, -0x024A, 0x75B7, 0x2217, + -0x2EB6, 0x4D81, 0x0757, 0x254F, -0x7FCC, -0x6A05, 0x65AE, -0x5AC9, + 0x5D3B, 0x4219, -0x47E8, 0x4A2C, -0x03AD, 0x6576, 0x00D7, 0x7AA6, + -0x0016, -0x2FEE, 0x55CB, 0x1E2C, -0x32AC, 0x2494, -0x4F3C, -0x6FFF, + 0x0826, 0x4087, -0x4C0A, 0x2E16, 0x4CEB, -0x6DE1, -0x03EC, 0x0BC2, + -0x484A, -0x2E04, 0x7E82, 0x4FAD, -0x55DF, -0x6293, 0x5530, -0x4875, + 0x5E20, 0x7DB6, -0x516A, -0x47EE, -0x4EC0, -0x3429, 0x2649, -0x3754, + -0x3F41, -0x00AD, 0x37BA, 0x5271, -0x3CFA, -0x1F8B, 0x2494, -0x371C, + -0x51F4, 0x1E9F, -0x0CCB, 0x59E3, 0x180D, -0x38F2, -0x2132, -0x2B94, + -0x17D1, 0x31A9, -0x275A, 0x2993, 0x417D, -0x49B1, -0x750B, 0x123F, + 0x3CCC, -0x18E2, 0x61E9, 0x5E28, -0x1D06, -0x68BA, 0x1647, 0x6698, + -0x18EE, 0x50D8, 0x4231, 0x2468, -0x4A2F, -0x4FED, 0x7584, 0x6DC2, + 0x3008, 0x23BA, 0x5366, -0x2ADE, -0x379A, -0x751F, 0x3367, -0x4DE8, + 0x4A1C, 0x42C4, -0x3A38, -0x34B1, -0x031A, 0x161B, 0x3F68, 0x244D, + 0x75F3, -0x7695, -0x7439, 0x797D, -0x3AD0, 0x18E2, -0x0248, -0x2D0D, + 0x5974, -0x31D6, 0x0D25, -0x3A8C, 0x2907, -0x343B, -0x6A7F, -0x24C1, + -0x56E9, 0x2A61, 0x1653, -0x66E7, -0x0081, -0x3549, -0x7E9C, -0x52ED, + 0x0077, -0x7C9D, 0x0411, -0x3E67, 0x6FA9, 0x3843, 0x5D37, 0x7640, + 0x021C, 0x52D1, 0x3649, -0x0232, -0x5179, 0x2204, -0x06FF, -0x20F1, + -0x4878, -0x59D2, -0x42CF, 0x5DE2, 0x0334, 0x305C, -0x5CC4, 0x0208, + 0x338C, 0x74B7, 0x4AA6, -0x2CC7, 0x0256, -0x7E98, -0x46AF, -0x5D0B, + 0x6BD0, 0x1578, 0x5DCD, 0x0E96, 0x0CCB, -0x23C8, 0x7A56, -0x5FD6, + 0x5AA2, 0x13A3, -0x4913, -0x6E7F, 0x0E97, 0x1045, 0x1310, -0x4AF4, + 0x6109, 0x2E24, 0x0194, 0x09EE, -0x7CEC, -0x5FDA, -0x13D6, 0x68D8, + -0x1CF3, -0x5984, -0x3410, -0x1BDF, -0x50A2, -0x5676, 0x3DBA, 0x45A4, + 0x2648, -0x412D, -0x5694, 0x2AD7, 0x2202, 0x0767, -0x2503, 0x54AD, + 0x72B7, -0x7AB2, -0x516B, -0x6D54, 0x74ED, -0x4088, 0x4054, -0x2C2A, + 0x71C3, -0x2056, 0x1932, -0x2341, 0x4799, -0x5911, -0x157C, 0x2875, + -0x336D, -0x34F4, 0x43A4, 0x669B, -0x7B82, 0x456D, -0x25CD, 0x1E52, + 0x0D98, -0x15E3, -0x337B, 0x025A, -0x2145, 0x0537, 0x6CA7, 0x58F5, + -0x42A1, 0x455D, 0x1087, 0x130F, -0x75F6, -0x6A54, 0x66C3, 0x0B25, + -0x3D68, 0x58B8, -0x2E70, -0x2196, 0x49EA, -0x7203, 0x4449, -0x0D4E, + 0x006E, 0x545F, 0x291A, 0x239D, -0x64EF, 0x5A21, -0x36AE, -0x7482, + 0x390C, -0x5420, -0x4630, -0x0778, 0x4816, 0x660F, -0x30ED, -0x7944, + 0x2971, -0x288A, 0x176E, -0x25EA, 0x1B62, 0x792E, 0x55D6, -0x7A84, + -0x1682, 0x5CA4, 0x7FDC, 0x0AED, -0x1EA0, 0x6813, -0x31C6, 0x0C70, + -0x74C0, 0x150B, -0x3E70, 0x1F4C, -0x551A, -0x0990, -0x4C4C, -0x410F, + -0x027E, -0x4782, 0x6F2C, -0x1CC9, 0x47E7, -0x01B2, 0x4D47, -0x31B9, + 0x229D, -0x5EA5, 0x5057, 0x65DB, 0x0A61, -0x237A, -0x3476, -0x41D3, + 0x3A7E, -0x2BE0, 0x0CE4, 0x5334, -0x3A76, 0x1070, -0x7421, 0x5099, + 0x7900, 0x483E, 0x1C26, -0x6E0C, 0x0741, 0x28DE, -0x530A, -0x403D, + -0x1390, 0x6D37, -0x0467, 0x10A9, -0x5E49, -0x16AC, -0x1F75, 0x3668, + -0x6C9F, -0x0D13, -0x6D49, -0x1ADE, 0x5D62, -0x4F88, 0x7560, -0x74AC, + -0x3848, -0x2FC7, -0x15E4, -0x5EE8, 0x072C, 0x21D0, -0x567F, 0x2F26, + -0x2D06, -0x7038, 0x1AE2, -0x19ED, -0x5B26, 0x08B0, 0x38BD, 0x6C56, + -0x2A22, -0x36D8, 0x773F, 0x428D, -0x0B3D, -0x7A88, 0x2C6A, -0x2783, + -0x1DEB, -0x04DB, 0x0265, 0x435E, 0x34B9, 0x6F06, -0x15A2, 0x11DB, + 0x5D5D, -0x7CA5, 0x199E, -0x2FA2, 0x183B, -0x0196, -0x7BD1, -0x53E6, + -0x6332, -0x12EF, 0x65AC, -0x40B1, 0x10DC, -0x4D1C, 0x45B1, 0x7759, + -0x3898, 0x7549, 0x0967, -0x5103, -0x3E04, 0x7912, -0x7A49, -0x1A90, + -0x0C1F, -0x2AE4, 0x139B, 0x19AB, -0x3354, 0x176B, -0x4DF2, -0x318A, + -0x774C, 0x474C, 0x2825, -0x4E4A, -0x3B1D, -0x300C, -0x5944, 0x6485, + -0x2692, -0x32E1, 0x7752, -0x0C84, 0x76E9, 0x4535, 0x307E, 0x67C8, + 0x093F, -0x4492, -0x187F, 0x0280, 0x6307, -0x518D, -0x1579, -0x5F48, + 0x28C4, 0x7C05, -0x7B06, -0x442B, -0x7F8C, 0x2C22, 0x3F7F, -0x695A, + -0x6FE8, -0x67D2, 0x3112, 0x0CBE, 0x3684, -0x7F64, -0x3A40, -0x797B, + -0x76DC, -0x006D, -0x6979, -0x6F65, -0x5DEB, -0x16E5, -0x3B2D, -0x6416, + 0x2528, -0x72B7, 0x511F, 0x600A, 0x133F, 0x53EA, 0x0832, 0x6556, + 0x5F8F, -0x2DD1, 0x6285, 0x2F50, -0x36BE, -0x4921, -0x0CBE, -0x7045, + 0x7CF9, 0x1B81, -0x2396, -0x6102, -0x0A4E, -0x3CF0, -0x396A, -0x29BE, + -0x5575, -0x4855, -0x2921, -0x2929, -0x0518, -0x3637, 0x3766, 0x4454, + -0x2183, 0x7F66, -0x6708, 0x5EF9, -0x184F, -0x213F, 0x3B57, -0x5C25, + -0x0B16, -0x60F7, 0x08A5, 0x3140, 0x3C37, 0x4495, 0x1A70, 0x36CD, + 0x0FDA, -0x67E1, 0x60D7, 0x17EC, -0x18CC, 0x1078, -0x46A2, -0x4F0F, + + 0x3694, -0x6FBD, 0x18D6, 0x3D8A, -0x7E9F, 0x162E, 0x2EF0, 0x6AE5, + 0x372C, -0x30D1, 0x16E8, 0x081A, -0x2DE1, 0x0940, -0x7429, -0x209F + +}; + +#define NHR (32) +#define NRR (128) +#define NXR (160) /* NX = NH + NR */ +#define PADR (16) + +const short FIR_Rx[NXR + 2*PADR] = +{ + 0x032C, -0x544D, -0x6A9D, 0x09C4, 0x5226, 0x6A85, 0x6EDE, 0x1463, // Beginning + -0x158A, 0x75BC, 0x7407, 0x160B, -0x0E16, -0x3F82, 0x5F6D, -0x567B, // PAD + + 0x453E, -0x321D, 0x2DBB, 0x77C7, -0x57B9, -0x4ADD, 0x10B7, -0x113F, + -0x1A92, 0x7CA7, 0x4A14, 0x719D, 0x3E61, 0x1858, -0x0D4C, 0x3D94, + -0x32B8, -0x14B2, 0x1B6A, 0x7A1D, 0x0D5B, 0x1D2C, 0x55D8, -0x5459, + 0x5030, -0x5CBD, 0x0180, 0x059B, 0x4D97, 0x49E3, 0x68A4, -0x3629, + -0x7AA5, -0x582E, 0x1D05, 0x3A65, -0x4734, 0x3D6B, -0x6CE3, 0x4A99, + 0x1D54, -0x50B4, 0x62F5, -0x75A7, -0x6AFA, 0x5D26, 0x3C1A, -0x793D, + -0x6493, 0x4282, -0x0020, 0x1BE0, 0x1A7F, 0x621B, -0x1C86, -0x254E, + -0x12FB, -0x4E5B, 0x3409, 0x223E, 0x3856, -0x4179, -0x60C9, -0x102C, + 0x5EB6, -0x097B, 0x7A6E, 0x1450, -0x41CD, -0x133A, 0x0358, -0x2677, + -0x0BA0, 0x6732, 0x19A5, -0x4961, -0x1E47, -0x6657, 0x57C6, 0x1E70, + 0x1F12, 0x59F9, 0x13A4, 0x16D9, 0x26E6, -0x4FE0, 0x39FA, -0x6AF4, + -0x2829, -0x673F, 0x7460, 0x57A6, -0x5BB4, 0x424C, -0x6068, 0x2CC9, + 0x0F61, -0x4030, -0x00AD, 0x6AE1, -0x4FD3, 0x56ED, 0x2FDA, -0x759C, + -0x726F, 0x78E3, 0x42DF, -0x63D3, -0x1F88, -0x71D0, 0x07E8, -0x6D4A, + 0x21E5, -0x6C4D, -0x0072, 0x0EEE, 0x749D, -0x4622, -0x2AF7, -0x3A2B, + 0x3DC4, 0x05D0, -0x00C7, 0x059F, 0x1C52, 0x36EE, 0x58B6, -0x7864, + -0x145A, -0x3F1F, 0x4107, 0x1B89, 0x2024, 0x4771, 0x3F8F, 0x4298, + 0x231F, 0x6C44, -0x79AD, 0x58DA, -0x1706, 0x37E1, 0x6B2A, 0x6447, + -0x7C33, 0x080C, 0x426E, 0x1F1C, -0x2095, 0x64D2, -0x7634, 0x4BC4, + 0x6720, 0x6260, -0x12BD, 0x040C, -0x3F04, 0x2FFF, 0x14F4, 0x00CC, + + -0x01CC, -0x1F8D, -0x35A1, 0x432A, -0x35C6, -0x0E0F, -0x7FEF, 0x3D0B, // Ending + 0x3D0B, 0x2B67, -0x7BC7, 0x48D5, -0x1FE3, 0x0ADA, 0x4F02, -0x69DF // PAD +}; + +const short FIR_Rh[NHR + 2*PADR] = +{ + -0x6226, 0x4E99, 0x52AC, -0x322F, -0x4CF2, 0x34FE, -0x26B0, 0x512C, // Beginning + -0x7CE4, 0x59F0, -0x4137, -0x7CBE, -0x7F4B, -0x5471, -0x1A85, -0x0F38, // PAD + + -0x0007, 0x002A, -0x0006, 0x0027, -0x0016, 0x001E, 0x0047, 0x005B, + 0x0064, -0x0017, -0x001F, 0x0039, -0x0015, -0x0063, -0x0009, -0x0016, + -0x0017, 0x003A, -0x0016, 0x0037, -0x0036, 0x003E, 0x0057, 0x006B, + 0x0074, -0x0037, -0x003F, 0x0069, -0x0035, -0x0033, -0x0019, -0x0036, + + 0x524B, -0x71B5, 0x5C6E, 0x4C92, 0x6100, 0x4ED3, 0x7244, -0x5594, // Ending + -0x12C8, -0x6F88, 0x6EDB, 0x3284, -0x36A5, 0x33E6, 0x05AC, -0x1E10 // PAD +}; + +#define NHS (16) +#define NRS (16) +#define NXS (48) /* NX = 2*NH + NR + 2 */ +#define PADS (16) + +/* ======================================================================= */ +/* Initilized arrays with fixed test data */ +/* ======================================================================= */ +const short FIR_xS[NXS] = +{ + 0xFF94, 0x000A, 0x236F, 0xFE45, 0xF9B1, 0x00E3, 0x001F, 0xD5E4, + 0x03EE, 0xF9F2, 0x001A, 0xFFFC, 0xFFD6, 0xFFFD, 0x0000, 0x0000, + 0xFFFF, 0xE82B, 0xABCD, 0xBCDE, 0xCDEF, 0xDEFA, 0xEFAB, 0xFAB1, + 0xAB12, 0xB123, 0x1234, 0x2345, 0x3456, 0x4567, 0x5678, 0x6789, + 0x789A, 0x89AB, 0x9ABC, 0xABCD, 0xADDA, 0xEFFE, 0xBCCA, 0xDEAD, + 0x7FF7, 0x7FFF, 0xFDCA, 0x4823, 0x2567, 0x4EEA, 0x8000, 0x7ACE +}; + +const short FIR_hs[NHS + 2*PADS] = +{ + 0x02AC, 0xFFFF, 0x3F6B, 0x3D15, 0xFFDE, 0xFFFB, 0x0003, 0xFFE5, + 0xFFEA, 0x0032, 0x2411, 0xFC54, 0x0072, 0xFF6A, 0xFFE5, 0xFFFA, + 0xDBC7, 0xFFF8, 0x0002, 0x0000, 0x3FCC, 0xE8AA, 0x019E, 0x0009, + 0xFF26, 0x0005, 0x0023, 0x0009, 0xEA26, 0x07F0, 0xF3CD, 0x001B, + 0xF07B, 0x007B, 0x0001, 0x0372, 0xFFFE, 0xFFF6, 0x0016, 0xFFD2, + 0x185F, 0x00FF, 0xFAAF, 0xDADE, 0xDEAD, 0xCEAD, 0xABBA, 0x7FFF +}; + +short IFFT_x[2*256 ] = +{ + -0x02B3, -0x39E6, -0x1CB4, 0x4BBD, 0x103A, 0x0812, 0x3F07, 0x149D, + 0x4411, 0x3FB2, 0x412A, -0x5490, -0x05B9, 0x7604, -0x6FDB, 0x517B, + -0x09CF, 0x09AF, -0x2093, 0x521F, 0x0C36, 0x63AB, 0x2510, 0x278C, + -0x711A, 0x2207, -0x1D98, 0x3DAE, 0x0269, 0x2328, -0x1A91, -0x1D21, + -0x652A, -0x0EF8, 0x1A34, -0x2728, -0x0C18, 0x15F8, -0x280D, 0x0564, + -0x6569, -0x2B99, 0x354C, -0x28AD, -0x2FF2, -0x37DE, -0x15E8, -0x42D1, + 0x1E84, -0x1B63, 0x2A6A, 0x5034, 0x2279, 0x5FB6, 0x0922, -0x65FE, + 0x29CC, -0x0384, -0x1555, 0x0C98, 0x0A39, 0x3F7B, 0x685A, -0x77F1, + -0x3547, 0x0202, 0x50E7, 0x238C, -0x7FC5, -0x0F13, 0x158F, 0x0003, + 0x0147, 0x6A73, 0x5051, -0x2CD2, -0x2E05, 0x476D, -0x3C2F, -0x76B5, + -0x2513, 0x04AB, 0x6457, -0x69E8, 0x636E, -0x3046, -0x1E8D, 0x6696, + -0x2E54, -0x0146, 0x3EC0, 0x7704, -0x51CA, 0x6BA8, -0x1DB9, -0x6C5E, + 0x6D60, 0x2EB5, -0x47F9, -0x504E, 0x7E0A, 0x4414, -0x30E6, -0x07C4, + 0x1F48, -0x6931, 0x00FE, 0x780F, 0x7569, -0x15E4, 0x1779, -0x1976, + 0x67DD, 0x30B0, 0x07A8, 0x229C, -0x3A7B, -0x406A, -0x6359, -0x366F, + 0x2BD9, -0x0EF8, 0x365B, 0x7314, 0x3275, -0x603D, 0x06E2, 0x1FFA, + 0x5E88, 0x1167, 0x551C, 0x354F, 0x549E, -0x3CB8, 0x4DDC, -0x49E6, + -0x26AA, -0x69AC, -0x3CC5, 0x116D, 0x0F67, -0x149C, -0x7181, 0x1A34, + 0x7E9E, 0x16A3, -0x22C9, -0x57C5, 0x5A23, -0x399B, 0x16E6, 0x5405, + -0x6749, -0x3DF5, -0x4C27, -0x182A, 0x3B40, -0x66A0, -0x4D64, -0x2279, + 0x7543, -0x5405, -0x0970, -0x5F6B, 0x02B7, 0x2324, 0x401F, -0x2909, + 0x4CBE, 0x4BB2, 0x2415, 0x622E, -0x2D46, -0x358B, 0x7E98, -0x7FE3, + 0x5749, 0x4A95, -0x04BE, -0x72E4, 0x569F, -0x0382, 0x17DC, -0x0D2F, + 0x35BE, -0x773C, 0x2937, -0x50BA, -0x38EC, -0x2475, -0x0C54, 0x13C2, + -0x7608, 0x62F2, 0x36B5, 0x13E3, 0x2A87, 0x23FC, -0x36D0, -0x3287, + -0x289C, 0x3C7A, -0x4644, -0x5D5D, -0x3328, 0x4E7A, -0x1447, -0x7759, + -0x582F, 0x43B4, -0x3B96, -0x0EEB, 0x0547, 0x0175, 0x57B9, -0x205E, + -0x1E83, 0x7B91, -0x6BE7, -0x61B5, 0x36A3, -0x502F, 0x040A, -0x65CE, + 0x6D60, 0x0168, -0x7F42, -0x183E, 0x08B3, -0x7E1F, 0x7563, -0x1D6D, + 0x15BF, -0x6BEB, 0x2986, 0x7E89, -0x1513, -0x7F62, -0x79E1, -0x4842, + -0x6007, 0x5F4B, -0x164A, -0x5B5B, -0x2BA4, -0x07E7, 0x7933, -0x5011, + 0x3294, -0x05D7, -0x7E3A, 0x7CB8, 0x41D3, 0x2037, 0x4C74, -0x1A96, + -0x0E76, -0x48EB, 0x0BC3, -0x5816, 0x7559, 0x07A3, 0x3F0E, 0x3281, + -0x2324, 0x27CC, 0x25ED, 0x190A, -0x0A26, -0x4EFC, -0x54B7, -0x5524, + -0x10A6, -0x1F41, 0x6690, 0x2EF9, 0x4A12, -0x758A, 0x0F82, 0x4AFD, + -0x7E47, -0x765C, 0x0829, 0x054E, 0x02BE, 0x0341, 0x5E6C, -0x08F6, + -0x1B27, 0x1A4D, -0x263E, 0x173D, -0x15FA, 0x7ECA, -0x7273, -0x4D31, + 0x4359, 0x69C2, 0x6D8D, 0x09BC, -0x6BCD, 0x77CD, 0x67FC, 0x0F05, + -0x3C9E, -0x106C, -0x7839, -0x3316, 0x0F94, -0x182B, -0x679C, -0x1224, + -0x1E49, -0x2E8F, -0x302D, -0x1348, -0x134D, -0x1112, -0x02C8, 0x6CBD, + 0x1004, 0x2402, -0x4166, 0x2CCA, 0x7CC0, -0x4663, 0x363E, 0x2852, + -0x6395, 0x76F7, -0x33D7, 0x5CA0, 0x4B41, -0x54E8, 0x7141, -0x5334, + -0x3AB0, -0x6698, -0x1C72, 0x70FE, -0x1A02, -0x3D46, 0x7D19, 0x2A69, + 0x226C, -0x5E9F, 0x0AF7, -0x2771, -0x2BCC, 0x3FBA, 0x17E4, 0x743C, + 0x3D17, 0x35C0, 0x5711, 0x15CC, -0x2404, -0x71E0, 0x7B85, 0x332F, + 0x75DA, 0x1148, 0x1EA7, -0x6BDA, 0x7B00, 0x6EFE, 0x2F64, 0x5C4F, + 0x1B3B, -0x3009, 0x607C, -0x3D9A, -0x519C, 0x54E6, 0x1969, -0x15B3, + -0x2C37, -0x1364, 0x786D, 0x6557, -0x1707, 0x189C, -0x35C2, -0x2BB7, + 0x3271, 0x13B1, 0x10D1, 0x33AC, 0x58A8, -0x26F0, 0x0CCB, 0x44D3, + -0x62FC, -0x6094, 0x4911, -0x58D8, 0x6222, 0x2495, -0x4B0B, 0x0E37, + 0x6B0C, 0x6A17, 0x2F8C, 0x1DFF, 0x66CB, 0x5C55, -0x4D64, 0x6AFD, + 0x40D7, -0x3356, 0x69B3, 0x2580, -0x4913, 0x6208, 0x5DD9, -0x194A, + -0x4F3B, -0x1865, 0x2266, 0x1CFD, -0x21DC, 0x7BE9, 0x057C, -0x5C05, + 0x1DD8, 0x2CF8, 0x4296, 0x02ED, 0x1D0C, 0x78EF, -0x3F35, -0x3645, + -0x2B7F, 0x27BE, -0x2DE1, -0x6BAD, 0x292D, 0x1D42, 0x7B81, 0x3CBB, + 0x70AF, 0x7E6D, -0x4918, -0x5F97, 0x2830, -0x3711, 0x490C, -0x64A2, + 0x781C, 0x41DE, -0x6ABC, -0x6181, -0x08BB, 0x59E2, -0x0EF9, 0x6EAE, + 0x3BDD, 0x695D, 0x0A89, -0x78D8, -0x5B28, 0x591A, -0x3F02, -0x5A62, + -0x09D3, -0x5706, 0x15F8, -0x1166, 0x2F7A, 0x5F21, -0x6B95, 0x4894, + 0x2B82, 0x6724, -0x372D, 0x515A, -0x79EB, -0x4243, 0x30F2, 0x762C, + 0x47D3, 0x167A, 0x3ABE, -0x45E1, -0x34AD, 0x60EF, -0x381F, -0x68C0, + 0x7E2A, -0x5317, -0x4F9F, -0x7208, -0x31AD, -0x03DE, -0x3014, -0x2DD1, + -0x138A, 0x73F9, 0x113F, -0x594B, -0x326C, 0x72A4, 0x0C31, -0x349D, + -0x0D6E, 0x0E6A, -0x6A25, -0x5477, 0x7524, 0x785B, -0x1B93, -0x6CED, +}; + +#define NK_IIR (32) +#define NK1_IIR (NK_IIR+1) +#define NX_IIR (20) +#define PAD_IIR (16) + + +/* ======================================================================= */ +/* Initialized arrays with fixed test data. */ +/* ======================================================================= */ +short x_IIR[NX_IIR + 2*PAD_IIR] = +{ + 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, + 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, + + 0xBBCD, 0xABCD, 0x1223, 0x1111, 0x2222, 0x3333, 2191, 738, + -242, 308, 1411, -322, 603, 197, -1972, 2191, + 738, -242, 308, 0, + + 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, + 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, +}; + +const short k_IIR[NK_IIR] = +{ + -13839, 22437, -27054, 19741, + -16792, -30550, -25856, 6973, + -13839, 22437, -27054, 19741, + -16792, -30550, -25856, 6973, + -13839, 22437, -27054, 19741, + -16792, -30550, -25856, 6973, + -13839, 22437, -27054, 19741, + -16792, -30550, -25856, 6973, +}; + +int b_c_IIR[NK1_IIR + 2*PAD_IIR] = +{ + 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, + 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, + 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, + 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, + + 0x000A0000, 0x00050000, 0x00A00000, 0x00110000, + 0x00340000, 0xF6B50000, 0x003C0000, 0xFFE10000, + 0x009D0000, + + 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, + 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, + 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, + 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, +}; + +#define NCOEFS_IIRSS (64) +#define PAD_IIRSS (8) +#define SFB (16383.5) +#define N_IIRSS (128) +#define T_IIRSS (NCOEFS + PAD) +/* ======================================================================= */ +/* Initilized arrays with fixed test data */ +/* ======================================================================= */ +short ptr_Coefs[NCOEFS_IIRSS + 2 * PAD_IIRSS] = +{ + 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, + (short)(-2.0*SFB), (short)(1.0*SFB), + (short)( 1.4*SFB), (short)(-0.74*SFB), + (short)( 2.0*SFB), (short)(1.0*SFB), + (short)(-1.4*SFB), (short)(-0.74*SFB), + (short)(-2.0*SFB), (short)(1.0*SFB), + (short)( 1.4*SFB), (short)(-0.74*SFB), + (short)( 2.0*SFB), (short)(1.0*SFB), + (short)(-1.4*SFB), (short)(-0.74*SFB), + (short)(-2.0*SFB), (short)(1.0*SFB), + (short)( 1.4*SFB), (short)(-0.74*SFB), + (short)( 2.0*SFB), (short)(1.0*SFB), + (short)(-1.4*SFB), (short)(-0.74*SFB), + (short)(-2.0*SFB), (short)(1.0*SFB), + (short)( 1.4*SFB), (short)(-0.74*SFB), + (short)( 2.0*SFB), (short)(1.0*SFB), + (short)(-1.4*SFB), (short)(-0.74*SFB), + (short)(-2.0*SFB), (short)(1.0*SFB), + (short)( 1.4*SFB), (short)(-0.74*SFB), + (short)( 2.0*SFB), (short)(1.0*SFB), + (short)(-1.4*SFB), (short)(-0.74*SFB), + (short)(-2.0*SFB), (short)(1.0*SFB), + (short)( 1.4*SFB), (short)(-0.74*SFB), + (short)( 2.0*SFB), (short)(1.0*SFB), + (short)(-1.4*SFB), (short)(-0.74*SFB), + (short)(-2.0*SFB), (short)(1.0*SFB), + (short)( 1.4*SFB), (short)(-0.74*SFB), + (short)( 2.0*SFB), (short)(1.0*SFB), + (short)(-1.4*SFB), (short)(-0.74*SFB), + (short)(-2.0*SFB), (short)(1.0*SFB), + (short)( 1.4*SFB), (short)(-0.74*SFB), + (short)( 2.0*SFB), (short)(1.0*SFB), + (short)(-1.4*SFB), (short)(-0.74*SFB), + 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; + +#define R1 (16) +#define C1R2 (16) +#define C2 (16) +#define R1C1 (256) +#define R1C2 (256) +#define R2C2 (256) + +/* ======================================================================== */ +/* Initialized arrays with fixed test data. */ +/* ======================================================================== */ +const short MAT_x[R1C1] = +{ + 0x453E, -0x321D, 0x2DBB, 0x77C7, -0x57B9, -0x4ADD, 0x10B7, -0x113F, + -0x1A92, 0x7CA7, 0x4A14, 0x719D, 0x3E61, 0x1858, -0x0D4C, 0x3D94, + -0x32B8, -0x14B2, 0x1B6A, 0x7A1D, 0x0D5B, 0x1D2C, 0x55D8, -0x5459, + 0x5030, -0x5CBD, 0x0180, 0x059B, 0x4D97, 0x49E3, 0x68A4, -0x3629, + -0x7AA5, -0x582E, 0x1D05, 0x3A65, -0x4734, 0x3D6B, -0x6CE3, 0x4A99, + 0x1D54, -0x50B4, 0x62F5, -0x75A7, -0x6AFA, 0x5D26, 0x3C1A, -0x793D, + -0x6493, 0x4282, -0x0020, 0x1BE0, 0x1A7F, 0x621B, -0x1C86, -0x254E, + -0x12FB, -0x4E5B, 0x3409, 0x223E, 0x3856, -0x4179, -0x60C9, -0x102C, + 0x5EB6, -0x097B, 0x7A6E, 0x1450, -0x41CD, -0x133A, 0x0358, -0x2677, + -0x0BA0, 0x6732, 0x19A5, -0x4961, -0x1E47, -0x6657, 0x57C6, 0x1E70, + 0x1F12, 0x59F9, 0x13A4, 0x16D9, 0x26E6, -0x4FE0, 0x39FA, -0x6AF4, + -0x2829, -0x673F, 0x7460, 0x57A6, -0x5BB4, 0x424C, -0x6068, 0x2CC9, + 0x0F61, -0x4030, -0x00AD, 0x6AE1, -0x4FD3, 0x56ED, 0x2FDA, -0x759C, + -0x726F, 0x78E3, 0x42DF, -0x63D3, -0x1F88, -0x71D0, 0x07E8, -0x6D4A, + 0x1FAE, 0x1489, 0x1EC9, -0x6F5E, 0x5BE8, -0x024A, 0x75B7, 0x2217, + -0x2EB6, 0x4D81, 0x0757, 0x254F, -0x7FCC, -0x6A05, 0x65AE, -0x5AC9, + 0x5D3B, 0x4219, -0x47E8, 0x4A2C, -0x03AD, 0x6576, 0x00D7, 0x7AA6, + -0x0016, -0x2FEE, 0x55CB, 0x1E2C, -0x32AC, 0x2494, -0x4F3C, -0x6FFF, + 0x0826, 0x4087, -0x4C0A, 0x2E16, 0x4CEB, -0x6DE1, -0x03EC, 0x0BC2, + -0x484A, -0x2E04, 0x7E82, 0x4FAD, -0x55DF, -0x6293, 0x5530, -0x4875, + 0x5E20, 0x7DB6, -0x516A, -0x47EE, -0x4EC0, -0x3429, 0x2649, -0x3754, + -0x3F41, -0x00AD, 0x37BA, 0x5271, -0x3CFA, -0x1F8B, 0x2494, -0x371C, + -0x51F4, 0x1E9F, -0x0CCB, 0x59E3, 0x180D, -0x38F2, -0x2132, -0x2B94, + -0x17D1, 0x31A9, -0x275A, 0x2993, 0x417D, -0x49B1, -0x750B, 0x123F, + 0x3CCC, -0x18E2, 0x61E9, 0x5E28, -0x1D06, -0x68BA, 0x1647, 0x6698, + -0x18EE, 0x50D8, 0x4231, 0x2468, -0x4A2F, -0x4FED, 0x7584, 0x6DC2, + 0x3008, 0x23BA, 0x5366, -0x2ADE, -0x379A, -0x751F, 0x3367, -0x4DE8, + 0x4A1C, 0x42C4, -0x3A38, -0x34B1, -0x031A, 0x161B, 0x3F68, 0x244D, + 0x75F3, -0x7695, -0x7439, 0x797D, -0x3AD0, 0x18E2, -0x0248, -0x2D0D, + 0x5974, -0x31D6, 0x0D25, -0x3A8C, 0x2907, -0x343B, -0x6A7F, -0x24C1, + -0x56E9, 0x2A61, 0x1653, -0x66E7, -0x0081, -0x3549, -0x7E9C, -0x52ED, + 0x21E5, -0x6C4D, -0x0072, 0x0EEE, 0x749D, -0x4622, -0x2AF7, -0x3A2B, +}; + +const short MAT_y[R2C2] = +{ + 0x126C, 0x3DE7, -0x754D, 0x360C, -0x2589, -0x2234, -0x2DAF, -0x7E1F, + 0x022A, -0x4C8A, -0x34A6, 0x2A23, -0x5A1A, 0x4B95, -0x0317, 0x7430, + -0x7091, -0x0CC1, -0x0A3E, -0x7AFE, 0x645A, -0x50BD, 0x0909, 0x6090, + 0x34AE, -0x56B3, -0x3AA9, 0x438B, 0x1C64, 0x62BE, -0x5E6A, 0x7A07, + 0x0D08, 0x6089, -0x5D4D, 0x0B27, 0x4A2C, 0x79F5, 0x5A86, 0x4061, + -0x4411, -0x6674, 0x19FC, 0x7F77, -0x4EBE, 0x0E21, -0x5D11, 0x72BE, + 0x2232, 0x4040, 0x3DA5, -0x1736, 0x10DD, -0x192A, -0x768A, 0x770A, + 0x1261, -0x788B, -0x2778, 0x4989, -0x4999, 0x7905, 0x6F1E, 0x184B, + -0x3C6D, 0x1543, -0x6F94, -0x3588, -0x0D80, 0x57D4, -0x728A, -0x5E27, + 0x4092, -0x59A4, -0x2322, -0x762C, 0x684B, -0x0AA5, 0x5F2B, 0x5F6B, + -0x5CA5, -0x01CC, -0x1F8D, -0x35A1, 0x432A, -0x35C6, -0x0E0F, -0x7FEF, + 0x3D0B, 0x3D0B, 0x2B67, -0x7BC7, 0x48D5, -0x1FE3, 0x0ADA, 0x4F02, + -0x69DF, -0x6226, 0x4E99, 0x52AC, -0x322F, -0x4CF2, 0x34FE, -0x26B0, + 0x512C, -0x7CE4, 0x59F0, -0x4137, -0x7CBE, -0x7F4B, -0x5471, -0x1A85, + -0x0F38, -0x0883, 0x3513, -0x0813, 0x322B, -0x1C8F, 0x2643, 0x59E8, + 0x7410, 0x7F60, -0x1D73, -0x27DB, 0x48FD, -0x1AAB, -0x7DD7, -0x0BD5, + -0x1CA4, 0x524B, -0x71B5, 0x5C6E, 0x4C92, 0x6100, 0x4ED3, 0x7244, + -0x5594, -0x12C8, -0x6F88, 0x6EDB, 0x3284, -0x36A5, 0x33E6, 0x05AC, + -0x1E10, 0x13B5, 0x49C1, 0x1399, -0x721F, 0x5033, 0x430D, 0x3B48, + 0x6B6D, 0x18FB, -0x2711, -0x0233, -0x5DBB, 0x6FB3, 0x2341, 0x3640, + -0x027C, -0x5C31, -0x4715, 0x795B, 0x5C52, -0x3241, 0x1380, 0x50AE, + -0x0365, -0x42AD, 0x3917, -0x4178, 0x2082, -0x7CCF, -0x222D, 0x1931, + 0x46E0, 0x4CAF, -0x1DED, -0x6482, 0x7B64, -0x340E, -0x623A, -0x4B9A, + 0x0077, -0x7C9D, 0x0411, -0x3E67, 0x6FA9, 0x3843, 0x5D37, 0x7640, + 0x021C, 0x52D1, 0x3649, -0x0232, -0x5179, 0x2204, -0x06FF, -0x20F1, + -0x4878, -0x59D2, -0x42CF, 0x5DE2, 0x0334, 0x305C, -0x5CC4, 0x0208, + 0x338C, 0x74B7, 0x4AA6, -0x2CC7, 0x0256, -0x7E98, -0x46AF, -0x5D0B, + 0x6BD0, 0x1578, 0x5DCD, 0x0E96, 0x0CCB, -0x23C8, 0x7A56, -0x5FD6, + 0x5AA2, 0x13A3, -0x4913, -0x6E7F, 0x0E97, 0x1045, 0x1310, -0x4AF4, + 0x6109, 0x2E24, 0x0194, 0x09EE, -0x7CEC, -0x5FDA, -0x13D6, 0x68D8, + -0x1CF3, -0x5984, -0x3410, -0x1BDF, -0x50A2, -0x5676, 0x3DBA, 0x45A4, + -0x2D4B, -0x1563, -0x5F28, -0x7754, -0x44D3, -0x030A, 0x6E31, -0x67CF, +}; + +#define NTABLE (9*256) +#define NerrCoefs (9) +#define GSP0_TERMS 9 +#define GSP0_NUM 256 +#define PAD_MINERR 16 + +/* ======================================================================= */ +/* Initilized arrays with fixed test data */ +/* ======================================================================= */ +const short GSP0_TABLE[GSP0_NUM*GSP0_TERMS ] = +{ + 0xFF66, 0xFFFE, 0x0164, 0x0009, 0xCC13, 0x0000, 0x0000, 0x045E, + 0xEADA, 0x0A2C, 0x057E, 0x0486, 0xE076, 0x0002, 0xFFFF, 0xF452, + 0x007D, 0x0002, 0x0002, 0x0003, 0xFFC5, 0x001F, 0xFD7F, 0xFFFE, + 0xFE2C, 0xFFFA, 0x000C, 0xFFFE, 0x00AB, 0x00EB, 0x0000, 0xFBBE, + 0x0000, 0x00DD, 0xFB44, 0xFFFC, 0x0008, 0x000D, 0x00AC, 0x0000, + 0xFFE4, 0xE48D, 0xFFFF, 0x0027, 0x0000, 0x0000, 0x0001, 0x3C30, + 0x0000, 0xFFFF, 0xFF26, 0xFFFC, 0x0A53, 0xFFFA, 0x0030, 0xFF5E, + 0xFEA7, 0x00EF, 0xFEF8, 0xFF55, 0xFE71, 0x01F2, 0xFE33, 0xFD31, + 0xFC72, 0xFE37, 0x03A4, 0x0001, 0xF97B, 0x0003, 0xFFFE, 0xFFFF, + 0xFFF5, 0x0003, 0xDA57, 0x53E8, 0xFFE9, 0x0007, 0xFFD6, 0x00A4, + 0x0000, 0x05C6, 0xFFF8, 0xFFFF, 0xFFFF, 0xFE85, 0xFFFD, 0xF629, + 0x0001, 0x0005, 0x35C1, 0xFF86, 0xC1DF, 0x009D, 0x0015, 0xFC00, + 0xFAD2, 0xFFFE, 0x006F, 0xE745, 0xFFD0, 0xFC23, 0xFD66, 0xFFFB, + 0x2CBB, 0x0017, 0xE51D, 0xFFF9, 0xE267, 0xFFFE, 0x02A7, 0xF9BC, + 0x3EBC, 0x15EA, 0x0D7C, 0xFF82, 0xFF2A, 0x0000, 0x00B5, 0xFFFF, + 0xFE70, 0xFFFE, 0x0D97, 0x0D96, 0xFFFE, 0xFFDE, 0x00E0, 0xF88B, + 0xFFFE, 0xF140, 0xFE88, 0x04BF, 0x4B97, 0xFFC4, 0xF936, 0xFCFC, + 0xFFF8, 0xF141, 0xFFFF, 0x0015, 0xFFFE, 0x1AA3, 0x0005, 0xFE62, + 0x0B3A, 0x0000, 0xFFFE, 0xFFF9, 0x9E99, 0x0027, 0xFE60, 0xFFFC, + 0xFFFC, 0xD895, 0x0159, 0xFF97, 0xFF85, 0xF5D2, 0xFB71, 0x03A3, + 0xF971, 0x0000, 0xF657, 0xBB75, 0x015C, 0xFFFF, 0x0000, 0x0018, + 0x0006, 0x0001, 0xFE12, 0xF921, 0x001E, 0xFFB3, 0x0002, 0xFFFF, + 0xFFFD, 0x0003, 0x006F, 0x01ED, 0xFF94, 0x0000, 0x0574, 0xFFFD, + 0x00CF, 0x004C, 0xFFFF, 0xE0F5, 0xFB5F, 0x0632, 0xFFFF, 0xFFC4, + 0xFDAE, 0xEF70, 0x0007, 0x0589, 0xE7F9, 0x9AE1, 0xFFFD, 0xFFFC, + 0x000B, 0x0000, 0xFF82, 0x059C, 0xFE96, 0xA45E, 0xF56D, 0xFFFF, + 0xFE8C, 0x03A0, 0xF128, 0xFCE8, 0xFFF7, 0x0000, 0xFFEA, 0xFFD5, + 0x0007, 0xFFFE, 0xFFEA, 0xE552, 0xFEAD, 0xFE83, 0xFFFE, 0x0065, + 0x01DB, 0x02E2, 0x0037, 0x051F, 0x0C6E, 0xFFC4, 0x0001, 0xFFFE, + 0x0773, 0x028D, 0x0001, 0xFFF2, 0xF41E, 0x08C9, 0x0059, 0xFFFE, + 0xFFF4, 0x0000, 0x000E, 0xFFFE, 0xFFBE, 0x0007, 0xFFF3, 0xFFEB, + 0x0048, 0x1FB1, 0xFB20, 0x01E1, 0x003D, 0xFFFD, 0xFFFE, 0x0003, + 0xE231, 0xE116, 0xFFFE, 0x0000, 0x07ED, 0xFFFF, 0x0002, 0x0001, + 0xF74C, 0xFFFA, 0xF100, 0xFFFC, 0x045F, 0xFFF0, 0x00E5, 0xF324, + 0x004C, 0xFFFD, 0x1B1E, 0xE5A2, 0xFD54, 0xFFA6, 0xFF78, 0x001E, + 0x0008, 0xF87E, 0xFFFF, 0xFFFE, 0x0001, 0x0000, 0xFFE8, 0x0027, + 0xFFFB, 0xBFA3, 0xFFE0, 0x071D, 0xE163, 0x0544, 0xFFED, 0x195F, + 0xFFFF, 0xFFFF, 0x0003, 0x0001, 0x0038, 0x0049, 0xFF06, 0xFFFE, + 0x003B, 0xFFFF, 0xFFF4, 0x008B, 0xEF2E, 0xFF8E, 0xFFF9, 0x020E, + 0xFFF8, 0x0000, 0x00EC, 0x17EB, 0x0014, 0x1261, 0x0ECC, 0x17F0, + 0x0073, 0xFFE5, 0x001F, 0x0713, 0xFF94, 0x0000, 0x41CA, 0xFFFF, + 0xFE2F, 0x00E5, 0x0008, 0x0509, 0xFFF1, 0xFD8A, 0x06C8, 0xFDE3, + 0xFFFA, 0xFF3B, 0x0024, 0xFFF7, 0xF353, 0xFFF4, 0x009F, 0x0D81, + 0x0486, 0x0407, 0xEA8E, 0x0083, 0x000A, 0xFFE4, 0xFFFC, 0x3562, + 0x0227, 0x44DE, 0xFFF3, 0xFEC6, 0x0002, 0xFFC6, 0xFFFF, 0x0681, + 0xFFFE, 0xFF5F, 0xFE14, 0xFF37, 0xFFE1, 0xFFFC, 0x0125, 0xFEE6, + 0x0018, 0xFFFC, 0x004C, 0x0001, 0xFEBC, 0xFEE5, 0x05BE, 0x01C1, + 0xD7C7, 0xFFFD, 0xFFFA, 0xD7FD, 0xFFFE, 0x0000, 0xFFF5, 0x4BF6, + 0xEBFE, 0x0035, 0x0003, 0xFFFE, 0xFCC1, 0xFFE4, 0x0001, 0x00BD, + 0x333B, 0x00DB, 0x57D6, 0x0000, 0x000E, 0xFFDD, 0x2446, 0x000D, + 0x0005, 0xFF7B, 0xCDFC, 0xFFF9, 0x0011, 0xFFC5, 0xFFFC, 0xFFFF, + 0x0380, 0xFF72, 0xFFFC, 0x0025, 0x364C, 0x77F5, 0xFFFF, 0x131B, + 0xFFFF, 0x0001, 0xFFFC, 0xFFF8, 0x001B, 0x2750, 0xFFFF, 0x1CD9, + 0xFF5D, 0x03F5, 0xFFFC, 0xFD02, 0x0000, 0xFFC8, 0x0072, 0xFD46, + 0x0027, 0x00DF, 0xFF08, 0xE255, 0x0001, 0x2733, 0xFEDE, 0xFFE2, + 0xFFFF, 0xFFBB, 0x0000, 0xFFFE, 0x0030, 0x0002, 0x0001, 0xFFFC, + 0x0246, 0x0009, 0xFFF8, 0x0FB1, 0xF9F3, 0x000E, 0x02C8, 0xFFD6, + 0x7555, 0x0416, 0x0002, 0x0000, 0xFA57, 0x00BE, 0xFF99, 0xFD25, + 0xFFFF, 0xFFFC, 0xCE61, 0x011D, 0xFFFD, 0x0000, 0xF9E0, 0xFFE9, + 0x03E5, 0xFFF2, 0xFFE1, 0x0002, 0x02F1, 0x01F8, 0x0027, 0xF0CE, + 0x7A3D, 0x1798, 0x0025, 0x0000, 0x0000, 0xFFFA, 0x19EC, 0x197F, + 0x0025, 0xFFFB, 0x7DB3, 0x427B, 0x0002, 0xFFFC, 0xF62A, 0xFFE1, + 0xFE1B, 0x0002, 0xFFFF, 0x0000, 0xFFEB, 0xF8F9, 0x0032, 0xFF93, + 0x1568, 0xFFFF, 0x0000, 0x0002, 0x0018, 0xFDA6, 0x00FD, 0x0036, + 0x04B3, 0x0001, 0xFFFB, 0xFE49, 0x0001, 0x00B2, 0xFFC2, 0xE5F9, + 0xFFF8, 0x0000, 0xFA7D, 0xFFCE, 0xFF89, 0xFFFE, 0xF6C3, 0xFFFF, + 0xFF94, 0xFFFF, 0x0280, 0x00DD, 0xFFFE, 0x00C3, 0xF7EC, 0xF75E, + 0xF2D6, 0xFD39, 0xFFFF, 0xFFFE, 0xFC15, 0xFFC0, 0x0025, 0x001A, + 0x006E, 0xFFD1, 0xFFF7, 0x0494, 0x0011, 0xF919, 0x11F2, 0x0741, + 0x35F5, 0x0253, 0x0005, 0xE546, 0x0003, 0xE740, 0xFFFE, 0xFF03, + 0x0004, 0x014E, 0x041F, 0x0A16, 0xFFF5, 0x0EC0, 0x0000, 0xFC40, + 0x086C, 0x0055, 0x23B8, 0xFFFE, 0xFFF2, 0xE1EE, 0x0000, 0xFC9E, + 0xFFFC, 0xFFF5, 0x1C21, 0xFC7E, 0x0126, 0xFFCA, 0xFFFB, 0x01B2, + 0x0000, 0x0F95, 0xFFCD, 0x0006, 0x0000, 0x00B9, 0x00AE, 0x0003, + 0xFFEC, 0xFFFD, 0xFBAE, 0xFFFD, 0x05C7, 0xED4E, 0xFFFE, 0x0003, + 0xFFFE, 0xFFFD, 0xFFFE, 0x2825, 0x0005, 0xFFFA, 0x0009, 0xFF55, + 0xFF90, 0x002C, 0xFF5C, 0xE178, 0x0021, 0x00BC, 0xFFFF, 0x0018, + 0x000B, 0x04E5, 0x001D, 0x0002, 0x0FDF, 0x3549, 0xFB2C, 0xCA86, + 0x1A7D, 0xE4C1, 0xFFFF, 0x0038, 0xFFF1, 0x0005, 0x0034, 0x0198, + 0x0001, 0xFF8A, 0xFFB0, 0xFFFC, 0xFFFF, 0xFFFF, 0xF626, 0x0EBD, + 0xF924, 0x0000, 0x001B, 0xFFF8, 0x0703, 0x01F0, 0xFFF4, 0xFFF0, + 0x0008, 0x0000, 0xFE92, 0x0ADD, 0xFF05, 0x0067, 0xFFEC, 0x011D, + 0xFFFF, 0xFFF4, 0x0020, 0xFFCB, 0x0BEC, 0xFF9F, 0xFF99, 0xFFCF, + 0xF1D9, 0x4CC1, 0x1264, 0x0002, 0xDCBE, 0xF984, 0x3B0D, 0x026F, + 0xFFF6, 0x3A06, 0xFBEA, 0xFFFD, 0x0018, 0xFFE7, 0x0030, 0x27F4, + 0x0001, 0x016E, 0xFF26, 0xFFFE, 0xFFFA, 0xFFFD, 0xFFFD, 0x1E68, + 0x000B, 0xFFFF, 0x0001, 0xFE44, 0xCB0A, 0xFFFE, 0xFFF7, 0x0002, + 0x1C77, 0xF3B2, 0x0000, 0x0013, 0xFFC5, 0xFFFE, 0xF543, 0xFFF7, + 0xFFFF, 0x0013, 0x02BA, 0xFFF8, 0x0002, 0x02BC, 0xFFFF, 0x01BB, + 0x09FA, 0x04FE, 0x001F, 0xFCB2, 0xE888, 0xFFFC, 0x0000, 0xFF9E, + 0xFFF9, 0x0006, 0x0003, 0xF3D4, 0x0007, 0xFFFF, 0xFFFA, 0x003A, + 0x0000, 0xFFFE, 0xFFFF, 0x0001, 0xF9F1, 0x048D, 0xFFD9, 0x0021, + 0x0001, 0x0C71, 0x2F65, 0x0072, 0x0004, 0xFFFF, 0x011A, 0xFCA1, + 0x011A, 0x0015, 0x0002, 0x0019, 0xFFF8, 0x0A31, 0xFFFF, 0x1AC7, + 0xFFFE, 0x083B, 0x09AF, 0x0024, 0xFFFB, 0x1B4D, 0xFFFC, 0x0010, + 0x09B9, 0x0219, 0xFF50, 0xFF81, 0xFD59, 0x0234, 0x003F, 0x0000, + 0x008F, 0xFFFF, 0xFE52, 0x0080, 0x001D, 0x0000, 0x0391, 0x0001, + 0xA1AA, 0xFBAA, 0x1ED3, 0xFFFE, 0xFFF9, 0x1F99, 0x017C, 0xFFF5, + 0x0006, 0xD0A3, 0x733A, 0x0006, 0x0620, 0x0399, 0xC22C, 0xF629, + 0x00EA, 0xFFFF, 0x8F5B, 0x0017, 0x7A28, 0xFEF6, 0xFFFD, 0xFF9D, + 0x0016, 0x02D4, 0x0032, 0xFF37, 0xFFF3, 0xFF34, 0x2CB0, 0xFF2D, + 0x0000, 0x000C, 0xFF41, 0xF427, 0x1642, 0x0002, 0xFFFF, 0xEB0C, + 0xFFD0, 0xE52D, 0x4AC2, 0x001E, 0xFCC1, 0x4A7B, 0xECB3, 0xFFDB, + 0x002F, 0xF272, 0x0040, 0x03A4, 0x0001, 0x0003, 0xFFE1, 0xF862, + 0x1EC3, 0xFB78, 0x0000, 0xF49D, 0x02EB, 0xFFFE, 0x000E, 0xFCE4, + 0xFFFF, 0xE600, 0x0A6F, 0xFFFF, 0xFFF8, 0xFFFB, 0xFFFF, 0xFC04, + 0x0001, 0x0026, 0xFFD6, 0x00DE, 0xFFD9, 0xFF09, 0xFFD3, 0x001C, + 0x0001, 0xFFF2, 0xA540, 0x02EE, 0x001F, 0xFFE3, 0x0003, 0x05F6, + 0xFFF7, 0x1EA3, 0x0000, 0xFCAE, 0xFF00, 0xFFF9, 0xFFEE, 0xFFFF, + 0x000D, 0x0C73, 0xFEA0, 0x024D, 0xFFC1, 0x0000, 0xFFEC, 0x0004, + 0x9255, 0x0008, 0x0900, 0x0000, 0x0056, 0x001A, 0xE9E1, 0x0116, + 0xF702, 0xFF8E, 0xFFE9, 0xFEFF, 0x002F, 0xFFFF, 0xFFF5, 0x009C, + 0x00DC, 0x8701, 0xFFE8, 0xFEF3, 0xF77A, 0x0006, 0x00AD, 0x0003, + 0x0000, 0x0000, 0x0052, 0x0019, 0x0000, 0xFFFF, 0xFF7B, 0x1B8B, + 0xFFFF, 0x11A6, 0xFFE9, 0xFFBE, 0xC35A, 0x0000, 0xFF23, 0xF5F9, + 0x001C, 0x0007, 0xFAA2, 0x0000, 0xFE74, 0xFFFE, 0xFFFF, 0xFFCF, + 0xFFEF, 0xFFFE, 0x0025, 0x0000, 0xFFFE, 0xFF74, 0x0000, 0xC26B, + 0xFFFF, 0xF814, 0x0004, 0xFE77, 0x0000, 0x0025, 0x0001, 0x000B, + 0x0000, 0xFDE7, 0xF0A0, 0x00A7, 0x0003, 0xFFF2, 0x2053, 0x0001, + 0x0003, 0x0042, 0xF6D3, 0xFFF2, 0xFB3F, 0x0019, 0xFFF9, 0xEA0D, + 0x001C, 0x1863, 0x1849, 0x04E7, 0x0010, 0xE948, 0x0000, 0xFFFF, + 0xFFFF, 0xF176, 0x5F8A, 0x0000, 0x0001, 0x0019, 0xFE4C, 0x0322, + 0xFFE8, 0x00C5, 0x1C9A, 0x0000, 0xFAC4, 0xDE12, 0x099E, 0x0001, + 0xFFDD, 0x0000, 0x001C, 0xFC66, 0xF152, 0xFFF1, 0x0005, 0x003D, + 0xFFFF, 0xF8AC, 0xFEA6, 0x00B8, 0xFFFF, 0x009B, 0x0012, 0xFFFF, + 0xFFD8, 0xFE5D, 0xE84B, 0x000A, 0xE287, 0xFFD5, 0xF884, 0x0010, + 0xFFF9, 0x0002, 0xFFEC, 0x0002, 0x0002, 0x1E8A, 0xFA99, 0xFFAE, + 0x0000, 0x0185, 0xFFF2, 0xFFF2, 0xFFFF, 0xFFB4, 0xFFF2, 0x0006, + 0x03F3, 0xFFFE, 0x002C, 0x0696, 0x02A8, 0x0003, 0xFE9B, 0x0000, + 0xFFFF, 0x0069, 0xFD6E, 0xFFFE, 0xFFFF, 0xFFCC, 0x02A1, 0xFD29, + 0x09F8, 0xFEEF, 0xFFFE, 0xFFFF, 0xFA15, 0xFFFC, 0x0180, 0xFFD0, + 0xFFFE, 0xF3CA, 0xE42D, 0xFFFE, 0xFFFB, 0x003C, 0x0000, 0x0000, + 0x0003, 0x042A, 0x0FB0, 0x0000, 0xEFDB, 0x0024, 0xF36A, 0x0009, + 0xCA11, 0xFAE5, 0x1328, 0xFFFD, 0x203C, 0x0003, 0x0003, 0x0200, + 0x0003, 0xFF5C, 0xFF3E, 0x003B, 0xD5AF, 0x0000, 0x0065, 0xFE4A, + 0x0B6F, 0x0057, 0x02A5, 0x0000, 0x01E1, 0xFFF8, 0x3370, 0x0019, + 0xFFAA, 0xFFF3, 0xE0D5, 0x0177, 0x0000, 0xFFD2, 0xFFE1, 0x0011, + 0xFF0D, 0x0173, 0xF924, 0x004B, 0x0012, 0x0E1D, 0xFFFE, 0xFF1A, + 0x03C9, 0x003E, 0x0000, 0xFDE0, 0x0000, 0x0004, 0x0E1B, 0x005B, + 0xFF8E, 0x0017, 0xFA51, 0x02D0, 0xFFDA, 0xFFF1, 0xFFF7, 0xFFFF, + 0xFEFF, 0x39C2, 0x0000, 0xE2F3, 0x1BEF, 0x0002, 0x0056, 0xFFF4, + 0x029C, 0x0012, 0xCE2B, 0xFF6C, 0x0037, 0xFA03, 0x05D5, 0x0008, + 0xFFDD, 0x0000, 0x000C, 0x0220, 0xFDB3, 0xF5DD, 0xFFF1, 0xFFB2, + 0x000E, 0xFFFF, 0xFFD6, 0xFF96, 0xFFFE, 0xFFFE, 0xFE59, 0xC0EB, + 0x19C0, 0xFFEC, 0xFFF8, 0xFFF9, 0xFFFE, 0x0000, 0x0026, 0xDB9D, + 0x0004, 0x15F2, 0xFFC3, 0xFFC4, 0x29B3, 0xFFFB, 0xFFF6, 0xFFDE, + 0xFD6B, 0xC829, 0x0250, 0xE604, 0xFFFF, 0xFF37, 0xF3BE, 0x005C, + 0x5386, 0xFE90, 0xFF19, 0xFFF8, 0x0B38, 0x00D5, 0x24EE, 0x044D, + 0xFFB2, 0xFFEC, 0x0D0D, 0xFFE9, 0xFDCD, 0xFFFE, 0x02A5, 0xFFFF, + 0x0001, 0xFE70, 0xFFFF, 0xFDBE, 0xFE5D, 0x0FF1, 0x0095, 0xFC6F, + 0x000C, 0xEDC1, 0x8AB1, 0xC5EB, 0xFFFF, 0x0354, 0x009F, 0x0000, + 0xFF6E, 0x000E, 0x00CF, 0x0005, 0xFFFF, 0xFFFB, 0x0002, 0xF36D, + 0xFFFE, 0x12D8, 0x0388, 0x00EC, 0x0003, 0x2D66, 0xFA50, 0xFC80, + 0xFFFD, 0xEA26, 0xEBB7, 0x0261, 0x0000, 0x0009, 0x0001, 0x0468, + 0xFFFD, 0x3526, 0x022C, 0x0227, 0xFFFD, 0x0051, 0x0008, 0x6F38, + 0xFFFE, 0x0001, 0xFF21, 0xA428, 0x0000, 0x239A, 0x0000, 0x002D, + 0x00EB, 0x000A, 0xFDE0, 0x0004, 0xFFFE, 0xF22A, 0xFFFF, 0x0000, + 0x0001, 0x0001, 0xF700, 0xFFBD, 0x16EB, 0x0007, 0xFC28, 0xF677, + 0xFF55, 0xFFEA, 0x0000, 0xFC6C, 0xFFF9, 0xFFC4, 0xFFFE, 0xE6ED, + 0x1CE0, 0x011C, 0x0035, 0xFFFE, 0x0007, 0xFFAA, 0xFFF4, 0x0FBF, + 0x3516, 0xE8EE, 0xFFFB, 0x3CC5, 0x30FB, 0x0001, 0x0000, 0xFF63, + 0x0051, 0xFFFE, 0xF8E4, 0xFFFF, 0xF9A2, 0xB968, 0x019F, 0xFD74, + 0xFFEC, 0xF888, 0xF966, 0x036D, 0xFFF8, 0xFFC0, 0xF64B, 0xFFFF, + 0xFFA5, 0x0012, 0x0E31, 0x0056, 0xF89C, 0xFFF0, 0x01F3, 0x0005, + 0x0001, 0xFFE6, 0xFEB4, 0x000E, 0xF062, 0x01DC, 0x05F2, 0xFC43, + 0x00E5, 0xFD5A, 0xF0C6, 0x0221, 0x070C, 0xFFFE, 0xFFC8, 0xFFFF, + 0x0029, 0x01F2, 0xFE19, 0xFFE8, 0xFFFF, 0x0000, 0xFFE9, 0x003C, + 0xFFFD, 0xFCBA, 0xFEAA, 0xFBD9, 0xE47B, 0x0174, 0xFFBE, 0xE13D, + 0xFFFF, 0x001D, 0x0014, 0x49CB, 0xFFFB, 0x40A4, 0x0813, 0x033E, + 0xA69F, 0x3D97, 0x0667, 0xFFFF, 0xFD9D, 0x00F4, 0x0069, 0xFDB3, + 0xFFC5, 0xE5B1, 0x00AF, 0x54EB, 0xFFF4, 0x0001, 0x10EB, 0xDB1B, + 0xFFFE, 0xFFAD, 0x005E, 0x76A4, 0xFFFC, 0x0031, 0x001B, 0xFFE0, + 0x06D2, 0x0278, 0xFFE0, 0xFE11, 0xFFF1, 0x001C, 0x1B38, 0xFFFE, + 0x0000, 0xFFEE, 0xFFFF, 0xFF92, 0x2C96, 0x066D, 0x1BAF, 0x04BD, + 0xFFDD, 0x060C, 0x02D1, 0xFF0A, 0x0A69, 0xFFFF, 0xF8CC, 0xFF6E, + 0xFE64, 0x001F, 0xFD79, 0x0000, 0xFFED, 0x05CF, 0x0001, 0x002A, + 0xFF4F, 0x00A9, 0xF98B, 0xFFF7, 0xFFFC, 0x0348, 0xDEF2, 0x0053, + 0xFFDF, 0x0005, 0x0000, 0x0351, 0x001E, 0xFFAB, 0x0033, 0xFFFA, + 0x0007, 0xFFA8, 0xD1E2, 0xE116, 0x1486, 0xFF40, 0x1A3B, 0x0004, + 0x00A5, 0x0018, 0x0A5D, 0xFFCD, 0xFFFD, 0x0005, 0xFF34, 0xFFFE, + 0xDB6D, 0x001F, 0x044B, 0xFFCC, 0xFCB1, 0x574D, 0xFFFE, 0x0000, + 0x019E, 0xF35A, 0x3A3B, 0x0B5D, 0x218B, 0x0001, 0xFFC3, 0xF716, + 0xFFFF, 0x03CB, 0x0029, 0xFFF9, 0xFDF5, 0x05BB, 0x020D, 0xF844, + 0xC8F0, 0x0971, 0xF198, 0x0007, 0xFFF8, 0xFD64, 0xAE6C, 0x20A3, + 0x1899, 0xFDDE, 0xFFF7, 0x1A24, 0xFFFF, 0xFFFD, 0x0189, 0xD62C, + 0x0164, 0xF6FC, 0xFFEF, 0xFD6A, 0x4D30, 0xFCF7, 0xF612, 0x0012, + 0x0000, 0xFEB6, 0x02AF, 0x0000, 0xFFCD, 0xFFF6, 0xF71F, 0xF881, + 0x0001, 0x0004, 0xFF9F, 0x000D, 0x0001, 0x06F2, 0x0000, 0xFFF5, + 0x016F, 0xFFFF, 0x062F, 0xFC46, 0xEFEA, 0xF91C, 0x0002, 0x0003, + 0xD301, 0x05BC, 0xFFFE, 0xFFF2, 0x0003, 0x3825, 0xF4A2, 0xFFFE, + 0xF869, 0xFFFF, 0xFF96, 0xFFB5, 0xFB42, 0xEFA9, 0xFFFF, 0x0000, + 0xFFFC, 0x1076, 0x0000, 0xF05D, 0x0066, 0xF5EF, 0x0000, 0xFFF7, + 0xFFFF, 0xFFF3, 0xFFFE, 0xF847, 0xF702, 0x0010, 0xFFFB, 0xFE64, + 0xFFF3, 0x0000, 0x03F6, 0xE8F6, 0xFFFE, 0x0000, 0xFFE1, 0xFFFF, + 0xFFFF, 0x0120, 0x0000, 0x0000, 0xB852, 0x0250, 0xFFFF, 0xFFCC, + 0xFFFC, 0x1542, 0xFFFE, 0x001D, 0xFFF0, 0xFFFE, 0xFFE8, 0xF034, + 0xFFFE, 0x0009, 0xFFE1, 0xECA5, 0x0097, 0x0000, 0x0004, 0x509D, + 0x0000, 0xFE2D, 0x0C1B, 0x024D, 0xFD38, 0xFFFF, 0x1CB9, 0xFFFF, + 0xFB5D, 0xFFFF, 0x003A, 0x0008, 0xFF3C, 0xFF99, 0x0028, 0xFFF9, + 0x03A7, 0x0002, 0x0000, 0x0000, 0x0003, 0x0130, 0x1F4C, 0x0F79, + 0x0003, 0xD43D, 0xFF44, 0x0001, 0xFF9C, 0xFF57, 0xFFFE, 0x01E3, + 0x16F8, 0x0001, 0x1C9B, 0x037C, 0xFFFE, 0x0048, 0xFFFB, 0xF5BF, + 0x01F2, 0x049E, 0x002B, 0x06F9, 0x02A6, 0xCF11, 0xF8C5, 0xFFFB, + 0xAF6A, 0x3EAD, 0xFFFD, 0x007F, 0xFFFC, 0x0004, 0x0000, 0xE00A, + 0xFFC5, 0xB899, 0x0001, 0xFF49, 0x0187, 0x0E52, 0x0000, 0x0000, + 0x0000, 0xFFED, 0x005E, 0x13E9, 0x0655, 0x053E, 0x0EE7, 0xFFFF, + 0x2C3F, 0x0000, 0xA510, 0x95FC, 0x0573, 0x5DAC, 0xFBAF, 0xFFF6, + 0xFFF5, 0x0686, 0xFE2E, 0x0000, 0x01BD, 0x0000, 0xFFFA, 0x0A07, + 0x0B7A, 0x0000, 0x000D, 0xFB87, 0xCCC4, 0xFFEB, 0xE5CF, 0x007C, + 0x001E, 0x0008, 0x0000, 0x065D, 0xE5F9, 0xF073, 0xFFF6, 0xFFF3, + 0x0162, 0xFFF9, 0x00B9, 0xD8AC, 0x000B, 0xFE97, 0xFFFF, 0x0004, + 0x0000, 0x01DE, 0x0000, 0xFFA3, 0x0000, 0x0875, 0x0000, 0x1F32, + 0x0000, 0x0049, 0x0000, 0xFFA0, 0x00B4, 0x0002, 0xF911, 0xF8BA, + 0xFB64, 0xFE3C, 0xFFD9, 0xFB1C, 0xFFDE, 0xFFE0, 0x01F5, 0xF614, + 0x0013, 0x0005, 0x091D, 0xFFFF, 0x01F9, 0xFFFD, 0xFB5D, 0x0043, + 0x0351, 0xF865, 0x38EE, 0x0001, 0x0110, 0x0000, 0x0E38, 0x0033, + 0xFF4F, 0x0004, 0x085C, 0xFF14, 0x0B1D, 0x0026, 0x029E, 0xFC4B, + 0xFFC8, 0x01B4, 0x0003, 0xD99A, 0xFD17, 0x05D8, 0xFD89, 0xFFE6, + 0x0000, 0xDD50, 0xDEA6, 0x0009, 0x0000, 0xFEA6, 0x003F, 0xFFED, + 0xF48E, 0xFFFA, 0xFFD2, 0xFA3C, 0xF968, 0x09E8, 0x5993, 0xFF9F, + 0xFFED, 0xF158, 0x0003, 0x0003, 0x0008, 0xFFF4, 0x7A88, 0x017C, + 0xFFCA, 0xFFFC, 0xFFFD, 0xCBAF, 0x0017, 0x3956, 0x0000, 0x0001, + 0xFFFF, 0xFF62, 0x0000, 0xBCF5, 0x3ACC, 0xFC21, 0x4D8E, 0xFFFE, + 0x0310, 0x2723, 0x45FA, 0x0062, 0xFFFF, 0x0050, 0x0072, 0xFFFF, + 0x1CB7, 0xFF68, 0x003D, 0xFF9D, 0xFF1C, 0x001F, 0xFFFF, 0x0002, + 0xFFFE, 0xFFFF, 0x00FB, 0xFFB7, 0xF421, 0x0010, 0xFFE5, 0x0012, + 0xFFFF, 0x02E7, 0x0000, 0xFFEE, 0xFFFA, 0x0015, 0x2792, 0xFFDC, + 0xFFFC, 0xFFFF, 0xFFFF, 0xFD1C, 0xFCFC, 0xFDB6, 0x000B, 0x0006, + 0x0613, 0xFFCA, 0xFFEB, 0xFFFE, 0xFD94, 0xCDC5, 0xFFF0, 0xFFE6, + 0x0004, 0x0003, 0x0001, 0x005A, 0x0002, 0x0001, 0xFFD0, 0xFE98, + 0x0694, 0x0000, 0xFFF8, 0x88FA, 0xFFFC, 0xF8D5, 0xFC47, 0xFF38, + 0x0012, 0xFFFF, 0x0000, 0x0789, 0xFF18, 0xECF3, 0xF4A2, 0x0027, + 0xFFB1, 0x0314, 0xFFFE, 0x001A, 0xFDB7, 0xFDBD, 0xFE1C, 0x0003, + 0x29B3, 0xD5FB, 0xFE7F, 0xFC92, 0xF745, 0xF9B5, 0xFEC4, 0x6DE2, + 0xFFFD, 0x23DE, 0xFDC9, 0x000D, 0x000B, 0xFFE4, 0x000D, 0xFB43, + 0x0026, 0x006E, 0x0B12, 0xFFFD, 0xFFFE, 0x0007, 0x025D, 0xFFFF, + 0x1EC6, 0xFE14, 0x0042, 0x0371, 0xFFFF, 0x0009, 0xA8A6, 0xF9DA, + 0xFF4F, 0xFFCC, 0x1170, 0xFFFF, 0x01BA, 0xFDC0, 0x0366, 0xFFFE, + 0x1875, 0x0005, 0xFEDB, 0xFC34, 0xFFDA, 0xFFF4, 0xFE9A, 0x3E36, + 0xFFFE, 0xD51F, 0xFFBE, 0xFF1B, 0x0964, 0x0009, 0xFFCF, 0xF37E, + 0xFF6A, 0xFFE3, 0xFFFF, 0x0005, 0xF9A5, 0x07A3, 0x0001, 0xF421, + 0xFFEC, 0xFFBB, 0xFFFE, 0x001B, 0xFE8B, 0xFFFA, 0x0023, 0x3271, + 0x0000, 0xFFFB, 0x0009, 0xFFFC, 0xFFFC, 0x0A58, 0x0000, 0x0044, + 0xD658, 0x0013, 0xFFFE, 0x0000, 0x01F1, 0x00BF, 0x0683, 0x31A6, + 0x0004, 0x0005, 0xF303, 0x0104, 0xFD1A, 0xEA53, 0x0098, 0xFFFF, + 0xFFFD, 0xFFFE, 0xFFF1, 0xFF9B, 0xFE88, 0xFFA0, 0xFFFF, 0x0016, + 0x0000, 0xFFCE, 0xFFFB, 0xB4B5, 0x0005, 0x57D9, 0x0007, 0x0003, + 0x0035, 0x0005, 0xCAAB, 0xF410, 0xE9A1, 0xFE26, 0xFFD8, 0xFFFF, + 0xFFFE, 0xFFFD, 0xFFF3, 0x283E, 0x25AD, 0x0002, 0x15B6, 0x78F2, + 0xFFCF, 0xF44B, 0xFFFF, 0x0000, 0xFF97, 0x0018, 0x0035, 0xFFF7, + 0x0011, 0xFFA1, 0xFFFF, 0xFF6F, 0x065C, 0x002D, 0xFFFB, 0xFFFE, + 0x0010, 0xFF66, 0x84EE, 0x28FF, 0xFFAA, 0xFE84, 0x01CD, 0x000D, + 0xFACC, 0x0020, 0x00B6, 0xFFFF, 0xF01F, 0x002B, 0xF0ED, 0xFFFC, + 0xFFF6, 0x02E1, 0x0040, 0x001F, 0x0061, 0xFF75, 0xAB5F, 0x0773, + 0xF6E4, 0x0011, 0xFFFE, 0xCAE8, 0x0104, 0xFFCE, 0x0004, 0x0323, + 0xFFFE, 0x00AF, 0xFE3D, 0xC32B, 0xFF04, 0x0015, 0xFBC6, 0x348C, + 0xFFC4, 0x1937, 0x37BB, 0x07F2, 0xFFF9, 0x103F, 0x0000, 0xFFD1, + 0x000A, 0xFFCC, 0x5514, 0x0906, 0xF6E8, 0x0023, 0x0000, 0xFFFB, + 0x0000, 0xF8EE, 0x0212, 0xFFFF, 0x002B, 0x03B4, 0xFFF2, 0xFFFF, + 0x0BF8, 0xFCF9, 0xFFF0, 0x0000, 0x0046, 0x0016, 0x12E8, 0xC8D4, + 0x007A, 0xFE8A, 0xFFFF, 0xFFF9, 0x0365, 0xFE4E, 0x01A7, 0x2C8D, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFB, 0xFDE4, 0x0007, 0x0817, 0x0163, + 0x056D, 0x0000, 0x0006, 0x4692, 0xFFE9, 0xFBC3, 0x072C, 0xFFFF, + 0x001B, 0xFFF9, 0x0007, 0xFFFC, 0xFFFA, 0x0002, 0x0002, 0xFFFF, + 0x0038, 0x8BFF, 0xA286, 0x046B, 0x0000, 0xE060, 0xFEEF, 0xF94C, + 0x0000, 0x03EC, 0x0007, 0xFEC0, 0x5A94, 0xFFC0, 0x00AC, 0x0188, + 0xFE46, 0xFE81, 0xFFF4, 0x07CF, 0xF28A, 0x02EA, 0xFFFF, 0x00F5, + 0xFFE5, 0xF0D1, 0xFF99, 0x000A, 0x000F, 0x09CF, 0xFFFD, 0x04C0, + 0x0002, 0x0079, 0x03C0, 0x0002, 0xFFC7, 0x04B8, 0x0015, 0xFD2C, + 0xF848, 0xFFFE, 0x0002, 0xFFF8, 0x1DFF, 0x04B9, 0x175F, 0x000B, + 0x0000, 0xFFF6, 0x0306, 0x0000, 0x0003, 0x0001, 0x0E76, 0x002D, + 0x0001, 0xCF4F, 0x30A2, 0x0007, 0xFF89, 0xFFFE, 0xFFFC, 0x0000, + 0xFFFE, 0xFFFB, 0xFFD7, 0xFFE0, 0xFFFD, 0xFFFF, 0x1A3A, 0xFFFA, + 0xFFFF, 0xFFF7, 0x0950, 0x0003, 0xFFFD, 0x000F, 0x0000, 0xAD6B, + 0x0073, 0xFF21, 0xFFCF, 0x0007, 0xE0D3, 0x0000, 0xFF65, 0x00F7, + 0x0016, 0x00CE, 0xFFDB, 0x0464, 0xFFF4, 0xFFFD, 0xFFC7, 0x0015, + 0x6726, 0xFFEA, 0x0005, 0xFE40, 0x000F, 0x0000, 0xFF86, 0x03E9, + 0xFFFE, 0xFFFB, 0x354F, 0xFFFD, 0x0000, 0x000C, 0x00F0, 0xFFFE, + 0xFE0C, 0xCA1A, 0x26FC, 0x0002, 0xFDF0, 0x0000, 0xFF93, 0xF082, + 0x1041, 0xF7B9, 0x01BD, 0x0BAA, 0x05D1, 0xFF84, 0x007F, 0xFC31, + 0xFFFF, 0x0001, 0x000B, 0xFFC7, 0xFF8F, 0x0003, 0xCDEC, 0xFFD2, + 0xB1EA, 0xFFF5, 0xFFF6, 0xFFFC, 0xE29B, 0x0007, 0x0000, 0x16C9, + 0xFC31, 0xFFFC, 0x0261, 0xFFFF, 0x1AEA, 0x00DE, 0xFC1E, 0xFFE4, + 0xFF28, 0xFE59, 0xFFFE, 0xFFE9, 0xFFFD, 0x0001, 0x0120, 0xFFFD, + 0x0000, 0xFFFC, 0xFE4F, 0xFFFF, 0x0A75, 0x096E, 0xFF93, 0xFF62, + 0xFFFF, 0xFE3E, 0xFFF1, 0xFF34, 0xFFF3, 0xF75C, 0xFFFE, 0x0001, + 0xFC7F, 0x0025, 0x0007, 0x0753, 0x00A7, 0xFFE1, 0xFD17, 0xFF90, + 0xFA43, 0x0000, 0xFFFF, 0xFF9F, 0xFFF9, 0x002F, 0x73FF, 0x0641, +}; + +const short errCoefs[NerrCoefs] = +{ + 0xFC7F, 0x0753, 0x069F, 0xFFFD, 0x1A29, + 0xEAEA, 0xAEAE, 0xAAEE, 0xFFF6 +}; + + +#define N_W_VEC (256) /* number of elements in input and output vectors */ +#define PAD_W_VEC (16) + +#define M_W_VEC (16384) + +short a_W_VEC[N_W_VEC + 2*PAD_W_VEC] = +{ + 0xD9CF, 0x0E33, 0x2ADE, 0xFE88, 0xCE0D, 0x10D6, 0x29B4, 0x3D39, + 0x0DC4, 0xE849, 0xDB6A, 0x14C5, 0x117B, 0x0C1D, 0x2321, 0x24C3, + + 0xE3B5, 0xC48C, 0x3E1B, 0xD4D3, 0x0E3E, 0xE83C, 0xEB19, 0x1A12, + 0xCD9B, 0xCE2F, 0x3F27, 0xEDA9, 0xCA97, 0x1D68, 0x2EFC, 0xD185, + 0x0B12, 0x0273, 0x2293, 0xC1F2, 0x0A24, 0xF26A, 0xD7BF, 0xF121, + 0xF42C, 0xD906, 0x3696, 0xD5AD, 0x37E0, 0x1D63, 0xCFA4, 0x0DCC, + 0xC64D, 0x21AE, 0xE57B, 0x25A3, 0x2FAB, 0x233A, 0x2A16, 0xF309, + 0xF670, 0xF0FD, 0x0361, 0x3D18, 0x01F7, 0xEC0B, 0xEF0D, 0xC4DA, + 0xF7C3, 0x1E7C, 0xC198, 0xEE2D, 0xF235, 0x13FF, 0x388E, 0xD925, + 0x3978, 0x16DC, 0xD33E, 0xDDD0, 0xE22D, 0xDFCE, 0x373E, 0xEAEE, + 0xFEC0, 0x021B, 0x3AA0, 0x0B9E, 0x12EE, 0x2DC9, 0x2B55, 0xE62E, + 0x0ADC, 0x2F0D, 0x23EA, 0xFF9D, 0xF6C2, 0xF540, 0xCFC4, 0xDEF7, + 0x3798, 0x193A, 0x052F, 0xFC34, 0xD2C3, 0x12D7, 0x3390, 0x124D, + 0xF60B, 0xF620, 0xFB0E, 0xD40E, 0x0253, 0xDC86, 0x157F, 0x3A81, + 0xC2D6, 0xD32C, 0x1F3D, 0xE3D5, 0xD414, 0x2464, 0x1FA7, 0x28DE, + 0x160A, 0xEC22, 0x0C9F, 0x2F61, 0xF59B, 0x2008, 0x2E4A, 0x3309, + 0xD362, 0xE712, 0x114C, 0x20E5, 0x0466, 0xFC01, 0xF345, 0xC3E5, + 0x2357, 0xEF78, 0xD719, 0x2E02, 0xE19C, 0x1DA2, 0x279A, 0xF6E1, + 0x23CA, 0xE1F1, 0xE8E7, 0xF2A2, 0xC7E4, 0xD3F8, 0xF01D, 0xF9BE, + 0x1ACE, 0x2E88, 0x2345, 0x2AA0, 0x0BB2, 0x2206, 0xE4E7, 0x3224, + 0xD3C0, 0x0378, 0x0659, 0xC626, 0x25B0, 0xDBA4, 0xD478, 0x23A5, + 0xF01F, 0x2498, 0xF749, 0x1583, 0x04FD, 0x0685, 0xF197, 0xE83F, + 0xCA95, 0x181E, 0x2D88, 0xC3A3, 0xD358, 0xE3D4, 0xCDD7, 0xE4F8, + 0xD442, 0xEE02, 0x08CB, 0xE3FE, 0x10F3, 0xE132, 0xD89A, 0x3B3C, + 0xE4D5, 0xC7BF, 0xD3DD, 0x0DDA, 0x2878, 0x1C33, 0x0944, 0x1E11, + 0xCE26, 0x28C1, 0x22CD, 0x28B3, 0x1166, 0xDF7D, 0xF584, 0xD6DE, + 0xEFA3, 0x3E43, 0x1EF6, 0x36C3, 0x3BA0, 0xD04E, 0xFA71, 0x38DE, + 0xF7D8, 0xC7E8, 0xD091, 0x17F4, 0x0DDB, 0xCB01, 0x03CD, 0x3F57, + 0x2D17, 0xD309, 0xE4AC, 0x2EF7, 0xDC1C, 0x11A1, 0x2073, 0xDECC, + 0xD8EE, 0xE3C1, 0x2574, 0x21D0, 0x120B, 0x2C5D, 0xEA24, 0xC119, + 0x3222, 0x1601, 0xDF76, 0xE462, 0xDED5, 0x1885, 0xE0B7, 0x1DF3, + 0xFCB4, 0xE493, 0xFD3D, 0x009C, 0xE3D6, 0x2DA1, 0x2021, 0xE66C, + 0xA03E, 0x871C, 0x5E13, 0xB77E, 0x5D45, 0xF0BC, 0x0301, 0xEFEB, + 0xF75B, 0x2C53, 0xDFD0, 0x6B0B, 0x4474, 0x7130, 0x93BC, 0xD4C2, + + 0x3DEA, 0xEC1B, 0xFD11, 0xE60C, 0x39C4, 0xF795, 0x825F, 0xAC41, + 0x36F1, 0x601C, 0x45C5, 0xC852, 0x108C, 0xA866, 0x6D28, 0xA80B +}; + + +#endif + diff --git a/libraries/public/dsplib/include/dsplib/dvp_kl_dsplib.h b/libraries/public/dsplib/include/dsplib/dvp_kl_dsplib.h new file mode 100644 index 0000000..8f5d26a --- /dev/null +++ b/libraries/public/dsplib/include/dsplib/dvp_kl_dsplib.h @@ -0,0 +1,137 @@ +/* ==================================================================== + * Copyright (C) 2012 Texas Instruments Incorporated + * ==================================================================== */ + +/*! + * \file + * \brief This file decribes the exact set of kernels supported by the DSPLIB + * algorithm library as exported through DVP. + * \note When using these enums, only the DSPLIB kernels will be used! + * \defgroup group_algo_dsplib Algos: DSP Library + */ + +#ifndef _DVP_KL_DSPLIB_H_ +#define _DVP_KL_DSPLIB_H_ + +#ifdef DVP_USE_DSPLIB + +#include +//#define DVP_DSPLIB_TEST1 1 +//#define DVP_DSPLIB_TEST2 1 + +/*! + * \brief The explicit list of kernels supported by DSPLIB. + * \see DVP_DSPFunc + * \ingroup group_algo_dsplib + */ +enum { + DVP_KN_DSP_BASE = DVP_KN_LIBRARY_BASE(DVP_KL_DSPLIB), + DVP_KN_DSP_ADD16, //!< 16-bit Addition + DVP_KN_DSP_ADD32, //!< 32-bit Addition + DVP_KN_DSP_AUTOCORR16, //!< Autocorrelation + DVP_KN_DSP_BITEXP32, //!< Block exponent + DVP_KN_DSP_BLKESWAP16, //!< Endian-swap a block of 16-bit values + DVP_KN_DSP_BLKESWAP32, //!< Endian-swap a block of 32-bit values + DVP_KN_DSP_BLKESWAP64, //!< Endian-swap a block of 64-bit values + DVP_KN_DSP_BLKMOVE, //!< Block Move + DVP_KN_DSP_DOTPRODSQR, //!< Vector dot product and square + DVP_KN_DSP_DOTPROD, //!< Vector dot product + DVP_KN_DSP_FFT_16x16, //!< Complex forward FFT with digital reversal + DVP_KN_DSP_FFT_16x16R, //!< Complex forward mixed radix 16- x 16-bit FFT with rounding + DVP_KN_DSP_FFT_16x16_IMRE, + DVP_KN_DSP_FFT_16x32, //!< Complex forward mixed radix 16- x 32-bit FFT with rounding + DVP_KN_DSP_FFT_32x32, //!< Complex forward mixed radix 32- x 32-bit FFT with rounding + DVP_KN_DSP_FFT_32x32s, //!< Complex forward mixed radix 32- x 32-bit FFT with scaling + DVP_KN_DSP_FIR_CPLX, //!< Complex FIR filter (radix 2) + DVP_KN_DSP_FIR_HM4x4, //!< Complex FIR output with complex filter co-efficients (multiple of 4). + DVP_KN_DSP_FIR_GEN, //!< Real FIR fitering + DVP_KN_DSP_FIR_HM17_RA8x8, + DVP_KN_DSP_FIR_LMS2, //!< LMS Adaptive Filtering + DVP_KN_DSP_FIR_R4, //!< Radix-4 FIR Filter + DVP_KN_DSP_FIR_R8, //!< Radix-8 FIR Filter + DVP_KN_DSP_FIR_HM16_RM8A8x8, + DVP_KN_DSP_FIR_SYM, //!< Symmetric FIR filter (radix-8) + DVP_KN_DSP_IFFT_16x16, //!< Complex inverse mixed radix 16 x 16-bit FFT with rounding + DVP_KN_DSP_IFFT_16x16_IMRE, //!< Similar to IFFT16.16 with reversed positions for real and imaginary components in signals + DVP_KN_DSP_IFFT_16x32, //!< Complex inverse mixed radix 16 x 32-bit FFT with rounding + DVP_KN_DSP_IFFT_32x32, //!< Complex inverse mixed radix 32 x 32-bit FFT with rounding + DVP_KN_DSP_IIR, //!< IIR Filter with 5 coefficients + DVP_KN_DSP_IIR_LAT, //!< All-Pole IIR Lattice Filter + DVP_KN_DSP_IIR_SS, //!< Single-sample IIR filter + DVP_KN_DSP_MUL, //!< Matrix Multiplication + DVP_KN_DSP_MUL_CPLX, //!< Matrix Mulitplication of Complex Numbers + DVP_KN_DSP_MAT_TRANS, //!< Matrix Transpose + DVP_KN_DSP_MAXIDX, //!< Index of the maximum element of a vector + DVP_KN_DSP_MAXVAL, //!< Maximum value of a vector + DVP_KN_DSP_MINERROR, //!< Minimum energy error search + DVP_KN_DSP_MINVAL, //!< Minimum value of a vector. + DVP_KN_DSP_MUL32, //!< 32-bit vector multiply + DVP_KN_DSP_NEG32, //!< 32-bit vector negate + DVP_KN_DSP_Q15TOFL, //!< Q15 to float conversion --> Not supported on C64+ Fixed point DSP + DVP_KN_DSP_RECIP16, //!< 16-bit reciprocal + DVP_KN_DSP_VECSUMSQ, //!< Sum of squares + DVP_KN_DSP_W_VEC, //!< Weighted vector sum + DVP_KN_GEN_TWIDDLE_FFT_16X16, //!< Generate 16x16 twiddle factors needed for FFT operations + DVP_KN_GEN_TWIDDLE_FFT_16X16_IMRE, //!< Generate 16x16 twiddle factors needed for FFT IMRE operations + DVP_KN_GEN_TWIDDLE_FFT_16X32, //!< Generate 16x32 twiddle factors needed for FFT operations + DVP_KN_GEN_TWIDDLE_FFT_32x32, //!< Generate 32x32 twiddle factors needed for FFT operations + DVP_KN_GEN_TWIDDLE_IFFT_16X16, //!< Generate 16x16 twiddle factors needed for IFFT operations + DVP_KN_GEN_TWIDDLE_IFFT_16X16_IMRE //!< Generate 16x16 twiddle factors needed for IFFT IMRE operations +}; + +/*! \brief This is not a generic function. It can find if x is the power of no. + * \note No has to be multiple of 2 and 4. + * \param [in] x The value to determine. + * \param [in] no The + * \ingroup group_algo_dsplib + */ +static inline DVP_U16 isPowerOf (DVP_U32 x, DVP_U16 no ) +{ + if ( no == 2) + { + return ( + x == 8 || x == 16 || x == 32 || + x == 64 || x == 128 || x == 256 || x == 512 || x == 1024 || + x == 2048 || x == 4096 || x == 8192 || x == 16384) ; + } + if ( no == 4) + { + return(x == 16 || x == 64 || x == 256 || x == 1024 || + x == 4096 || x == 16384 ) ; + } + else + return 0; +} + +/*! \brief Multiplication strucutre + * \ingroup group_algo_dsplib + */ +typedef struct _dsp_matmul{ + DVP_Buffer_t input0; + DVP_Buffer_t input1; + DVP_Buffer_t output0; + DVP_S32 r1; // Rows of input0 + DVP_S32 c1; // Coloumns of input0 + DVP_S32 r2; // Rows of input1 + DVP_S32 c2; // Coloumns of input0 + DVP_S32 qs; // User defined right shift on final result. +}DVP_DSP_MatMul; + +/*! \brief Generic Function Parameters to DSPLIB functions. + * \ingroup group_algo_dsplib + */ +typedef struct _dsp_func{ + DVP_Buffer_t input0; + DVP_Buffer_t input1; + DVP_Buffer_t twoway; + DVP_Buffer_t output0; + DVP_Buffer_t output1; + DVP_S32 val1; + DVP_S32 val2; + DVP_S32 val3; +}DVP_DSPFunc; + +#endif // DVP_USE_DSPLIB + +#endif // _DVP_KL_DSPLIB_H_ + diff --git a/libraries/public/imgfilter/Android.mk b/libraries/public/imgfilter/Android.mk new file mode 100644 index 0000000..a3de7db --- /dev/null +++ b/libraries/public/imgfilter/Android.mk @@ -0,0 +1,44 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This can only be included when NEON is present +ifeq ($(TARGET_ARCH_VARIANT),armv7-a-neon) +VISION_LIBRARIES += imgfilter + +ifdef DVP_LOCAL_BUILD +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(DVP_DEBUGGING) $(DVP_CFLAGS) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +LOCAL_SRC_FILES := $(notdir $(wildcard $(LOCAL_PATH)/*.S)) +LOCAL_MODULE := libimgfilter +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(DVP_DEBUGGING) $(DVP_CFLAGS) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(DVP_INCLUDES) +LOCAL_SRC_FILES := imgFilter.c +LOCAL_STATIC_LIBRARIES := libimgfilter libsosal +LOCAL_SHARED_LIBRARIES := libcutils +LOCAL_MODULE := imgfilter_test +include $(BUILD_EXECUTABLE) +endif +endif + diff --git a/libraries/public/imgfilter/__3chan_tap_filter_image_3x1.S b/libraries/public/imgfilter/__3chan_tap_filter_image_3x1.S new file mode 100644 index 0000000..6f9d803 --- /dev/null +++ b/libraries/public/imgfilter/__3chan_tap_filter_image_3x1.S @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __3chan_tap_filter_image_3x1 + +.include "imgfilter.inc" + +/* make the 3x1 data input array in U16 format from some input */ +.macro MAKE_3x1_U16 dSrc, qA, qB, qC, dA_0, dC_0 + vshl.U64 \dA_0, \dSrc, #8 + vmovl.U8 \qA, \dA_0 + vmovl.U8 \qB, \dSrc + vshr.U64 \dC_0, \dSrc, #8 + vmovl.U8 \qC, \dC_0 +.endm + +.macro LENGTHEN_DATA_COEFF dA0_0, dA0_1, qA0, qA1, dCoeff_0, dCoeff_1, qCoeff0, qCoeff1 + vmovl.U16 \qA0, \dA0_0 + vmovl.U16 \qA1, \dA0_1 + vmovl.S16 \qCoeff0, \dCoeff_0 + vmovl.S16 \qCoeff1, \dCoeff_1 +.endm + +/* Assumes input is a 3 pixel channel source like xRGB where the first byte is ignored. + */ +__3chan_tap_filter_image_3x1: +pSrc .req r0 +width .req r1 +height .req r2 +pDst .req r3 +pixelsLeft .req r4 +linesLeft .req r5 +tmp .req r6 +srcStride .req r7 +dstStride .req r8 +srcStep .req r7 +dstStep .req r8 +coeff .req r9 +tmp2 .req r10 +tmp3 .req r11 + + PROLOG r0, r11 + + /* load the strides */ + ldr srcStride, [sp, #(13 * 4)] + ldr dstStride, [sp, #(14 * 4)] + ldr coeff, [sp, #(15 * 4)] + + /* initialize the height counter */ + mov linesLeft, height + + /* make tmp = width * 4; make the strides into steps */ + mov tmp, width, lsl #2 + sub srcStep, srcStride, tmp + sub dstStep, dstStride, tmp + + /* load signed 16 bit coefficients into q14,q15,q16 registers */ + ldrsh tmp, [coeff, #0] + vdup.16 q13, tmp + ldrsh tmp, [coeff, #2] + vdup.16 q14, tmp + ldrsh tmp, [coeff, #4] + vdup.16 q15, tmp + +__3chan_tap_filter_image_3x1_line: + + mov pixelsLeft, width + sub pixelsLeft, #2 + + pld [pSrc] + mov tmp, #L2_LINE_SIZE + pld [pSrc, tmp] + add tmp, tmp, #L2_LINE_SIZE + pld [pSrc, tmp] + add tmp, tmp, #L2_LINE_SIZE + + # do the first pixel set from ARMv6 + ldrb tmp, [pSrc] + strb tmp, [pDst] + + mov tmp, #128 + ldrb tmp2, [pSrc, #1] + ldrsh tmp3, [coeff, #0] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #1] + ldrsh tmp3, [coeff, #2] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #5] + ldrsh tmp3, [coeff, #4] + smlabb tmp, tmp3, tmp2, tmp + usat tmp, #8, tmp, asr #8 + strb tmp, [pDst, #1] + + mov tmp, #128 + ldrb tmp2, [pSrc, #2] + ldrsh tmp3, [coeff, #0] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #2] + ldrsh tmp3, [coeff, #2] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #6] + ldrsh tmp3, [coeff, #4] + smlabb tmp, tmp3, tmp2, tmp + usat tmp, #8, tmp, asr #8 + strb tmp, [pDst, #2] + + mov tmp, #128 + ldrb tmp2, [pSrc, #3] + ldrsh tmp3, [coeff, #0] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #3] + ldrsh tmp3, [coeff, #2] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #7] + ldrsh tmp3, [coeff, #4] + smlabb tmp, tmp3, tmp2, tmp + usat tmp, #8, tmp, asr #8 + strb tmp, [pDst, #3] + +__3chan_tap_filter_image_3x1_pixels: + + mov tmp, #L2_LINE_SIZE + add tmp, tmp, tmp, lsl #1 /* tmp = 3*L2size */ + pld [pSrc, tmp] + + vld4.8 {d0,d1,d2,d3}, [pSrc] + + /* ignore d0, the 'x' */ + + vmov.U32 q9, #0 + vmov.U32 q10, #0 + MAKE_3x1_U16 d1, q2, q3, q4, d4, d8 + LENGTHEN_DATA_COEFF d4, d5, q5, q6, d26, d27, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + LENGTHEN_DATA_COEFF d6, d7, q5, q6, d28, d29, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + LENGTHEN_DATA_COEFF d8, d9, q5, q6, d30, d31, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + vqrshrun.S32 d4, q9, #8 + vqrshrun.S32 d5, q10, #8 + vqrshrn.U16 d1, q2, #0 + + vmov.U32 q9, #0 + vmov.U32 q10, #0 + MAKE_3x1_U16 d2, q2, q3, q4, d4, d8 + LENGTHEN_DATA_COEFF d4, d5, q5, q6, d26, d27, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + LENGTHEN_DATA_COEFF d6, d7, q5, q6, d28, d29, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + LENGTHEN_DATA_COEFF d8, d9, q5, q6, d30, d31, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + vqrshrun.S32 d4, q9, #8 + vqrshrun.S32 d5, q10, #8 + vqrshrn.U16 d2, q2, #0 + + vmov.U32 q9, #0 + vmov.U32 q10, #0 + MAKE_3x1_U16 d3, q2, q3, q4, d4, d8 + LENGTHEN_DATA_COEFF d4, d5, q5, q6, d26, d27, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + LENGTHEN_DATA_COEFF d6, d7, q5, q6, d28, d29, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + LENGTHEN_DATA_COEFF d8, d9, q5, q6, d30, d31, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + vqrshrun.S32 d4, q9, #8 + vqrshrun.S32 d5, q10, #8 + vqrshrn.U16 d3, q2, #0 + + add tmp, pDst, #4 + + /* write out 6 32 bit interleaved pixels from the d0,d1,d2,d3 set */ + vst1.8 {d0[1]}, [tmp]! + vst1.8 {d1[1]}, [tmp]! + vst1.8 {d2[1]}, [tmp]! + vst1.8 {d3[1]}, [tmp]! + + vst1.8 {d0[2]}, [tmp]! + vst1.8 {d1[2]}, [tmp]! + vst1.8 {d2[2]}, [tmp]! + vst1.8 {d3[2]}, [tmp]! + + vst1.8 {d0[3]}, [tmp]! + vst1.8 {d1[3]}, [tmp]! + vst1.8 {d2[3]}, [tmp]! + vst1.8 {d3[3]}, [tmp]! + + vst1.8 {d0[4]}, [tmp]! + vst1.8 {d1[4]}, [tmp]! + vst1.8 {d2[4]}, [tmp]! + vst1.8 {d3[4]}, [tmp]! + + vst1.8 {d0[5]}, [tmp]! + vst1.8 {d1[5]}, [tmp]! + vst1.8 {d2[5]}, [tmp]! + vst1.8 {d3[5]}, [tmp]! + + vst1.8 {d0[6]}, [tmp]! + vst1.8 {d1[6]}, [tmp]! + vst1.8 {d2[6]}, [tmp]! + vst1.8 {d3[6]}, [tmp]! + + subs pixelsLeft, pixelsLeft, #6 + addeq pSrc, pSrc, #8*4 + addeq pDst, pDst, #8*4 + beq __3chan_tap_filter_image_3x1_pixels_end + cmp pixelsLeft, #6 + addge pSrc, pSrc, #6*4 + addge pDst, pDst, #6*4 + bge __3chan_tap_filter_image_3x1_pixels + /* if there are less than 6 left, back up and redo part of them */ + movlt tmp, #6 + sublt tmp, tmp, pixelsLeft + sublt pSrc, pSrc, tmp, lsl #2 + sublt pDst, pDst, tmp, lsl #2 + movlt pixelsLeft, #6 + blt __3chan_tap_filter_image_3x1_pixels + +__3chan_tap_filter_image_3x1_pixels_end: + + # do the last pixel set from ARMv6 + sub pSrc, pSrc, #8 + sub pDst, pDst, #8 + + ldrb tmp, [pSrc, #4] + strb tmp, [pDst, #4] + + mov tmp, #128 + ldrb tmp2, [pSrc, #1] + ldrsh tmp3, [coeff, #0] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #5] + ldrsh tmp3, [coeff, #2] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #5] + ldrsh tmp3, [coeff, #4] + smlabb tmp, tmp3, tmp2, tmp + usat tmp, #8, tmp, asr #8 + strb tmp, [pDst, #5] + + mov tmp, #128 + ldrb tmp2, [pSrc, #2] + ldrsh tmp3, [coeff, #0] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #6] + ldrsh tmp3, [coeff, #2] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #6] + ldrsh tmp3, [coeff, #4] + smlabb tmp, tmp3, tmp2, tmp + usat tmp, #8, tmp, asr #8 + strb tmp, [pDst, #6] + + mov tmp, #128 + ldrb tmp2, [pSrc, #3] + ldrsh tmp3, [coeff, #0] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #7] + ldrsh tmp3, [coeff, #2] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #7] + ldrsh tmp3, [coeff, #4] + smlabb tmp, tmp3, tmp2, tmp + usat tmp, #8, tmp, asr #8 + strb tmp, [pDst, #7] + + add pSrc, pSrc, #8 + add pDst, pDst, #8 + + # now do the line math + + add pSrc, pSrc, srcStep + add pDst, pDst, dstStep + + subs linesLeft, linesLeft, #1 + bgt __3chan_tap_filter_image_3x1_line + + EPILOG r0, r11 + +.unreq tmp3 +.unreq tmp2 +.unreq coeff +.unreq dstStep +.unreq dstStride +.unreq srcStep +.unreq srcStride +.unreq tmp +.unreq pixelsLeft +.unreq linesLeft +.unreq pDst +.unreq height +.unreq width +.unreq pSrc + +.end diff --git a/libraries/public/imgfilter/__3chan_tap_filter_image_3x1_fixed.S b/libraries/public/imgfilter/__3chan_tap_filter_image_3x1_fixed.S new file mode 100644 index 0000000..83fefc8 --- /dev/null +++ b/libraries/public/imgfilter/__3chan_tap_filter_image_3x1_fixed.S @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __3chan_tap_filter_image_3x1_fixed + +.include "imgfilter.inc" + +/* Assumes input is a 3 pixel channel source like xRGB where the first byte is ignored. + * uses fixed coefficients of -0.125, 1.25, -0.125. or a[0]>>4, a[1] + a[1]>>2, a[2]>>4 + */ +__3chan_tap_filter_image_3x1_fixed: +pSrc .req r0 +width .req r1 +height .req r2 +pDst .req r3 +pixelsLeft .req r4 +linesLeft .req r5 +tmp .req r6 +srcStride .req r7 +dstStride .req r8 +srcStep .req r7 +dstStep .req r8 +tmp2 .req r9 +tmp3 .req r10 + + PROLOG r0, r10 + + /* load the strides */ + ldr srcStride, [sp, #(12 * 4)] + ldr dstStride, [sp, #(13 * 4)] + + /* initialize the height counter */ + mov linesLeft, height + + /* make tmp = width * 4; make the strides into steps */ + mov tmp, width, lsl #2 + sub srcStep, srcStride, tmp + sub dstStep, dstStride, tmp + +__3chan_tap_filter_image_3x1_fixed_line: + + mov pixelsLeft, width + sub pixelsLeft, #2 + + pld [pSrc] + mov tmp, #L2_LINE_SIZE + pld [pSrc, tmp] + add tmp, tmp, #L2_LINE_SIZE + pld [pSrc, tmp] + add tmp, tmp, #L2_LINE_SIZE + + # do the first pixel set from ARMv6 + ldrb tmp, [pSrc] + strb tmp, [pDst] + + ldrb tmp2, [pSrc, #1] + add tmp, tmp2, tmp2, lsr #2 + sub tmp, tmp, tmp2, lsr #3 + ldrb tmp2, [pSrc, #5] + sub tmp, tmp, tmp2, lsr #3 + usat tmp, #8, tmp, asr #0 + strb tmp, [pDst, #1] + + ldrb tmp2, [pSrc, #2] + add tmp, tmp2, tmp2, lsr #2 + sub tmp, tmp, tmp2, lsr #3 + ldrb tmp2, [pSrc, #6] + sub tmp, tmp, tmp2, lsr #3 + usat tmp, #8, tmp, asr #0 + strb tmp, [pDst, #2] + + ldrb tmp2, [pSrc, #3] + add tmp, tmp2, tmp2, lsr #2 + sub tmp, tmp, tmp2, lsr #3 + ldrb tmp2, [pSrc, #7] + sub tmp, tmp, tmp2, lsr #3 + usat tmp, #8, tmp, asr #0 + strb tmp, [pDst, #3] + +__3chan_tap_filter_image_3x1_fixed_pixels: + + mov tmp, #L2_LINE_SIZE + add tmp, tmp, tmp, lsl #1 /* tmp = 3*L2size */ + pld [pSrc, tmp] + + vld4.8 {d0,d1,d2,d3}, [pSrc] + + /* ignore d0, the 'x' */ + + /* d1+d1>>2 = q13, etc */ + vshr.U8 d16, d1, #2 + vaddl.U8 q13, d1, d16 + vshr.U8 d16, d2, #2 + vaddl.U8 q14, d2, d16 + vshr.U8 d16, d3, #2 + vaddl.U8 q15, d3, d16 + + /* d1>>3=d4, d2>>3=d5, d3>>3=d6 */ + vshr.U8 d4, d1, #3 + vshr.U8 d5, d2, #3 + vshr.U8 d6, d3, #3 + + /* roll d4,5,6 to the left and up into d7,8,9 */ + vshl.U64 d7, d4, #8 + vshl.U64 d8, d5, #8 + vshl.U64 d9, d6, #8 + vmovl.U8 q10, d7 + vmovl.U8 q11, d8 + vmovl.U8 q12, d9 + + /* roll d4,5,6 to the right and up into d10,11,12 */ + vshr.U64 d10, d4, #8 + vshr.U64 d11, d5, #8 + vshr.U64 d12, d6, #8 + vmovl.U8 q7, d10 + vmovl.U8 q8, d11 + vmovl.U8 q9, d12 + + /* add the components together */ + vsub.I16 q2, q13, q7 + vsub.I16 q2, q2, q10 + vsub.I16 q3, q14, q8 + vsub.I16 q3, q3, q11 + vsub.I16 q4, q15, q9 + vsub.I16 q4, q4, q12 + + /* narrow back down */ + vqrshrun.S16 d1, q2, #0 + vqrshrun.S16 d2, q3, #0 + vqrshrun.S16 d3, q4, #0 + + add tmp, pDst, #4 + + /* write out 6 32 bit interleaved pixels from the d0,d1,d2,d3 set */ + vst1.8 {d0[1]}, [tmp]! + vst1.8 {d1[1]}, [tmp]! + vst1.8 {d2[1]}, [tmp]! + vst1.8 {d3[1]}, [tmp]! + + vst1.8 {d0[2]}, [tmp]! + vst1.8 {d1[2]}, [tmp]! + vst1.8 {d2[2]}, [tmp]! + vst1.8 {d3[2]}, [tmp]! + + vst1.8 {d0[3]}, [tmp]! + vst1.8 {d1[3]}, [tmp]! + vst1.8 {d2[3]}, [tmp]! + vst1.8 {d3[3]}, [tmp]! + + vst1.8 {d0[4]}, [tmp]! + vst1.8 {d1[4]}, [tmp]! + vst1.8 {d2[4]}, [tmp]! + vst1.8 {d3[4]}, [tmp]! + + vst1.8 {d0[5]}, [tmp]! + vst1.8 {d1[5]}, [tmp]! + vst1.8 {d2[5]}, [tmp]! + vst1.8 {d3[5]}, [tmp]! + + vst1.8 {d0[6]}, [tmp]! + vst1.8 {d1[6]}, [tmp]! + vst1.8 {d2[6]}, [tmp]! + vst1.8 {d3[6]}, [tmp]! + + subs pixelsLeft, pixelsLeft, #6 + addeq pSrc, pSrc, #8*4 + addeq pDst, pDst, #8*4 + beq __3chan_tap_filter_image_3x1_fixed_pixels_end + cmp pixelsLeft, #6 + addge pSrc, pSrc, #6*4 + addge pDst, pDst, #6*4 + bge __3chan_tap_filter_image_3x1_fixed_pixels + /* if there are less than 6 left, back up and redo part of them */ + movlt tmp, #6 + sublt tmp, tmp, pixelsLeft + sublt pSrc, pSrc, tmp, lsl #2 + sublt pDst, pDst, tmp, lsl #2 + movlt pixelsLeft, #6 + blt __3chan_tap_filter_image_3x1_fixed_pixels + +__3chan_tap_filter_image_3x1_fixed_pixels_end: + + # do the last pixel set from ARMv6 + sub pSrc, pSrc, #8 + sub pDst, pDst, #8 + + ldrb tmp, [pSrc, #4] + strb tmp, [pDst, #4] + + mov tmp, #0 + ldrb tmp2, [pSrc, #1] + sub tmp, tmp, tmp2, lsr #3 + ldrb tmp2, [pSrc, #5] + add tmp2, tmp2, tmp2, lsr #2 + sub tmp2, tmp2, tmp2, lsr #3 + add tmp, tmp, tmp2 + usat tmp, #8, tmp, asr #0 + strb tmp, [pDst, #1] + + mov tmp, #0 + ldrb tmp2, [pSrc, #2] + sub tmp, tmp, tmp2, lsr #3 + ldrb tmp2, [pSrc, #6] + add tmp2, tmp2, tmp2, lsr #2 + sub tmp2, tmp2, tmp2, lsr #3 + add tmp, tmp, tmp2 + usat tmp, #8, tmp, asr #0 + strb tmp, [pDst, #2] + + mov tmp, #0 + ldrb tmp2, [pSrc, #3] + sub tmp, tmp, tmp2, lsr #3 + ldrb tmp2, [pSrc, #7] + add tmp2, tmp2, tmp2, lsr #2 + sub tmp2, tmp2, tmp2, lsr #3 + add tmp, tmp, tmp2 + usat tmp, #8, tmp, asr #0 + strb tmp, [pDst, #3] + + add pSrc, pSrc, #8 + add pDst, pDst, #8 + + # now do the line math + + add pSrc, pSrc, srcStep + add pDst, pDst, dstStep + + subs linesLeft, linesLeft, #1 + bgt __3chan_tap_filter_image_3x1_fixed_line + + EPILOG r0, r10 + +.unreq tmp3 +.unreq tmp2 +.unreq dstStep +.unreq dstStride +.unreq srcStep +.unreq srcStride +.unreq tmp +.unreq pixelsLeft +.unreq linesLeft +.unreq pDst +.unreq height +.unreq width +.unreq pSrc + + +.end diff --git a/libraries/public/imgfilter/__3chan_tap_filter_image_3x1_fixed_k.S b/libraries/public/imgfilter/__3chan_tap_filter_image_3x1_fixed_k.S new file mode 100644 index 0000000..0386922 --- /dev/null +++ b/libraries/public/imgfilter/__3chan_tap_filter_image_3x1_fixed_k.S @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __3chan_tap_filter_image_3x1_fixed_k + +.include "imgfilter.inc" + +/* Assumes input is a 3 pixel channel source like xRGB where the first byte is ignored. + * uses symmetric fractional coefficients = [-k/64, (64+2k)/64, -k/64] where + * 0 <= k <= 64. If a value of 11 is used this reduces to + * [-8/64, (64+16)/64, -8/64] => [-0.125, 1.25, -0.125]. The benifit of this + * reduced range is that the math never exceeds 16 bit representation. + */ +__3chan_tap_filter_image_3x1_fixed_k: +pSrc .req r0 +width .req r1 +height .req r2 +pDst .req r3 +pixelsLeft .req r4 +linesLeft .req r5 +tmp .req r6 +srcStride .req r7 +dstStride .req r8 +srcStep .req r7 +dstStep .req r8 +tmp2 .req r9 +k1 .req r10 +k .req r11 + + PROLOG r0, r11 + + /* load the strides */ + ldr srcStride, [sp, #(13 * 4)] + ldr dstStride, [sp, #(14 * 4)] + ldr k, [sp, #(15 * 4)] + + /* clamp k to 64, and make the (1+2k) version */ + mov k1, #64 + cmp k, k1 + movgt k, #64 + mov tmp2, #2 + smlabb k1, k, tmp2, k1 + vdup.U08 d28, k + vdup.U16 q15, k1 + + /* initialize the height counter */ + mov linesLeft, height + + /* make tmp = width * 4; make the strides into steps */ + mov tmp, width, lsl #2 + sub srcStep, srcStride, tmp + sub dstStep, dstStride, tmp + +__3chan_tap_filter_image_3x1_fixed_k_line: + + mov pixelsLeft, width + sub pixelsLeft, #2 + + pld [pSrc] + mov tmp, #L2_LINE_SIZE + pld [pSrc, tmp] + add tmp, tmp, #L2_LINE_SIZE + pld [pSrc, tmp] + add tmp, tmp, #L2_LINE_SIZE + +.ifeq SUPPORT_EDGES + # do the first pixel set from ARMv6 + ldrb tmp, [pSrc] + strb tmp, [pDst] + + ldrb tmp, [pSrc, #1] + mul tmp2, tmp, k1 /* tmp2 = tmp*tmp3 */ + ldrb tmp, [pSrc, #5] + mul tmp, tmp, k /* tmp = tmp*k */ + sub tmp, tmp2, tmp /* tmp = tmp2-tmp */ + usat tmp2, #8, tmp, asr #6 /* tmp = usat(tmp>>6, 8) */ + strb tmp2, [pDst, #1] + + ldrb tmp, [pSrc, #2] + mul tmp2, tmp, k1 /* tmp2 = tmp*tmp3 */ + ldrb tmp, [pSrc, #6] + mul tmp, tmp, k /* tmp = tmp*k */ + sub tmp, tmp2, tmp /* tmp = tmp2-tmp */ + usat tmp2, #8, tmp, asr #6 /* tmp = usat(tmp>>6, 8) */ + strb tmp2, [pDst, #2] + + ldrb tmp, [pSrc, #3] + mul tmp2, tmp, k1 /* tmp2 = tmp*tmp3 */ + ldrb tmp, [pSrc, #7] + mul tmp, tmp, k /* tmp = tmp*k */ + sub tmp, tmp2, tmp /* tmp = tmp2-tmp */ + usat tmp2, #8, tmp, asr #6 /* tmp = usat(tmp>>6, 8) */ + strb tmp2, [pDst, #3] +.endif + +__3chan_tap_filter_image_3x1_fixed_k_pixels: + + mov tmp, #L2_LINE_SIZE + add tmp, tmp, tmp, lsl #1 /* tmp = 3*L2size */ + pld [pSrc, tmp] + + vld4.8 {d0,d1,d2,d3}, [pSrc] + + /*********************************/ + /* |00|01|02|03|04|05|06|07| */ + /* |-----------------------| */ + /* d00 |a0|a1|a2|a3|a4|a5|a6|a7| */ + /* d01 |r0|r1|r2|r3|r4|r5|r6|r7| */ + /* d02 |g0|g1|g2|g3|g4|g5|g6|g7| */ + /* d03 |b0|b1|b2|b3|b4|b5|b6|b7| */ + /* d04 | r0| r1| r2| r3| */ + /* d05 | r4| r5| r6| r7| */ + /* d06 | g0| g1| g2| g3| */ + /* d07 | g4| g5| g6| g7| */ + /* d08 | b0| b1| b2| b3| */ + /* d09 | b4| b5| b6| b7| */ + /* d10 |r0*k1|r1*k1|r2*k1|r3*k1| */ + /* d11 |r4*k1|r5*k1|r6*k1|r7*k1| */ + /* d12 |g0*k1|g1*k1|g2*k1|g3*k1| */ + /* d13 |g4*k1|g5*k1|g6*k1|g7*k1| */ + /* d14 |b0*k1|b1*k1|b2*k1|b3*k1| */ + /* d15 |b4*k1|b5*k1|b6*k1|b7*k1| */ + /* d16 | r1*k| r2*k| r3*k| r4*k| */ + /* d17 | r5*k| r6*k| r7*k| 00*k| */ + /* d18 | g1*k| g2*k| g3*k| g4*k| */ + /* d19 | g5*k| g6*k| g7*k| 00*k| */ + /* d20 | b1*k| b2*k| b3*k| b4*k| */ + /* d21 | b5*k| b6*k| b7*k| 00*k| */ + /* d22 | 00*k| r0*k| r1*k| r2*k| */ + /* d23 | r3*k| r4*k| r5*k| r6*k| */ + /* d24 | 00*k| g0*k| g1*k| g2*k| */ + /* d25 | g3*k| g4*k| g5*k| g6*k| */ + /* d26 | 00*k| b0*k| b1*k| b2*k| */ + /* d27 | b3*k| b4*k| b5*k| b6*k| */ + /* d28 | k| k| k| k| k| k| k| k| */ + /* d29 ... */ + /* d30 | k1| k1| k1| k1| */ + /* d31 | k1| k1| k1| k1| */ + /*********************************/ + + /* expand dx to qx */ + vmovl.U08 q2, d1 + vmovl.U08 q3, d2 + vmovl.U08 q4, d3 + + /* multiply k1*qx */ + vmul.U16 q5, q2, q15 + vmul.U16 q6, q3, q15 + vmul.U16 q7, q4, q15 + + /* roll dx to the right */ + vshr.U64 d16, d1, #8 + vshr.U64 d18, d2, #8 + vshr.U64 d20, d3, #8 + + /* roll dx to the left */ + vshl.U64 d22, d1, #8 + vshl.U64 d24, d2, #8 + vshl.U64 d26, d3, #8 + + /* multiply k*dx (right) and upconvert */ + vmull.U08 q8, d16, d28 + vmull.U08 q9, d18, d28 + vmull.U08 q10, d20, d28 + + /* multiply k*dx (left) and upconvert */ + vmull.U08 q11, d22, d28 + vmull.U08 q12, d24, d28 + vmull.U08 q13, d26, d28 + + /* subtract qx[-1,1] from qx[0] */ + vqsub.S16 q5, q5, q8 + vqsub.S16 q6, q6, q9 + vqsub.S16 q7, q7, q10 + vqsub.S16 q5, q5, q11 + vqsub.S16 q6, q6, q12 + vqsub.S16 q7, q7, q13 + + /* narrow qx to dx */ + vqrshrun.S16 d1, q5, #6 + vqrshrun.S16 d2, q6, #6 + vqrshrun.S16 d3, q7, #6 + +.ifeq SUPPORT_EDGES + add tmp, pDst, #4 +.endif + + /* write out 6 32 bit interleaved pixels from the d0,d1,d2,d3 set */ + vst1.8 {d0[1]}, [tmp]! + vst1.8 {d1[1]}, [tmp]! + vst1.8 {d2[1]}, [tmp]! + vst1.8 {d3[1]}, [tmp]! + + vst1.8 {d0[2]}, [tmp]! + vst1.8 {d1[2]}, [tmp]! + vst1.8 {d2[2]}, [tmp]! + vst1.8 {d3[2]}, [tmp]! + + vst1.8 {d0[3]}, [tmp]! + vst1.8 {d1[3]}, [tmp]! + vst1.8 {d2[3]}, [tmp]! + vst1.8 {d3[3]}, [tmp]! + + vst1.8 {d0[4]}, [tmp]! + vst1.8 {d1[4]}, [tmp]! + vst1.8 {d2[4]}, [tmp]! + vst1.8 {d3[4]}, [tmp]! + + vst1.8 {d0[5]}, [tmp]! + vst1.8 {d1[5]}, [tmp]! + vst1.8 {d2[5]}, [tmp]! + vst1.8 {d3[5]}, [tmp]! + + vst1.8 {d0[6]}, [tmp]! + vst1.8 {d1[6]}, [tmp]! + vst1.8 {d2[6]}, [tmp]! + vst1.8 {d3[6]}, [tmp]! + +.ifeq SUPPORT_EDGES + subs pixelsLeft, pixelsLeft, #6 + addeq pSrc, pSrc, #8*4 + addeq pDst, pDst, #8*4 + beq __3chan_tap_filter_image_3x1_fixed_k_pixels_end + cmp pixelsLeft, #6 + addge pSrc, pSrc, #6*4 + addge pDst, pDst, #6*4 + bge __3chan_tap_filter_image_3x1_fixed_k_pixels + /* if there are less than 6 left, back up and redo part of them */ + movlt tmp, #6 + sublt tmp, tmp, pixelsLeft + sublt pSrc, pSrc, tmp, lsl #2 + sublt pDst, pDst, tmp, lsl #2 + movlt pixelsLeft, #6 + blt __3chan_tap_filter_image_3x1_fixed_k_pixels +.endif + +__3chan_tap_filter_image_3x1_fixed_k_pixels_end: + +.ifeq SUPPORT_EDGES + # do the last pixel set from ARMv6 + sub pSrc, pSrc, #8 + sub pDst, pDst, #8 + + ldrb tmp, [pSrc, #4] + strb tmp, [pDst, #4] + + ldrb tmp, [pSrc, #1] + mul tmp2, tmp, k + ldrb tmp, [pSrc, #5] + mul tmp, tmp, k1 + sub tmp, tmp, tmp2 + usat tmp, #8, tmp, asr #6 + strb tmp, [pDst, #1] + + ldrb tmp2, [pSrc, #2] + mul tmp2, tmp, k + ldrb tmp2, [pSrc, #6] + mul tmp, tmp, k1 + sub tmp, tmp, tmp2 + usat tmp, #8, tmp, asr #6 + strb tmp, [pDst, #2] + + ldrb tmp2, [pSrc, #3] + mul tmp2, tmp, k + ldrb tmp2, [pSrc, #7] + mul tmp, tmp, k1 + sub tmp, tmp, tmp2 + usat tmp, #8, tmp, asr #6 + strb tmp, [pDst, #3] +.endif + + add pSrc, pSrc, #8 + add pDst, pDst, #8 + + # now do the line math + + add pSrc, pSrc, srcStep + add pDst, pDst, dstStep + + subs linesLeft, linesLeft, #1 + bgt __3chan_tap_filter_image_3x1_fixed_k_line + + EPILOG r0, r11 + +.unreq k +.unreq k1 +.unreq tmp2 +.unreq dstStep +.unreq dstStride +.unreq srcStep +.unreq srcStride +.unreq tmp +.unreq pixelsLeft +.unreq linesLeft +.unreq pDst +.unreq height +.unreq width +.unreq pSrc + + +.end diff --git a/libraries/public/imgfilter/__dual_sqrt.S b/libraries/public/imgfilter/__dual_sqrt.S new file mode 100644 index 0000000..9309232 --- /dev/null +++ b/libraries/public/imgfilter/__dual_sqrt.S @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __dual_sqrti_array +.global __dual_sqrtf_array + +.include "imgfilter.inc" + +__dual_sqrti_array: + PROLOG r0, r12 +__dual_sqrti_outer_loop: + vld1.32 {d0}, [r0]! + vcvt.F32.S32 d0, d0 + vmov.F32 d1, d0 + SQRTF d0, d1, d2, d3 + vcvt.S32.F32 d0, d0 + vst1.32 {d0}, [r2]! + subs r1, r1, #2 + bgt __dual_sqrti_outer_loop + EPILOG r0, r12 + +__dual_sqrtf_array: + PROLOG r0, r12 +__dual_sqrtf_outer_loop: + vld1.32 {d0}, [r0]! + SQRTF d0, d1, d2, d3 + vst1.32 {d0}, [r2]! + subs r1, r1, #2 + bgt __dual_sqrtf_outer_loop + EPILOG r0, r12 + +.end diff --git a/libraries/public/imgfilter/__planar_edge_filter_3x3.S b/libraries/public/imgfilter/__planar_edge_filter_3x3.S new file mode 100644 index 0000000..f159baa --- /dev/null +++ b/libraries/public/imgfilter/__planar_edge_filter_3x3.S @@ -0,0 +1,856 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __planar_edge_filter_3x3 + +.include "imgfilter.inc" + +__planar_edge_filter_3x3: +/* areas where the coefficient is zero, thus useless, are not included */ +width .req r0 +height .req r1 +pSrc .req r2 +srcStride .req r3 +pA .req r4 +pDst .req r5 +dstStride .req r6 +dstStep .req r6 +pixelsLeft .req r7 +tmp .req r8 +range .req r9 +limit .req r10 +tmp1 .req r11 + +row0_u8 .req d0 +row1_u8 .req d1 +row2_u8 .req d2 +dtmp1 .req d3 + +row0_s16 .req q2 +row1_s16 .req q3 +row2_s16 .req q4 + +Gx00 .req d10 +/* no Gx01, it's zero */ +Gx02 .req d11 +Gx10 .req d12 +/* no Gx11, it's zero */ +Gx12 .req d13 +Gx20 .req d14 +/* no Gx21, it's zero */ +Gx22 .req d15 + +Gy00 .req d16 +Gy01 .req d17 +Gy02 .req d18 +/* no Gx10, it's zero */ +/* no Gx11, it's zero */ +/* no Gx12, it's zero */ +Gy20 .req d19 +Gy21 .req d20 +Gy22 .req d21 + +dtmp2 .req d22 +dtmp3 .req d23 +qtmp0 .req q11 /* THIS OVERWRITES dtmp2 and dtmp3 !!! BE CAREFUL! */ + +qtmp1 .req q12 +qtmp2 .req q13 + +GxA .req q14 +GyA .req q15 + +GxA_00 .req d28 +GxA_01 .req d29 + +GyA_00 .req d30 +GyA_01 .req d31 + + PROLOG r0, r12 + + /* load other parameters */ + ldr pA, [sp, #(14 * 4)] + ldr pDst, [sp, #(15 * 4)] + ldr dstStride, [sp, #(16 * 4)] + ldr range, [sp, #(17 * 4)] + ldr limit, [sp, #(18 * 4)] + + /* load the matricies */ + mov tmp, #0 + vdup.8 dtmp3, tmp + + /* {-pA[0], 0, pA[0]} */ + /* Gx = {-pA[1], 0, pA[1]} */ + /* {-pA[2], 0, pA[2]} */ + + /* {-pA[0], -pA[1],-pA[2]} */ + /* Gy = { 0, 0, 0} */ + /* { pA[0], pA[1], pA[2]} */ + + ldr tmp, [pA] + vdup.8 Gx02, tmp + vsub.I8 Gx00, dtmp3, Gx02 + ldr tmp, [pA, #4] + vdup.8 Gx12, tmp + vsub.I8 Gx10, dtmp3, Gx12 + ldr tmp, [pA, #8] + vdup.8 Gx22, tmp + vsub.I8 Gx20, dtmp3, Gx22 + vmov.8 Gy00, Gx00 + vmov.8 Gy01, Gx10 + vmov.8 Gy02, Gx20 + vmov.8 Gy20, Gx02 + vmov.8 Gy21, Gx12 + vmov.8 Gy22, Gx22 + + /* Move pDst to the second line and remove the first and last line from consideration */ + add pDst, pDst, dstStride + sub height, #2 + +__planar_edge_filter_lines: + + /* reinitalize the row counter */ + mov pixelsLeft, width + sub pixelsLeft, #2 /* the first and last pixel will not be processed */ + +__planar_edge_filter_pixels: + + /* preload the next block */ + add tmp, pSrc, #L2_LINE_SIZE /* cache line size on A9 is 32 */ + pld [tmp] + add tmp, tmp, srcStride + pld [tmp] + add tmp, tmp, srcStride + pld [tmp] + + /* initialize the accumulators */ + mov tmp, #0 + vdup.16 GxA, tmp + vdup.16 GyA, tmp + + /* load 8x3 pixels */ + /* expand pixels from middle colum */ + vld1.8 {row0_u8}, [pSrc] + vmovl.U8 row0_s16, row0_u8 + add tmp, pSrc, srcStride + vld1.8 {row1_u8}, [tmp] + vmovl.U8 row1_s16, row1_u8 + add tmp, tmp, srcStride + vld1.8 {row2_u8}, [tmp] + vmovl.U8 row2_s16, row2_u8 + + /* middle column second matrix MLA */ + vmovl.S8 qtmp1, Gy01 + vmovl.S8 qtmp2, Gy21 + vmla.I16 GyA, row0_s16, qtmp1 + vmla.I16 GyA, row2_s16, qtmp2 + + /* create the shifted values for left column MLA */ + vshl.U64 dtmp1, row0_u8, #8 + vshl.U64 dtmp2, row1_u8, #8 + vshl.U64 dtmp3, row2_u8, #8 + vmovl.U8 row0_s16, dtmp1 + vmovl.U8 row1_s16, dtmp2 + vmovl.U8 row2_s16, dtmp3 + + /* left column first matrix MLA */ + vshl.U64 dtmp1, Gx00, #8 + vshl.U64 dtmp2, Gx10, #8 + vshl.U64 dtmp3, Gx20, #8 + vmovl.S8 qtmp1, dtmp1 + vmovl.S8 qtmp2, dtmp2 + vmovl.S8 qtmp0, dtmp3 + vmla.I16 GxA, row0_s16, qtmp1 + vmla.I16 GxA, row1_s16, qtmp2 + vmla.I16 GxA, row2_s16, qtmp0 + + /* left column second matrix MLA */ + vshl.U64 dtmp1, Gy00, #8 + vshl.U64 dtmp2, Gy20, #8 + vmovl.S8 qtmp1, dtmp1 + vmovl.S8 qtmp2, dtmp2 + vmla.I16 GyA, row0_s16, qtmp1 + vmla.I16 GyA, row2_s16, qtmp2 + + /* create the shifted values for right column MLA */ + vshr.U64 dtmp1, row0_u8, #8 + vshr.U64 dtmp2, row1_u8, #8 + vshr.U64 dtmp3, row2_u8, #8 + vmovl.U8 row0_s16, dtmp1 + vmovl.U8 row1_s16, dtmp2 + vmovl.U8 row2_s16, dtmp3 + + /* right column first matrix MLA */ + vshr.U64 dtmp1, Gx02, #8 + vshr.U64 dtmp2, Gx12, #8 + vshr.U64 dtmp3, Gx22, #8 + vmovl.S8 qtmp1, dtmp1 + vmovl.S8 qtmp2, dtmp2 + vmovl.S8 qtmp0, dtmp3 + vmla.I16 GxA, row0_s16, qtmp1 + vmla.I16 GxA, row1_s16, qtmp2 + vmla.I16 GxA, row2_s16, qtmp0 + + /* right column second matrix MLA */ + vshr.U64 dtmp1, Gy02, #8 + vshr.U64 dtmp2, Gy22, #8 + vmovl.S8 qtmp1, dtmp1 + vmovl.S8 qtmp2, dtmp2 + vmla.I16 GyA, row0_s16, qtmp1 + vmla.I16 GyA, row2_s16, qtmp2 + + /* square each gradient and expand each field from 16 to 32 */ + vmull.S16 q0, GxA_00, GxA_00 + vmull.S16 q1, GxA_01, GxA_01 + vmull.S16 q2, GyA_00, GyA_00 + vmull.S16 q3, GyA_01, GyA_01 + + /* sum top and bottom */ + vadd.S32 q0, q0, q2 + vadd.S32 q1, q1, q3 + + /* convert to float */ + vcvt.F32.S32 q0, q0 + vcvt.F32.S32 q1, q1 + + /* Square Root these Sum of Squares */ + SQRTF q0, q2, q3, q4 + SQRTF q1, q2, q3, q4 + + /* load the range and limit */ + vdup.32 q2, range + vcvt.F32.S32 q2, q2 + vdup.32 q3, limit + vcvt.F32.S32 q3, q3 + + /* divide by the range */ + vdiv.F32 s0, s0, s8 + vdiv.F32 s1, s1, s9 + vdiv.F32 s2, s2, s10 + vdiv.F32 s3, s3, s11 + vdiv.F32 s4, s4, s8 + vdiv.F32 s5, s5, s9 + vdiv.F32 s6, s6, s10 + vdiv.F32 s7, s7, s11 + + /* multiply by the limit */ + vmul.F32 s0, s0, s12 + vmul.F32 s1, s1, s13 + vmul.F32 s2, s2, s14 + vmul.F32 s3, s3, s15 + vmul.F32 s4, s4, s12 + vmul.F32 s5, s5, s13 + vmul.F32 s6, s6, s14 + vmul.F32 s7, s7, s15 + + /* convert back to int */ + vcvt.S32.F32 q0, q0 + vcvt.S32.F32 q1, q1 + + /* move back down to U8 (32->16->8) */ + vqmovn.U32 d0, q0 + vqmovn.U32 d1, q1 + vqmovn.U16 d0, q0 + + /* store */ + add tmp, pDst, #1 + vst1.8 {d0[1]}, [tmp]! + vst1.8 {d0[2]}, [tmp]! + vst1.8 {d0[3]}, [tmp]! + vst1.8 {d0[4]}, [tmp]! + vst1.8 {d0[5]}, [tmp]! + vst1.8 {d0[6]}, [tmp]! + + /* LOOP LOGIC */ + /* + pixelsLeft -= 6; + if (pixelsLeft == 0) { + pSrc += 8; + pDst += 8; + pixelsLeft = 0; // pointless + break; + } else if (pixelsLeft >= 6) { + pSrc += 6; + pDst += 6; + continue; + } else if (pixelsLeft < 6) { + pSrc -= 6 - pixelsLeft; + pDst -= 6 - pixelsLeft; + pixelsLeft = 6; + continue; + } */ + subs pixelsLeft, pixelsLeft, #6 + addeq pSrc, pSrc, #8 + addeq pDst, pDst, #8 + /* moveq pixelsLeft, #0 */ + beq __planar_edge_filter_pixels_end + cmp pixelsLeft, #6 + addge pSrc, pSrc, #6 + addge pDst, pDst, #6 + bge __planar_edge_filter_pixels + movlt tmp, #6 + sublt tmp, tmp, pixelsLeft + sublt pSrc, pSrc, tmp + sublt pDst, pDst, tmp + movlt pixelsLeft, #6 + blt __planar_edge_filter_pixels + + +__planar_edge_filter_pixels_end: + /* calculate the steps and apply */ + sub tmp, srcStride, width + add pSrc, pSrc, tmp + sub tmp, dstStride, width + add pDst, pDst, tmp + + /* loop the lines */ + subs height, height, #1 + bgt __planar_edge_filter_lines + + EPILOG r0, r12 +.unreq width +.unreq height +.unreq pSrc +.unreq srcStride +.unreq pA +.unreq pDst +.unreq dstStride +.unreq pixelsLeft +.unreq tmp +.unreq dstStep + +/* make the 3x1 data input array in U16 format from some input */ +.macro MAKE_3x1_U16 dSrc, qA, qB, qC, dA_0, dC_0 + vshl.U64 \dA_0, \dSrc, #8 + vmovl.U8 \qA, \dA_0 + vmovl.U8 \qB, \dSrc + vshr.U64 \dC_0, \dSrc, #8 + vmovl.U8 \qC, \dC_0 +.endm + +.macro LENGTHEN_DATA_COEFF dA0_0, dA0_1, qA0, qA1, dCoeff_0, dCoeff_1, qCoeff0, qCoeff1 + vmovl.U16 \qA0, \dA0_0 + vmovl.U16 \qA1, \dA0_1 + vmovl.S16 \qCoeff0, \dCoeff_0 + vmovl.S16 \qCoeff1, \dCoeff_1 +.endm + +/* Assumes input is a 3 pixel channel source like xRGB where the first byte is ignored. + */ +__3chan_tap_filter_image_3x1: +pSrc .req r0 +width .req r1 +height .req r2 +pDst .req r3 +pixelsLeft .req r4 +linesLeft .req r5 +tmp .req r6 +srcStride .req r7 +dstStride .req r8 +srcStep .req r7 +dstStep .req r8 +coeff .req r9 +tmp2 .req r10 +tmp3 .req r11 + + PROLOG r0, r11 + + /* load the strides */ + ldr srcStride, [sp, #(13 * 4)] + ldr dstStride, [sp, #(14 * 4)] + ldr coeff, [sp, #(15 * 4)] + + /* initialize the height counter */ + mov linesLeft, height + + /* make tmp = width * 4; make the strides into steps */ + mov tmp, width, lsl #2 + sub srcStep, srcStride, tmp + sub dstStep, dstStride, tmp + + /* load signed 16 bit coefficients into q14,q15,q16 registers */ + ldrsh tmp, [coeff, #0] + vdup.16 q13, tmp + ldrsh tmp, [coeff, #2] + vdup.16 q14, tmp + ldrsh tmp, [coeff, #4] + vdup.16 q15, tmp + +__3chan_tap_filter_image_3x1_line: + + mov pixelsLeft, width + sub pixelsLeft, #2 + + pld [pSrc] + mov tmp, #L2_LINE_SIZE + pld [pSrc, tmp] + add tmp, tmp, #L2_LINE_SIZE + pld [pSrc, tmp] + add tmp, tmp, #L2_LINE_SIZE + + # do the first pixel set from ARMv6 + ldrb tmp, [pSrc] + strb tmp, [pDst] + + mov tmp, #128 + ldrb tmp2, [pSrc, #1] + ldrsh tmp3, [coeff, #0] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #1] + ldrsh tmp3, [coeff, #2] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #5] + ldrsh tmp3, [coeff, #4] + smlabb tmp, tmp3, tmp2, tmp + usat tmp, #8, tmp, asr #8 + strb tmp, [pDst, #1] + + mov tmp, #128 + ldrb tmp2, [pSrc, #2] + ldrsh tmp3, [coeff, #0] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #2] + ldrsh tmp3, [coeff, #2] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #6] + ldrsh tmp3, [coeff, #4] + smlabb tmp, tmp3, tmp2, tmp + usat tmp, #8, tmp, asr #8 + strb tmp, [pDst, #2] + + mov tmp, #128 + ldrb tmp2, [pSrc, #3] + ldrsh tmp3, [coeff, #0] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #3] + ldrsh tmp3, [coeff, #2] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #7] + ldrsh tmp3, [coeff, #4] + smlabb tmp, tmp3, tmp2, tmp + usat tmp, #8, tmp, asr #8 + strb tmp, [pDst, #3] + +__3chan_tap_filter_image_3x1_pixels: + + mov tmp, #L2_LINE_SIZE + add tmp, tmp, tmp, lsl #1 /* tmp = 3*L2size */ + pld [pSrc, tmp] + + vld4.8 {d0,d1,d2,d3}, [pSrc] + + /* ignore d0, the 'x' */ + + vmov.U32 q9, #0 + vmov.U32 q10, #0 + MAKE_3x1_U16 d1, q2, q3, q4, d4, d8 + LENGTHEN_DATA_COEFF d4, d5, q5, q6, d26, d27, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + LENGTHEN_DATA_COEFF d6, d7, q5, q6, d28, d29, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + LENGTHEN_DATA_COEFF d8, d9, q5, q6, d30, d31, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + vqrshrun.S32 d4, q9, #8 + vqrshrun.S32 d5, q10, #8 + vqrshrn.U16 d1, q2, #0 + + vmov.U32 q9, #0 + vmov.U32 q10, #0 + MAKE_3x1_U16 d2, q2, q3, q4, d4, d8 + LENGTHEN_DATA_COEFF d4, d5, q5, q6, d26, d27, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + LENGTHEN_DATA_COEFF d6, d7, q5, q6, d28, d29, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + LENGTHEN_DATA_COEFF d8, d9, q5, q6, d30, d31, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + vqrshrun.S32 d4, q9, #8 + vqrshrun.S32 d5, q10, #8 + vqrshrn.U16 d2, q2, #0 + + vmov.U32 q9, #0 + vmov.U32 q10, #0 + MAKE_3x1_U16 d3, q2, q3, q4, d4, d8 + LENGTHEN_DATA_COEFF d4, d5, q5, q6, d26, d27, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + LENGTHEN_DATA_COEFF d6, d7, q5, q6, d28, d29, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + LENGTHEN_DATA_COEFF d8, d9, q5, q6, d30, d31, q7, q8 + vmla.I32 q9, q5, q7 + vmla.I32 q10, q6, q8 + vqrshrun.S32 d4, q9, #8 + vqrshrun.S32 d5, q10, #8 + vqrshrn.U16 d3, q2, #0 + + add tmp, pDst, #4 + + /* write out 6 32 bit interleaved pixels from the d0,d1,d2,d3 set */ + vst1.8 {d0[1]}, [tmp]! + vst1.8 {d1[1]}, [tmp]! + vst1.8 {d2[1]}, [tmp]! + vst1.8 {d3[1]}, [tmp]! + + vst1.8 {d0[2]}, [tmp]! + vst1.8 {d1[2]}, [tmp]! + vst1.8 {d2[2]}, [tmp]! + vst1.8 {d3[2]}, [tmp]! + + vst1.8 {d0[3]}, [tmp]! + vst1.8 {d1[3]}, [tmp]! + vst1.8 {d2[3]}, [tmp]! + vst1.8 {d3[3]}, [tmp]! + + vst1.8 {d0[4]}, [tmp]! + vst1.8 {d1[4]}, [tmp]! + vst1.8 {d2[4]}, [tmp]! + vst1.8 {d3[4]}, [tmp]! + + vst1.8 {d0[5]}, [tmp]! + vst1.8 {d1[5]}, [tmp]! + vst1.8 {d2[5]}, [tmp]! + vst1.8 {d3[5]}, [tmp]! + + vst1.8 {d0[6]}, [tmp]! + vst1.8 {d1[6]}, [tmp]! + vst1.8 {d2[6]}, [tmp]! + vst1.8 {d3[6]}, [tmp]! + + subs pixelsLeft, pixelsLeft, #6 + addeq pSrc, pSrc, #8*4 + addeq pDst, pDst, #8*4 + beq __3chan_tap_filter_image_3x1_pixels_end + cmp pixelsLeft, #6 + addge pSrc, pSrc, #6*4 + addge pDst, pDst, #6*4 + bge __3chan_tap_filter_image_3x1_pixels + /* if there are less than 6 left, back up and redo part of them */ + movlt tmp, #6 + sublt tmp, tmp, pixelsLeft + sublt pSrc, pSrc, tmp, lsl #2 + sublt pDst, pDst, tmp, lsl #2 + movlt pixelsLeft, #6 + blt __3chan_tap_filter_image_3x1_pixels + +__3chan_tap_filter_image_3x1_pixels_end: + + # do the last pixel set from ARMv6 + sub pSrc, pSrc, #8 + sub pDst, pDst, #8 + + ldrb tmp, [pSrc, #4] + strb tmp, [pDst, #4] + + mov tmp, #128 + ldrb tmp2, [pSrc, #1] + ldrsh tmp3, [coeff, #0] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #5] + ldrsh tmp3, [coeff, #2] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #5] + ldrsh tmp3, [coeff, #4] + smlabb tmp, tmp3, tmp2, tmp + usat tmp, #8, tmp, asr #8 + strb tmp, [pDst, #5] + + mov tmp, #128 + ldrb tmp2, [pSrc, #2] + ldrsh tmp3, [coeff, #0] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #6] + ldrsh tmp3, [coeff, #2] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #6] + ldrsh tmp3, [coeff, #4] + smlabb tmp, tmp3, tmp2, tmp + usat tmp, #8, tmp, asr #8 + strb tmp, [pDst, #6] + + mov tmp, #128 + ldrb tmp2, [pSrc, #3] + ldrsh tmp3, [coeff, #0] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #7] + ldrsh tmp3, [coeff, #2] + smlabb tmp, tmp3, tmp2, tmp + ldrb tmp2, [pSrc, #7] + ldrsh tmp3, [coeff, #4] + smlabb tmp, tmp3, tmp2, tmp + usat tmp, #8, tmp, asr #8 + strb tmp, [pDst, #7] + + add pSrc, pSrc, #8 + add pDst, pDst, #8 + + # now do the line math + + add pSrc, pSrc, srcStep + add pDst, pDst, dstStep + + subs linesLeft, linesLeft, #1 + bgt __3chan_tap_filter_image_3x1_line + + EPILOG r0, r11 + +.unreq tmp3 +.unreq tmp2 +.unreq coeff +.unreq dstStep +.unreq dstStride +.unreq srcStep +.unreq srcStride +.unreq tmp +.unreq pixelsLeft +.unreq linesLeft +.unreq pDst +.unreq height +.unreq width +.unreq pSrc + + +/* Assumes input is a 3 pixel channel source like xRGB where the first byte is ignored. + * uses fixed coefficients of -0.25, 1.5, -0.25. or a[0]>>2, a[1]*3>>1, a[2]>>2 + */ +__3chan_tap_filter_image_3x1_fixed: +pSrc .req r0 +width .req r1 +height .req r2 +pDst .req r3 +pixelsLeft .req r4 +linesLeft .req r5 +tmp .req r6 +srcStride .req r7 +dstStride .req r8 +srcStep .req r7 +dstStep .req r8 +tmp2 .req r9 +tmp3 .req r10 + + PROLOG r0, r10 + + /* load the strides */ + ldr srcStride, [sp, #(12 * 4)] + ldr dstStride, [sp, #(13 * 4)] + + /* initialize the height counter */ + mov linesLeft, height + + /* make tmp = width * 4; make the strides into steps */ + mov tmp, width, lsl #2 + sub srcStep, srcStride, tmp + sub dstStep, dstStride, tmp + +__3chan_tap_filter_image_3x1_fixed_line: + + mov pixelsLeft, width + sub pixelsLeft, #2 + + pld [pSrc] + mov tmp, #L2_LINE_SIZE + pld [pSrc, tmp] + add tmp, tmp, #L2_LINE_SIZE + pld [pSrc, tmp] + add tmp, tmp, #L2_LINE_SIZE + + # do the first pixel set from ARMv6 + ldrb tmp, [pSrc, #0] + strb tmp, [pDst, #0] + + ldrb tmp, [pSrc, #1] + add tmp2, tmp, tmp, lsr #1 + sub tmp2, tmp2, tmp, lsr #2 + ldrb tmp, [pSrc, #5] + sub tmp2, tmp2, tmp, lsr #2 + strb tmp2, [pDst, #1] + + ldrb tmp, [pSrc, #2] + add tmp2, tmp, tmp, lsr #1 + sub tmp2, tmp2, tmp, lsr #2 + ldrb tmp, [pSrc, #6] + sub tmp2, tmp2, tmp, lsr #2 + strb tmp2, [pDst, #2] + + ldrb tmp, [pSrc, #3] + add tmp2, tmp, tmp, lsr #1 + sub tmp2, tmp2, tmp, lsr #2 + ldrb tmp, [pSrc, #7] + sub tmp2, tmp2, tmp, lsr #2 + strb tmp2, [pDst, #3] + +__3chan_tap_filter_image_3x1_fixed_pixels: + + pld [pSrc, tmp] + + vld4.8 {d0,d1,d2,d3}, [pSrc] + + /* ignore d0, the 'x' */ + + /* d1>>2=d4, d2>>2=d5, d3>>2=d6 */ + vshr.U8 d4, d1, #2 + vshr.U8 d5, d2, #2 + vshr.U8 d6, d3, #2 + + /* d1*3/2=q13, d2*3/2=q14, d3*3/2=q15 */ + vmov.U8 d16, #3 + vmull.U16 q13, d16, d1 + vmull.U16 q14, d16, d2 + vmull.U16 q15, d16, d3 + + /* roll d4,5,6 to the left and up into d7,8,9 */ + vshl.U64 d7, d4, #8 + vshl.U64 d8, d5, #8 + vshl.U64 d9, d6, #8 + vmovl.U8 q10, d7 + vmovl.U8 q11, d8 + vmovl.U8 q12, d9 + + /* roll d4,5,6 to the right and up into d10,11,12 */ + vshr.U64 d10, d4, #8 + vshr.U64 d11, d5, #8 + vshr.U64 d12, d6, #8 + vmovl.U8 q7, d10 + vmovl.U8 q8, d11 + vmovl.U8 q9, d12 + + /* add the components together */ + vsub.U16 q2, q13, q7 + vsub.U16 q2, q2, q10 + vsub.U16 q3, q14, q8 + vsub.U16 q3, q3, q11 + vsub.U16 q4, q15, q9 + vsub.U16 q4, q4, q12 + + /* narrow back down */ + vqmovn.U16 d1, q2 + vqmovn.U16 d2, q3 + vqmovn.U16 d3, q4 + + add tmp, pDst, #4 + + vst1.8 {d0[1]}, [tmp]! + vst1.8 {d1[1]}, [tmp]! + vst1.8 {d2[1]}, [tmp]! + vst1.8 {d3[1]}, [tmp]! + + vst1.8 {d0[2]}, [tmp]! + vst1.8 {d1[2]}, [tmp]! + vst1.8 {d2[2]}, [tmp]! + vst1.8 {d3[2]}, [tmp]! + + vst1.8 {d0[3]}, [tmp]! + vst1.8 {d1[3]}, [tmp]! + vst1.8 {d2[3]}, [tmp]! + vst1.8 {d3[3]}, [tmp]! + + vst1.8 {d0[4]}, [tmp]! + vst1.8 {d1[4]}, [tmp]! + vst1.8 {d2[4]}, [tmp]! + vst1.8 {d3[4]}, [tmp]! + + vst1.8 {d0[5]}, [tmp]! + vst1.8 {d1[5]}, [tmp]! + vst1.8 {d2[5]}, [tmp]! + vst1.8 {d3[5]}, [tmp]! + + vst1.8 {d0[6]}, [tmp]! + vst1.8 {d1[6]}, [tmp]! + vst1.8 {d2[6]}, [tmp]! + vst1.8 {d3[6]}, [tmp]! + + subs pixelsLeft, pixelsLeft, #6 + addeq pSrc, pSrc, #8*4 + addeq pDst, pDst, #8*4 + beq __3chan_tap_filter_image_3x1_fixed_pixels_end + cmp pixelsLeft, #6 + addge pSrc, pSrc, #6*4 + addge pDst, pDst, #6*4 + bge __3chan_tap_filter_image_3x1_fixed_pixels + /* if there are less than 6 left, back up and redo part of them */ + movlt tmp, #6 + sublt tmp, tmp, pixelsLeft + sublt pSrc, pSrc, tmp, lsl #2 + sublt pDst, pDst, tmp, lsl #2 + movlt pixelsLeft, #6 + blt __3chan_tap_filter_image_3x1_fixed_pixels + +__3chan_tap_filter_image_3x1_fixed_pixels_end: + + # do the last pixel set from ARMv6 + sub pSrc, pSrc, #8 + sub pDst, pDst, #8 + + ldrb tmp, [pSrc, #4] + strb tmp, [pDst, #4] + + ldrb tmp, [pSrc, #1] + sub tmp2, tmp2, tmp, lsr #2 + ldrb tmp, [pSrc, #5] + add tmp2, tmp, tmp, lsr #1 + sub tmp2, tmp2, tmp, lsr #2 + strb tmp2, [pDst, #1] + + ldrb tmp, [pSrc, #2] + sub tmp2, tmp2, tmp, lsr #2 + ldrb tmp, [pSrc, #6] + add tmp2, tmp, tmp, lsr #1 + sub tmp2, tmp2, tmp, lsr #2 + strb tmp2, [pDst, #2] + + ldrb tmp, [pSrc, #3] + sub tmp2, tmp2, tmp, lsr #2 + ldrb tmp, [pSrc, #7] + add tmp2, tmp, tmp, lsr #1 + sub tmp2, tmp2, tmp, lsr #2 + strb tmp2, [pDst, #3] + + add pSrc, pSrc, #8 + add pDst, pDst, #8 + + add pSrc, pSrc, srcStep + add pDst, pDst, dstStep + + subs linesLeft, linesLeft, #1 + bgt __3chan_tap_filter_image_3x1_fixed_line + + EPILOG r0, r8 + +.unreq tmp3 +.unreq tmp2 +.unreq dstStep +.unreq dstStride +.unreq srcStep +.unreq srcStride +.unreq tmp +.unreq pixelsLeft +.unreq linesLeft +.unreq pDst +.unreq height +.unreq width +.unreq pSrc + + +.end diff --git a/libraries/public/imgfilter/concerto.mak b/libraries/public/imgfilter/concerto.mak new file mode 100644 index 0000000..31a6d49 --- /dev/null +++ b/libraries/public/imgfilter/concerto.mak @@ -0,0 +1,45 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_CPU),ARM) +ifneq ($(HOST_COMPILER),TMS470) + +include $(PRELUDE) + +VISION_LIBRARIES+=imgfilter +DVP_INC+=$(_MODPATH)/include +DVP_FEATURES+=DVP_USE_IMGFILTER + +ifdef DVP_LOCAL_BUILD +TARGET=imgfilter +TARGETTYPE=library +ASSEMBLY=$(all-S-files) +endif + +include $(FINALE) + +_MODULE=imgfilter_test +include $(PRELUDE) +ifdef DVP_LOCAL_BUILD +TARGET=imgfilter_test +TARGETTYPE=exe +CSOURCES=imgFilter.c +STATIC_LIBS+=imgfilter sosal +SYS_STATIC_LIBS+=$(PLATFORM_LIBS) +IDIRS+=$(_MODPATH)/include +endif +include $(FINALE) + +endif # TMS470 +endif # ARM diff --git a/libraries/public/imgfilter/imgFilter.c b/libraries/public/imgfilter/imgFilter.c new file mode 100644 index 0000000..0e2a73c --- /dev/null +++ b/libraries/public/imgfilter/imgFilter.c @@ -0,0 +1,413 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +typedef struct _argb_pixel_t { + union _pixel { + uint32_t u32; + uint8_t u8[4]; + } data; +} argb_pixel_t; + +int16_t coeff[] = {-32, 320, -32}; + +void __3chan_tap_filter_image_3x1_c(uint8_t *pSrc, + uint32_t width, + uint32_t height, + uint8_t *pDst, + uint32_t srcStride, + uint32_t dstStride, + int16_t coeff[3]) +{ + uint32_t x, y, c, i, j; + int32_t l, k; + const uint32_t coeff_q = 8; + const int32_t tw = 3; + const uint32_t nc = 4; + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + i = (y * srcStride) + (x * sizeof(uint32_t)); + j = (y * dstStride) + (x * sizeof(uint32_t)); + + for (c = 0; c < nc; c++) + { + if (c == 0) + { + pDst[j] = pSrc[i]; // copy the 0th channel + } + else + { + int32_t acc = 1 << (coeff_q-1); // the rounding padding + + for (k = -(tw/2); k <= tw/2; k++) + { + l = x + k; // add channel offset later + if (l < 0) + l = 0; + else if (l >= (int32_t)width) + l = width - 1; + + i = (y * srcStride) + (l * sizeof(uint32_t)); + acc += (uint16_t)pSrc[i+c] * coeff[k+tw/2]; + } + acc >>= coeff_q; + if (acc > ((1<data) + { + filter_args_t *args = (filter_args_t *)worker->data; + //printf("Working on %ux%u %p to %p\n", args->width, args->height, args->input, args->output); +#if 0 + __3chan_tap_filter_image_3x1(args->input, + args->width, + args->height, + args->output, + args->srcStride, + args->dstStride, + coeff); +#else + __3chan_tap_filter_image_3x1_fixed_k(args->input, + args->width, + args->height, + args->output, + args->srcStride, + args->dstStride, + 8); +#endif + return true_e; + } + return false_e; +} + +bool_e threadEdgeFilter(threadpool_worker_t *worker) +{ + if (worker && worker->data) + { + uint32_t limit = 255; + filter_args_t *args = (filter_args_t *)worker->data; + if (args->type == 0) + { + int32_t sobel_3[3] = {1,2,1}; + int32_t range = SOBEL_RANGE; + __planar_edge_filter_3x3(args->width, + args->height, + args->input, + args->width, + sobel_3, + args->output, + args->width, + range, + limit); + } + else if (args->type == 1) + { + int32_t prewitt_3[3] = {1,1,1}; + int32_t range = PREWITT_RANGE; + __planar_edge_filter_3x3(args->width, + args->height, + args->input, + args->width, + prewitt_3, + args->output, + args->width, + range, + limit); + } + else if (args->type == 2) + { + int32_t scharr_3[3] = {3,10,3}; + int32_t range = SCHARR_RANGE; + __planar_edge_filter_3x3(args->width, + args->height, + args->input, + args->width, + scharr_3, + args->output, + args->width, + range, + limit); + } + else if (args->type == 3) + { + int32_t kroon_3[3] = {17,61,17}; + int32_t range = KROON_RANGE; + __planar_edge_filter_3x3(args->width, + args->height, + args->input, + args->width, + kroon_3, + args->output, + args->width, + range, + limit); + } + return true_e; + } + return false_e; +} +int main(int argc, char *argv[]) +{ + printf("argc=%u argv[1]=%s\n", argc, argv[1]); + printf("$ %s \n", argv[0]); + if (argc == 8) + { + char op[10]; + uint32_t width = atoi(argv[2]); + uint32_t height = atoi(argv[3]); + FILE *fin = fopen(argv[4], "rb"); + FILE *fout = fopen(argv[5], "wb+"); + uint32_t freq = atoi(argv[6]); + uint32_t nthreads = atoi(argv[7]); + uint8_t *input = NULL; + uint8_t *output = NULL; + uint32_t size = width * height; // initial size + size_t nb = 0; + uint32_t limit = 255; + uint32_t stride = width; + profiler_t perf; + uint32_t i = 0; + + profiler_clear(&perf); + + strncpy(op, argv[1], sizeof(op)); + + if (strncmp(op,"tap", sizeof(op)) == 0 ) + { + size *= sizeof(uint32_t); + stride *= sizeof(uint32_t); + } + + printf("$ %s %s %u %u %s %s %u %u\n", argv[0], op, width, height, argv[4], argv[5], freq, nthreads); + + input = (uint8_t *)calloc(1, size); + output = (uint8_t *)calloc(1, size); + + if (input && output && fin && fout) + { + memset(input, 0x80, size); + memset(output, 0x00, size); + + if (nthreads == 1) + { + while ((nb = fread(input, 1, size, fin)) > 0) + { + printf("Read "FMT_SIZE_T" bytes\n", nb); + if (strncmp(op, "tap", sizeof(op)) == 0) + { + profiler_start(&perf); +#if 0 + __3chan_tap_filter_image_3x1_c((uint8_t *)input, + width, + height, + (uint8_t *)output, + width*sizeof(uint32_t), + width*sizeof(uint32_t), + coeff); +#else + __3chan_tap_filter_image_3x1_fixed_k((uint8_t *)input, + width, + height, + (uint8_t *)output, + width*sizeof(uint32_t), + width*sizeof(uint32_t), + 8); +#endif + profiler_stop(&perf); + } + else if (strncmp(op,"sobel",sizeof(op)) == 0) + { + int32_t sobel_3[3] = {1,2,1}; + int32_t range = SOBEL_RANGE; + profiler_start(&perf); + __planar_edge_filter_3x3(width, + height, + input, + width, + sobel_3, + output, + width, + range, + limit); + profiler_stop(&perf); + } + else if (strncmp(op,"prewitt",sizeof(op)) == 0) + { + int32_t prewitt_3[3] = {1,1,1}; + int32_t range = PREWITT_RANGE; + profiler_start(&perf); + __planar_edge_filter_3x3(width, + height, + input, + width, + prewitt_3, + output, + width, + range, + limit); + profiler_stop(&perf); + } + else if (strncmp(op,"scharr",sizeof(op)) == 0) + { + int32_t scharr_3[3] = {3,10,3}; + int32_t range = SCHARR_RANGE; + profiler_start(&perf); + __planar_edge_filter_3x3(width, + height, + input, + width, + scharr_3, + output, + width, + range, + limit); + profiler_stop(&perf); + } + else if (strncmp(op, "kroon", sizeof(op)) == 0) + { + int32_t kroon_3[3] = {17,61,17}; + int32_t range = KROON_RANGE; + profiler_start(&perf); + __planar_edge_filter_3x3(width, + height, + input, + width, + kroon_3, + output, + width, + range, + limit); + profiler_stop(&perf); + } + printf("Operations took %lf sec\n", (double)perf.tmpTime/perf.rate); + fwrite(output, 1, size, fout); + } + } + else if (1 < nthreads && nthreads <= 8) + { + filter_args_t args[8]; + threadpool_t *pool; + threadpool_f func = NULL; + + for (i = 0; i < nthreads; i++) + { + uint32_t bar_height = height/nthreads; + uint32_t bar_index = i * bar_height; + + args[i].input = &input[bar_index * stride]; + args[i].width = width; + args[i].height = height/nthreads; + args[i].output = &output[bar_index * stride]; + args[i].srcStride = stride; + args[i].dstStride = stride; + printf("%ux%u from %p to %p\n", args[i].width, args[i].height, args[i].input, args[i].output); + } + + if (strncmp(op, "tap", sizeof(op)) == 0) + func = threadTapFilter; + else + func = threadEdgeFilter; + + pool = threadpool_create(nthreads, 1, sizeof(filter_args_t), func, NULL); + if (pool) + { + while ((nb = fread(input, 1, size, fin)) > 0) + { + void *data[] = {&args[0], &args[1]}; + printf("Read "FMT_SIZE_T" bytes\n", nb); + + do + { + struct timespec t; + profiler_start(&perf); + if (true_e == threadpool_issue(pool, data, dimof(data))) + threadpool_complete(pool, true_e); + profiler_stop(&perf); + printf("Operation took %lf sec\n", (double)perf.tmpTime/perf.rate); + if (freq) + { + t.tv_sec = 0; + t.tv_nsec = (1000000000/freq) - perf.tmpTime; + printf("Sleeping for %lu ns\n", t.tv_nsec); + nanosleep(&t, &t); + } + } while (freq > 0); + fwrite(output, 1, size, fout); + } + threadpool_destroy(pool); + } + } + } + free(input); + free(output); + fclose(fin); + fclose(fout); + return 0; + } + else if (argc == 1) + { + uint32_t width = 1280; + uint32_t height = 720; + uint32_t *input = (uint32_t *)calloc(width*height, sizeof(uint32_t)); + uint32_t *output = (uint32_t *)calloc(width*height, sizeof(uint32_t)); + profiler_t perf; + + profiler_clear(&perf); + + if (input && output) + { + memset(input, 0x80, width*height*sizeof(uint32_t)); + memset(input, 0x00, width*height*sizeof(uint32_t)); + profiler_start(&perf); + memcpy(output, input, width*height*sizeof(uint32_t)); + profiler_stop(&perf); + printf("Memcpy of HD720 in %lf sec\n", (double)perf.tmpTime/perf.rate); + free(input); + free(output); + } + return 0; + } + return -1; +} diff --git a/libraries/public/imgfilter/imgfilter.inc b/libraries/public/imgfilter/imgfilter.inc new file mode 100644 index 0000000..3ae6d6c --- /dev/null +++ b/libraries/public/imgfilter/imgfilter.inc @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* .equ IMGFILTER_NOT_OPTIMIZED 0 */ + +/** PROLOG is a macro which saves your context on the stack. To reference the + * next stack variable, add (sN-s0+2)*4, ie PROLOG r0,r12 will move the sp - (14*4) + */ +.macro PROLOG, s0, sN + stmfd sp!, {\s0-\sN, lr} +.endm + +.macro EPILOG, s0, sN + ldmfd sp!, {\s0-\sN, pc} +.endm + +/** This macro performs a float sqrt on the t0 register. t1-t3 are temps. */ +.macro SQRTF t0, t1, t2, t3 + vmov.F32 \t1, \t0 + vrsqrte.F32 \t0, \t0 + vmul.F32 \t2, \t0, \t1 + vrsqrts.F32 \t3, \t2, \t0 + vmul.F32 \t0, \t0, \t3 + vmul.F32 \t2, \t0, \t1 + vrsqrts.F32 \t3, \t2, \t0 + vmul.F32 \t0, \t0, \t3 + vrecpe.F32 \t1, \t0 + vrecps.F32 \t2, \t1, \t0 + vmul.F32 \t1, \t1, \t2 + vrecps.F32 \t2, \t1, \t0 + vmul.F32 \t0, \t1, \t2 +.endm + +/* For Cortex A8 */ +/*.equ L1_LINE_SIZE, 64*/ +/*.equ L2_LINE_SIZE, 64*/ + +/* For Cortex A9 */ +.equ L1_LINE_SIZE, 32 +.equ L2_LINE_SIZE, 32 + +/* 0 is "on", anything else is "off" */ +.equ SUPPORT_NONMULTIPLE_LINES, 1 +.equ SUPPORT_EDGES, 0 diff --git a/libraries/public/imgfilter/include/imgfilter/dvp_kl_imgfilter.h b/libraries/public/imgfilter/include/imgfilter/dvp_kl_imgfilter.h new file mode 100644 index 0000000..e7109c2 --- /dev/null +++ b/libraries/public/imgfilter/include/imgfilter/dvp_kl_imgfilter.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! + * \file + * \brief This file decribes the exact set of kernels supported by the IMGFILTER + * algorithm library as exported through DVP. + * \note When using these enums, only the IMGFILTER kernels will be used! + */ + +#ifndef _DVP_KL_IMGFILTER_H_ +#define _DVP_KL_IMGFILTER_H_ + +#ifdef DVP_USE_IMGFILTER + +#include + +/*! The explicit list of kernels supported by the IMGFILTER algorithm library. + * \see DVP_Transform_t + */ +enum { + DVP_KN_IMGFILTER_BASE = DVP_KN_LIBRARY_BASE(DVP_KL_IMGFILTER), + + /*! + * Image Convolution of FOURCC_Y800 of data using the Sobel Gx and Gy operators\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_IMGFILTER_SOBEL, + + /*! + * Image Convolution of FOURCC_Y800 of data using the Scharr Gx and Gy operators\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_IMGFILTER_SCHARR, + + /*! + * Image Convolution of FOURCC_Y800 of data using the Scharr Gx and Gy operators\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_IMGFILTER_KROON, + + /*! + * Image Convolution of FOURCC_Y800 of data using the Prewitt Gx and Gy operators\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_IMGFILTER_PREWITT, + + /*! + * Image Filter of 1x3 with predetermined coefficients. + * \param [input] Image Color type supported: FOURCC_ARGB + * \param [output] Image Color type supported: FOURCC_ARGB + */ + DVP_KN_IMGFILTER_3CHAN_TAP_FILTER_1x3, +}; + +#endif // DVP_USE_IMGFILTER + +#endif // _DVP_KL_IMGFILTER_H_ + diff --git a/libraries/public/imgfilter/include/imgfilter/imgFilter_armv7.h b/libraries/public/imgfilter/include/imgfilter/imgFilter_armv7.h new file mode 100644 index 0000000..fea9701 --- /dev/null +++ b/libraries/public/imgfilter/include/imgfilter/imgFilter_armv7.h @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! + * \file + * \brief The IMGFILTER NEON Library. + * \author Erik Rainey s + * \defgroup group_imgfilter Algos: IMGFILTER (NEON) + * \brief This only works on ARMv7 NEON enabled cores. + */ + +/*! +\page page_imgfilter IMGFILTER NEON Library +This library implements a 3x3 convolution operation on 8 bit data in NEON. +*/ + +#ifndef _IMGFILTER_ARMV7_H_ +#define _IMGFILTER_ARMV7_H_ + +/*! Range of Prewitt Kernel */ +#define PREWITT_RANGE (721) + +/*! Range of Sobel Kernel */ +#define SOBEL_RANGE (1081) + +/*! Range of Scharr Kernel */ +#define SCHARR_RANGE (4688) + +/*! Range of Kroon Kernel */ +#define KROON_RANGE (34259) + +/*! Range of Tap Kernel */ +#define TAP_RANGE (256) + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * This function does an edge filter on the input image and writes the gradient + * data out to the pDst pointer per pixel. + * \param [in] width Image width in pixels + * \param [in] height Image height in pixels + * \param [in] pSrc The pointer to the planar image data. + * \param [in] srcStride The number of bytes between each pixel in the y direction. + * \param [in] a The values for the gradient matrix to convolve the image with. Gx and Gy will + * be created and used. + * \param [out] pDst The output gradient data. + * \param [in] dstStride The number of bytes between each pixel in the y direction. + * \ingroup group_imgfilter + */ +void __planar_edge_filter_3x3(uint32_t width, + uint32_t height, + uint8_t *pSrc, + int32_t srcStride, + int32_t a[3], + uint8_t *pDst, + int32_t dstStride, + int32_t range, + int32_t limit); + +/*! + * \brief Computes "num" integer square roots of a number in input and stores it + * in output. + * \param [in] input The array of input integers. + * \param [in] num The number of inputs to process. + * \param [out] output The location to store the results. + * \ingroup group_imgfilter + */ +void __dual_sqrti_array(int32_t *input, int32_t num, int32_t *output); + +/*! + * \brief Computes "num" float square roots of a number in input and stores it + * in output. + * \param [in] input The array of input floats. + * \param [in] num The number of inputs to process. + * \param [out] output The location to store the results. + * \ingroup group_imgfilter + */ +void __dual_sqrtf_array(float *input, int32_t num, float *output); + +/*! + * \brief A 3x1 image filter of fixed coefficients {-0.25, 1.5, -0.25} + * \param pSrc + * \param width + * \param height + * \param pDst + * \param srcStride + * \param dstStride + * \ingroup group_imgfilter + */ +void __3chan_tap_filter_image_3x1_fixed(uint8_t *pSrc, + uint32_t width, + uint32_t height, + uint8_t *pDst, + uint32_t srcStride, + uint32_t dstStride); + +/*! + * \brief A 3x1 image filter of computed fractional coefficients from 0<=k<=85. + * \param pSrc + * \param width + * \param height + * \param pDst + * \param srcStride + * \param dstStride + * \param k + * \ingroup group_imgfilter + */ +void __3chan_tap_filter_image_3x1_fixed_k(uint8_t *pSrc, + uint32_t width, + uint32_t height, + uint8_t *pDst, + uint32_t srcStride, + uint32_t dstStride, + uint8_t k); + +/*! + * \brief A 3x1 image filter which can take arbitrary coefficients. + * \param pSrc + * \param width + * \param height + * \param pDst + * \param srcStride + * \param dstStride + * \param coeff + * \ingroup group_imgfilter + */ +void __3chan_tap_filter_image_3x1(uint8_t *pSrc, + uint32_t width, + uint32_t height, + uint8_t *pDst, + uint32_t srcStride, + uint32_t dstStride, + int16_t coeff[3]); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libraries/public/ocl/clenvironment.c b/libraries/public/ocl/clenvironment.c new file mode 100644 index 0000000..ea48ec3 --- /dev/null +++ b/libraries/public/ocl/clenvironment.c @@ -0,0 +1,1242 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief The "OpenCL Environment" core features. + * \see http://github.com/emrainey/OpenCL-Environment + * \author Erik Rainey + */ + +#include +#include +#include +#ifdef DARWIN +#include +#else +#include +#endif +#include +#include + +#define CL_LOG_SIZE (1024*1024) + +void cl_free(void *ptr) +{ +#ifdef CL_DEBUG + //printf("Freeing %p\n",ptr); +#endif + free(ptr); +} + +void *cl_malloc(size_t numBytes) +{ + void *ptr = NULL; + if (numBytes == 0) + printf("WARNING: ALLOCATING A BUFFER OF ZERO BYTES!!\n"); + ptr = malloc(numBytes); +#ifdef CL_DEBUG + //printf("Malloc'd %p for %lu bytes\n",ptr,numBytes); +#endif + if (ptr) + memset(ptr, 0, numBytes); + return ptr; +} + +size_t flen(FILE *fp) +{ + size_t len = 0; + fseek(fp, 0, SEEK_END); + len = ftell(fp); + fseek(fp, 0, SEEK_SET); + return len; +} + +size_t flines(FILE *fp) +{ + size_t numLines = 0; + char line[1024]; + fseek(fp, 0, SEEK_SET); + while (fgets(line, sizeof(line), fp) > 0) { + numLines++; + } +#ifdef CL_DEBUG + printf("%lu lines in file %p\n",numLines,fp); +#endif + fseek(fp, 0, SEEK_SET); + return numLines; +} + +/* +static char *strlastitem(char *str, char item) +{ + int last = 0, i = 0; + char *s = str; + do { + if (s[i] == item) + last = i; + } while (s[i++] != '\0'); + if (s[] != item) + s = str; + return s; +} +*/ + +#define CASE_STRINGERIZE(err, label, function, file, line) \ + case err: \ + fprintf(stderr, "%s: OpenCL error "#err" at %s in %s:%d\n", label, function, file, line); \ + break + +cl_int clBuildError(cl_int build_status, char *label, const char *function, const char *file, int line) +{ + switch (build_status) + { + case CL_BUILD_SUCCESS: + break; + CASE_STRINGERIZE(CL_BUILD_NONE, label, function, file, line); + CASE_STRINGERIZE(CL_BUILD_ERROR, label, function, file, line); + CASE_STRINGERIZE(CL_BUILD_IN_PROGRESS, label, function, file, line); + default: + fprintf(stderr, "%s: Unknown build error %d at %s in %s:%d\n", label, build_status, function, file, line); + break; + } + return build_status; +} + +cl_int clPrintError(cl_int err, char *label, const char *function, const char *file, int line) +{ + switch (err) + { + case CL_SUCCESS: + break; + CASE_STRINGERIZE(CL_BUILD_PROGRAM_FAILURE, label, function, file, line); + CASE_STRINGERIZE(CL_COMPILER_NOT_AVAILABLE, label, function, file, line); + CASE_STRINGERIZE(CL_DEVICE_NOT_AVAILABLE, label, function, file, line); + CASE_STRINGERIZE(CL_DEVICE_NOT_FOUND, label, function, file, line); + CASE_STRINGERIZE(CL_IMAGE_FORMAT_MISMATCH, label, function, file, line); + CASE_STRINGERIZE(CL_IMAGE_FORMAT_NOT_SUPPORTED, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_ARG_INDEX, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_ARG_SIZE, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_ARG_VALUE, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_BINARY, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_BUFFER_SIZE, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_BUILD_OPTIONS, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_COMMAND_QUEUE, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_CONTEXT, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_DEVICE, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_DEVICE_TYPE, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_EVENT, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_EVENT_WAIT_LIST, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_GL_OBJECT, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_GLOBAL_OFFSET, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_HOST_PTR, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_IMAGE_SIZE, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_KERNEL_NAME, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_KERNEL, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_KERNEL_ARGS, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_KERNEL_DEFINITION, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_MEM_OBJECT, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_OPERATION, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_PLATFORM, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_PROGRAM, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_PROGRAM_EXECUTABLE, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_QUEUE_PROPERTIES, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_SAMPLER, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_VALUE, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_WORK_DIMENSION, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_WORK_GROUP_SIZE, label, function, file, line); + CASE_STRINGERIZE(CL_INVALID_WORK_ITEM_SIZE, label, function, file, line); + CASE_STRINGERIZE(CL_MAP_FAILURE, label, function, file, line); + CASE_STRINGERIZE(CL_MEM_OBJECT_ALLOCATION_FAILURE, label, function, file, line); + CASE_STRINGERIZE(CL_MEM_COPY_OVERLAP, label, function, file, line); + CASE_STRINGERIZE(CL_OUT_OF_HOST_MEMORY, label, function, file, line); + CASE_STRINGERIZE(CL_OUT_OF_RESOURCES, label, function, file, line); + CASE_STRINGERIZE(CL_PROFILING_INFO_NOT_AVAILABLE, label, function, file, line); + default: + fprintf(stderr, "%s: Unknown error %d at %s in %s:%d\n", label, err, function, file, line); + break; + } + return err; +} + +void clPrintEnvironment(cl_environment_t *pEnv) +{ + if (pEnv) + { + printf("Environment: %p\n" + "\t%u devices\n" + "\t%u kernels\n", + pEnv, pEnv->numDevices, pEnv->numKernels); + } +} + +void clDeleteEnvironment(cl_environment_t *pEnv) +{ + if (pEnv) + { + cl_uint i = 0; + if (pEnv->kernels) + { + for(i = 0; i < pEnv->numKernels; i++) + clReleaseKernel(pEnv->kernels[i]); + cl_free(pEnv->kernels); + } + if (pEnv->retCodes) + cl_free(pEnv->retCodes); + if (pEnv->program) + clReleaseProgram(pEnv->program); + if (pEnv->queues) + { + for (i = 0; i < pEnv->numDevices; i++) + { + clReleaseCommandQueue(pEnv->queues[i]); + } + cl_free(pEnv->queues); + } + if (pEnv->sources) + { + for (i = 0; i < pEnv->numLines; i++) + { + cl_free(pEnv->sources[i]); + pEnv->sources[i] = NULL; + } + cl_free(pEnv->lengths); + cl_free(pEnv->sources); + } + if (pEnv->context) + clReleaseContext(pEnv->context); + if (pEnv->devices) + cl_free(pEnv->devices); + + cl_free(pEnv); + } +} + + +void cl_dump_bin(char *filename, cl_byte *bin, size_t numBytes) +{ + FILE *fp = fopen(filename, "wb+"); + if (fp) + { +#ifdef CL_DEBUG + printf("Writing from %p to file %s for %lu bytes\n", bin, filename, numBytes); +#endif + fwrite(bin, 1, numBytes, fp); +#ifdef CL_DEBUG + printf("Wrote file %s\n",filename); +#endif + fclose(fp); + } +} + +cl_byte *cl_load_bin(char *filename, size_t *pNumBytes) +{ + cl_byte *bin = NULL; + FILE *fp = fopen(filename, "rb"); + if (fp != NULL) + { + size_t numBytes = flen(fp); + bin = (cl_byte *)cl_malloc(numBytes); + if (bin) + { + size_t b = fread(bin, 1, numBytes, fp); +#ifdef CL_DEBUG + printf("Read "FMT_SIZE_T" bytes\n", b); +#endif + fclose(fp); + } + } + return bin; +} + +cl_byte *cl_serialize_kernels(cl_kernel_bin_t *bins, size_t *pNumBytes) +{ + cl_uint i = 0; + cl_byte *bin = NULL; + + *pNumBytes = bins->numDevices*sizeof(size_t) + sizeof(size_t); + for (i = 0; i < bins->numDevices; i++) + { +#ifdef CL_DEBUG + printf("Serialized clBinary [%02u]: %u bytes\n", i, bins->sizes[i]); +#endif + *pNumBytes += bins->sizes[i]; + } +#ifdef CL_DEBUG + printf("There are %lu total bytes to serialize\n",*pNumBytes); +#endif + bin = cl_malloc_array(cl_byte,(*pNumBytes)); + if (bin) + { + size_t offset = 0; + memcpy(&bins[offset], &bins->deviceTypes, sizeof(cl_uint)); + offset += sizeof(cl_uint); + memcpy(&bins[offset], &bins->numDevices, sizeof(size_t)); + offset += sizeof(size_t); + for (i = 0; i < bins->numDevices; i++) + { + memcpy(&bins[offset], &bins->sizes[i], sizeof(size_t)); + offset += sizeof(size_t); + memcpy(&bins[offset], &bins->data[i], bins->sizes[i]); + offset += bins->sizes[i]; + } + if (offset != *pNumBytes) + printf("Warning: Serialization totals are off!\n"); + } + else + { + *pNumBytes = 0; + } + return bin; +} + +void cl_delete_kernel_bin(cl_kernel_bin_t *bins) +{ + if (bins) + { + cl_uint i = 0; + if (bins->data) + { + for (i = 0; i < bins->numDevices; i++) + { + if (bins->data[i]) + { + cl_free(bins->data[i]); + bins->data[i] = NULL; + } + } + cl_free(bins->data); + bins->data = NULL; + } + if (bins->sizes) + { + cl_free(bins->sizes); + bins->sizes = NULL; + } + // @TODO Fill in the structure with a bunch of garbage which will cause an abort later if dereferenced. + //memset(bins, 0xFE, sizeof(cl_kernel_bin_t)); + cl_free(bins); + } +} + +cl_kernel_bin_t *cl_create_kernel_bin(size_t numDevices) +{ + cl_kernel_bin_t *bins; + + bins = (cl_kernel_bin_t *)cl_malloc(sizeof(cl_kernel_bin_t)); + if (bins) + { + bins->deviceTypes = CL_DEVICE_TYPE_DEFAULT; + bins->numDevices = numDevices; + bins->numBytesSizes = sizeof(size_t) * bins->numDevices; + bins->numBytesData = sizeof(unsigned char *) * bins->numDevices; + bins->sizes = (size_t *)cl_malloc(bins->numBytesSizes); + bins->data = (unsigned char **)cl_malloc(bins->numBytesData); + + if (bins->sizes == NULL || bins->data == NULL) + { + cl_assert(bins->sizes != NULL && bins->data != NULL,); + cl_delete_kernel_bin(bins); + bins = NULL; + } + else + { + memset(bins->sizes, 0, bins->numBytesSizes); + memset(bins->data, 0, bins->numBytesData); + } + } + return bins; +} + +cl_kernel_bin_t *cl_unserialize_kernels(cl_byte *bin, size_t numBytes) +{ + cl_uint i,deviceTypes = CL_DEVICE_TYPE_DEFAULT; + size_t numDevices = 1; + size_t offset = 0; + cl_kernel_bin_t *bins = NULL; + + // minimum size + if (numBytes <= (2* sizeof(size_t))) + return NULL; + + memcpy(&deviceTypes, &bin[offset], sizeof(cl_uint)); + offset += sizeof(cl_uint); + memcpy(&numDevices, &bin[offset], sizeof(size_t)); + offset += sizeof(size_t); + printf("There are "FMT_SIZE_T" device kernels in the flat binary\n", numDevices); + bins = cl_create_kernel_bin(numDevices); + if (bins) + { + bins->deviceTypes = deviceTypes; + bins->numBytesSizes = sizeof(size_t) * numDevices; + bins->numBytesData = sizeof(cl_byte *) * numDevices; + for (i = 0; i < numDevices; i++) + { + memcpy(&bins->sizes[i], &bin[offset], sizeof(size_t)); + offset += sizeof(size_t); + bins->data[i] = (cl_byte *)cl_malloc(bins->sizes[i]); + if (bins->data[i] && offset < numBytes) + { + memcpy(bins->data[i], &bin[offset], bins->sizes[i]); + offset += bins->sizes[i]; + } + else + { + if (bins->data[i] == NULL) + printf("ERROR: Failed to allocate binary data array!\n"); + if (offset >= numBytes) + printf("ERROR: Offset is larger than read data\n"); + cl_delete_kernel_bin(bins); + bins = NULL; + break; + } + } + } + return bins; +} + +void cl_dump_kernels(char *filename, cl_kernel_bin_t *bins) +{ + size_t numBytes = 0; + cl_byte *bin = NULL; + + if (filename[0] == '\0') + return; + bin = cl_serialize_kernels(bins, &numBytes); +#ifdef CL_DEBUG + printf("There are %lu binaries to write out\n", bins->numDevices); +#endif + if (bin) + { + cl_dump_bin(filename, bin, numBytes); + cl_free(bin); + } +} + +cl_kernel_bin_t *cl_extract_kernels(cl_program program) +{ + size_t numBinaries = 0; + size_t numBinaries2 = 0; + cl_uint i = 0; + cl_int err = CL_SUCCESS; + size_t numDevices; + cl_kernel_bin_t *bins = NULL; + cl_device_id devices[CL_MAX_DEVICES]; + cl_device_type deviceTypes = 0; + cl_build_status build_status = 0; + + err = clGetProgramInfo(program, CL_PROGRAM_NUM_DEVICES, sizeof(size_t), &numDevices, NULL); + CL_ERROR(err, "clGetProgramInfo"); + if (err == CL_SUCCESS) + { +#ifdef CL_DEBUG + printf("There are %lu devices associated with this program %p.\n", numDevices, program); +#endif + // get the devices + err = clGetProgramInfo(program, CL_PROGRAM_DEVICES, sizeof(devices), devices, &numDevices); + CL_ERROR(err, "clGetProgramInfo"); + numDevices /= sizeof(cl_device_id); +#ifdef CL_DEBUG + printf("%u devices retrieved!\n",numDevices); +#endif + for (i = 0; i < numDevices; i++) + { + cl_device_type tmp = 0; + size_t bytes = 0; + // query each device and ask it what type it is. OR that into a singe bit field + + err = clGetDeviceInfo(devices[i], CL_DEVICE_TYPE, sizeof(tmp), &tmp, &bytes); + CL_ERROR(err, "clGetDeviceInfo"); + if (bytes == sizeof(tmp)) + { + deviceTypes |= tmp; + } + else + { + printf("ERROR!!!! Can't receive the CL_DEVICE_TYPE!\n"); + return NULL; + } + } +#ifdef CL_DEBUG + printf("CL_DEVICE_TYPE(s) = 0x%08x\n",deviceTypes); +#endif + // did it compile successfully? + err = clGetProgramBuildInfo(program, devices[0], CL_PROGRAM_BUILD_STATUS, sizeof(cl_int), &build_status, NULL); + CL_ERROR(err, "clGetProgramBuildInfo"); + if (err != CL_SUCCESS) + { + printf("ERROR: Build was not successful! (Error=%d, Build_Status=%d)\n",err, build_status); + return NULL; + } + if (build_status != CL_BUILD_SUCCESS) + { + size_t logSize = CL_LOG_SIZE; + char *log = malloc(CL_LOG_SIZE); + clBuildError(build_status, "clGetProgramBuildInfo", __FUNCTION__, __FILE__, __LINE__); + clGetProgramBuildInfo(program, devices[0], CL_PROGRAM_BUILD_LOG, logSize, log, &logSize); + printf("BUILD INFO ["FMT_SIZE_T"]:\n%s<deviceTypes = deviceTypes; + + err = clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, bins->numBytesSizes, bins->sizes, &numBinaries); + CL_ERROR(err, "clGetProgramInfo"); + if (err != CL_SUCCESS) + { + printf("Error: When requesting the number of binary outputs, error %d was returned\n", err); + cl_delete_kernel_bin(bins); + bins = NULL; + } + else if (err == CL_SUCCESS) + { + numBinaries /= sizeof(size_t); +#ifdef CL_DEBUG + printf("There are %lu binaries associated with this program %p\n", numBinaries, program); +#endif + for (i = 0; i < numBinaries; i++) + { +#ifdef CL_DEBUG + printf("Binary size for device %u is %lu\n", i, bins->sizes[i]); +#endif + bins->data[i] = (unsigned char *)cl_malloc(bins->sizes[i]); + } + err = clGetProgramInfo(program, CL_PROGRAM_BINARIES, bins->numBytesData, bins->data, &numBinaries2); + CL_ERROR(err, "clGetProgramInfo"); + numBinaries2 /= sizeof(unsigned char *); +#ifdef CL_DEBUG + printf("Wrote %u pointers to the binary structure!\n", numBinaries); +#endif + } + } + return bins; +} + +char **clLoadSources(char *filename, cl_uint *pNumLines) +{ + FILE *fp = fopen(filename, "r"); + cl_uint numLines = 0; + char **lines = NULL; + cl_uint i, lineSize = sizeof(char) * CL_MAX_LINESIZE; +#ifdef CL_DEBUG + printf("Reading file: %s (%p)\n",filename,fp); +#endif + if (fp != NULL) + { + numLines = (cl_uint)flines(fp); + *pNumLines = numLines; + lines = (char **)cl_malloc(numLines * sizeof(char *)); + if (lines != NULL) + { + for (i = 0; i < numLines; i++) + { + lines[i] = (char *)cl_malloc(lineSize); + if (lines[i]) + { + if (fgets(lines[i], lineSize, fp) == NULL) + printf("End of %s\n", filename); + } + else + { + for (i-=1; i >= 0; i--) + cl_free(lines[i]); + cl_free(lines); + lines = NULL; + break; + } + } + } + } + return lines; +} + +int cl_precompiled_header(char *filename, cl_kernel_bin_t *bins) +{ + FILE *fo = NULL; + size_t bw = 0; + if (filename[0] == '\0') + { + printf("ERROR: Filename is empty!\n"); + return 0; + } + fo = fopen(filename, "w+"); + if (fo != NULL) + { + cl_uint d, b; + bw += fprintf(fo, "// PRECOMPILED HEADER, DO NOT MODIFY!\n"); + bw += fprintf(fo, "#ifndef _PRECOMPILED_KERNEL_H_\n"); + bw += fprintf(fo, "#define _PRECOMPILED_KERNEL_H_\n"); + bw += fprintf(fo, "#include \n"); + bw += fprintf(fo, "static size_t gKernelBinarySizes["FMT_SIZE_T"] = {\n",bins->numDevices); + for (d = 0; d < bins->numDevices; d++) + bw += fprintf(fo, "\t"FMT_SIZE_T",\n", bins->sizes[d]); + bw += fprintf(fo, "};\n"); + for (d = 0; d < bins->numDevices; d++) + { + bw += fprintf(fo, "static cl_byte gKernelBinaryData%09u["FMT_SIZE_T"] = {\n", d, bins->sizes[d]); + for (b= 0 ; b < bins->sizes[d]; b++) + { + bw += fprintf(fo, "\t0x%02x,\n", bins->data[d][b]); + } + bw += fprintf(fo, "};\n"); + } + bw += fprintf(fo, "static cl_byte *gKernelBinaries["FMT_SIZE_T"] = {\n", bins->numDevices); + for (d = 0; d < bins->numDevices; d++) + { + bw += fprintf(fo, "\t(cl_byte *)&gKernelBinaryData%09u,\n", d); + } + bw += fprintf(fo, "};\n"); + bw += fprintf(fo, "static cl_kernel_bin_t gKernelBins = { 0x%08x, "FMT_SIZE_T", "FMT_SIZE_T", "FMT_SIZE_T", (size_t *)&gKernelBinarySizes, (cl_byte **)&gKernelBinaries };\n", (uint32_t)bins->deviceTypes, bins->numDevices, bins->numBytesSizes, bins->numBytesData); + bw += fprintf(fo, "#endif\n"); + bw += fclose(fo); + printf("Wrote %zu bytes to precompiled header\n", bw); + return 1; + } else { + printf("ERROR: Failed to open %s for writing\n", filename); + return 0; + } +} + +cl_environment_t *clCreateEnvironmentFromBins(cl_kernel_bin_t *bins, + clnotifier_f notifier, + char *cl_args) +{ + cl_int err = CL_SUCCESS; + cl_uint i,numPlatforms; + cl_uint numDevices = 0; + cl_environment_t *pEnv = cl_malloc_struct(cl_environment_t); + if (pEnv == NULL) + return NULL; + pEnv->numDevices = (cl_uint)bins->numDevices; + pEnv->devices = cl_malloc_array(cl_device_id, pEnv->numDevices); + pEnv->queues = cl_malloc_array(cl_command_queue, pEnv->numDevices); + if (pEnv->devices == NULL || pEnv->queues == NULL) + { + printf("ERROR: Failed allocate data structures for compilation.\n"); + clDeleteEnvironment(pEnv); + return NULL; + } + err = clGetPlatformIDs(1, &pEnv->platform, &numPlatforms); + CL_ERROR(err, "clGetPlatformIDs"); + if (err != CL_SUCCESS) + { + printf("ERROR: Failed to get any platform ID for OpenCL (%d)\n", err); + clDeleteEnvironment(pEnv); + return NULL; + } + else if (err == CL_SUCCESS && pEnv->platform) + { + cl_context_properties props[] = {(cl_context_properties)CL_CONTEXT_PLATFORM, + (cl_context_properties)pEnv->platform, + (cl_context_properties)0}; +#ifdef CL_DEBUG + printf("Platform ID %p\n", pEnv->platform); +#endif + err = clGetDeviceIDs(pEnv->platform, bins->deviceTypes, pEnv->numDevices, pEnv->devices, &numDevices); + if (err == CL_SUCCESS) + { +#ifdef CL_DEBUG + printf("Returned %u devices! (Asked for %u)\n", numDevices, pEnv->numDevices); + if (numDevices > pEnv->numDevices) + printf("Using only the requested number of devices!\n"); + for (i = 0; i < pEnv->numDevices; i++) + printf("Device ID[%02x] = %p\n", i, pEnv->devices[i]); +#endif + pEnv->context = clCreateContext(props, pEnv->numDevices, pEnv->devices, NULL, NULL, &err); + if (pEnv->context) + { +#ifdef CL_DEBUG + printf("Created context %p about to create %u queues\n",pEnv->context, pEnv->numDevices); +#endif + // create the command queues + for (i = 0; i < pEnv->numDevices; i++) + { + pEnv->queues[i] = clCreateCommandQueue(pEnv->context, pEnv->devices[i], CL_QUEUE_PROFILING_ENABLE, &err); + if (pEnv->queues[i] == NULL) + { + clDeleteEnvironment(pEnv); + return NULL; + } + } + // we aren't loading from sources, so that pointer will remain NULL + + // need to allocate retCodes though + pEnv->retCodes = cl_malloc_array(cl_int, pEnv->numDevices); + if (pEnv->retCodes == NULL) + { + clDeleteEnvironment(pEnv); + return NULL; + } + + // create the program from binaries + pEnv->program = clCreateProgramWithBinary(pEnv->context, pEnv->numDevices, pEnv->devices, bins->sizes, (const unsigned char **)bins->data, pEnv->retCodes, &err); + if (err != CL_SUCCESS) + { + printf("Failed to create program Error=%d!\n",err); + clDeleteEnvironment(pEnv); + return NULL; + } +#ifdef CL_DEBUG + printf("Created Program %p\n",pEnv->program); +#endif + // now actually build the program! + err = clBuildProgram(pEnv->program, pEnv->numDevices, pEnv->devices, cl_args, notifier, NULL); + if (err != CL_SUCCESS) + { + printf("Error building kernels! Error=%d: ",err); + switch (err) + { + case CL_INVALID_VALUE: + printf("Invalid value!\n"); + break; + case CL_INVALID_DEVICE: + printf("Invalid device!\n"); + break; + case CL_INVALID_BINARY: + printf("Invalid binary!\n"); + break; + case CL_INVALID_PROGRAM: + printf("Invalid program\n"); + break; + case CL_INVALID_BUILD_OPTIONS: + printf("Invalid build options!\n"); + break; + case CL_BUILD_PROGRAM_FAILURE: + { + size_t logSize = 10*1024; + char *log = (char *)cl_malloc(logSize); + printf("Build failure!\n"); + + err = clGetProgramBuildInfo(pEnv->program, pEnv->devices[0], CL_PROGRAM_BUILD_LOG, logSize, log, &logSize); + if (err == CL_SUCCESS) + printf("Log["FMT_SIZE_T"]: %s\n", logSize,log); + else + printf("Could not get build log! Error=%d\n",err); + cl_free(log); + break; + } + default: + printf("Unknown\n"); + break; + } + clDeleteEnvironment(pEnv); + return NULL; + } + + printf("No build errors\n"); + +#ifndef CL_ITERATIVE_QUERY + // do the initial query to find the exact number of kernels + err = clCreateKernelsInProgram(pEnv->program, 0, NULL, &pEnv->numKernels); + if (err != CL_SUCCESS || pEnv->numKernels == 0) + { + printf("ERROR! Failed to retreived the number of compiled kernels! (%u)\n",pEnv->numKernels); + clDeleteEnvironment(pEnv); + return NULL; + } +#else + // now we're going to try to allocate the number of kernels + // within the program by guessing a number and cl_malloc/freeing + // until that number is correct (so long as we get the error code + // that we are looking for). + pEnv->numKernels = 1; // assume 1 kernel +#endif + do { + // create the kernels + pEnv->kernels = cl_malloc_array(cl_kernel,pEnv->numKernels); + pEnv->retCodes = cl_malloc_array(cl_int,pEnv->numKernels); + if (pEnv->kernels == NULL || pEnv->retCodes == NULL) + { + printf("ERROR: Failed to allocate memory for kernel objects and return codes.\n"); + clDeleteEnvironment(pEnv); + pEnv = NULL; + break; + } + else + { +#ifdef CL_DEBUG + printf("Allocated room for %u kernels\n",pEnv->numKernels); +#endif + err = clCreateKernelsInProgram(pEnv->program, pEnv->numKernels, pEnv->kernels, &pEnv->numKernels); +#ifdef CL_DEBUG + printf("Queried for %u kernels\n", pEnv->numKernels); + CL_ERROR(err, "clCreateKernelsInProgram"); +#endif + if (err == CL_SUCCESS) + { + cl_uint j; + char function_name[CL_MAX_STRING]; + size_t len; + cl_uint numArgs; +#ifdef CL_DEBUG + printf("There were %u kernels in the supplied file!\n",pEnv->numKernels); +#endif + for (j = 0; j < pEnv->numKernels; j++) + { + clGetKernelInfo(pEnv->kernels[j], CL_KERNEL_FUNCTION_NAME, sizeof(function_name), function_name, &len); + clGetKernelInfo(pEnv->kernels[j], CL_KERNEL_NUM_ARGS, sizeof(numArgs), &numArgs, &len); + printf("SYMBOL: %s :: %u (%p)\n",function_name, numArgs, pEnv->kernels[j]); + } + } + else if (err == CL_INVALID_KERNEL_DEFINITION) + { + // something is terribly wrong (NVIDIA!!!!) + clDeleteEnvironment(pEnv); + return NULL; + } + else // if (err == CL_INVALID_VALUE) + { + printf("Only %u values were filled in!\n", pEnv->numKernels); + if (pEnv->kernels[0] != NULL) + printf("WARNING! Some Kernel Values were filled in!\n"); + cl_free(pEnv->kernels); + cl_free(pEnv->retCodes); + pEnv->numKernels++; + } + } + } while (err != CL_SUCCESS); + } + } + } + return pEnv; +} + + +cl_environment_t *clCreateEnvironment(char *filename, + cl_uint dev_types, + cl_uint numDevices, + clnotifier_f notifier, + char *cl_args) +{ + cl_int err; + cl_uint i; + cl_uint numPlatforms = 0; + + cl_environment_t *pEnv = cl_malloc_struct(cl_environment_t); + if (pEnv == NULL) + return NULL; + pEnv->devices = cl_malloc_array(cl_device_id,numDevices); + pEnv->queues = cl_malloc_array(cl_command_queue,numDevices); + if (pEnv->devices == NULL || pEnv->queues == NULL) + { + clDeleteEnvironment(pEnv); + return NULL; + } + printf("Environment: %p\n", pEnv); + err = clGetPlatformIDs(1, &pEnv->platform, &numPlatforms); + if (err == CL_SUCCESS && pEnv->platform) + { + cl_context_properties props[] = {(cl_context_properties)CL_CONTEXT_PLATFORM, + (cl_context_properties)pEnv->platform, + (cl_context_properties)0}; +#ifdef CL_DEBUG + printf("Platform ID %p\n", pEnv->platform); + //clPrintAllPlatformInfo(pEnv->platform); +#endif + pEnv->numDevices = numDevices; +#ifdef CL_DEBUG + printf("Requesting %u devices\n",numDevices); +#endif + err = clGetDeviceIDs(pEnv->platform, dev_types, pEnv->numDevices, pEnv->devices, &numDevices); + if (err == CL_SUCCESS) + { +#ifdef CL_DEBUG + printf("Returned %u devices! (Asked for %u)\n", numDevices, pEnv->numDevices); + if (numDevices > pEnv->numDevices) + printf("Using only the requested number of devices!\n"); + for (i = 0; i < pEnv->numDevices; i++) + printf("Device ID[%02x] = %p\n", i, pEnv->devices[i]); +#endif + pEnv->context = clCreateContext(props, pEnv->numDevices, pEnv->devices, NULL, NULL, &err); + if (pEnv->context) + { +#ifdef CL_DEBUG + printf("Created context %p about to create %u queues\n",pEnv->context, pEnv->numDevices); +#endif + // create the command queues + for (i = 0; i < pEnv->numDevices; i++) + { + pEnv->queues[i] = clCreateCommandQueue(pEnv->context, pEnv->devices[i], CL_QUEUE_PROFILING_ENABLE, &err); + if (pEnv->queues[i] == NULL) + { + clDeleteEnvironment(pEnv); + return NULL; + } + } + + // load source from a file + pEnv->sources = clLoadSources(filename, &pEnv->numLines); + pEnv->lengths = cl_malloc_array(size_t,pEnv->numLines); + if (pEnv->lengths && pEnv->sources) + { + for (i = 0; i < pEnv->numLines; i++) + pEnv->lengths[i] = strlen(pEnv->sources[i]); +#ifdef CL_DEBUG + for (i = 0; i < pEnv->numLines; i++) + printf("[%4u] %s",pEnv->lengths[i],pEnv->sources[i]); +#endif + } + else + { + clDeleteEnvironment(pEnv); + return NULL; + } + + // create the program from source + pEnv->program = clCreateProgramWithSource(pEnv->context, pEnv->numLines, (const char **)pEnv->sources, pEnv->lengths, &err); + if (err != CL_SUCCESS) + { + printf("Failed to create program Error=%d!\n",err); + clDeleteEnvironment(pEnv); + return NULL; + } +#ifdef CL_DEBUG + printf("Created Program %p\n",pEnv->program); +#endif + // now actually build the program! + err = clBuildProgram(pEnv->program, pEnv->numDevices, pEnv->devices, cl_args, notifier, NULL); + if (err != CL_SUCCESS) + { + CL_ERROR(err, "clBuildProgram"); + switch (err) + { + case CL_INVALID_VALUE: + printf("Invalid value!\n"); + break; + case CL_INVALID_DEVICE: + printf("Invalid device!\n"); + break; + case CL_INVALID_BINARY: + printf("Invalid binary!\n"); + break; + case CL_INVALID_PROGRAM: + printf("Invalid program\n"); + break; + case CL_INVALID_BUILD_OPTIONS: + printf("Invalid build options!\n"); + break; + case CL_BUILD_PROGRAM_FAILURE: + { + size_t logSize = 10*1024; + char *log = (char *)cl_malloc(logSize); + printf("Build failure!\n"); + + err = clGetProgramBuildInfo(pEnv->program, pEnv->devices[0], CL_PROGRAM_BUILD_LOG, logSize, log, &logSize); + if (err == CL_SUCCESS) + printf("Log["FMT_SIZE_T"]: %s\n", logSize,log); + else + printf("Could not get build log! Error=%d\n",err); + cl_free(log); + break; + } + default: + printf("Unknown\n"); + break; + } + clDeleteEnvironment(pEnv); + return NULL; + } + + printf("No build errors\n"); + +#ifndef CL_ITERATIVE_QUERY + // do the initial query to find the exact number of kernels + err = clCreateKernelsInProgram(pEnv->program, 0, NULL, &pEnv->numKernels); + CL_ERROR(err, "clCreateKernelsInProgram"); + if (err != CL_SUCCESS || pEnv->numKernels == 0) + { + printf("ERROR! Failed to retreived the number of compiled kernels! (%u)\n",pEnv->numKernels); + clDeleteEnvironment(pEnv); + return NULL; + } +#else + // now we're going to try to allocate the number of kernels + // within the program by guessing a number and cl_malloc/freeing + // until that number is correct (so long as we get the error code + // that we are looking for). + pEnv->numKernels = 1; // assume 1 kernel to start with +#endif + + do { + // create the kernels + pEnv->kernels = cl_malloc_array(cl_kernel,pEnv->numKernels); + pEnv->retCodes = cl_malloc_array(cl_int,pEnv->numKernels); + if (pEnv->kernels == NULL || pEnv->retCodes == NULL) + { + printf("ERROR: Failed to allocate memory for kernel objects and return codes.\n"); + clDeleteEnvironment(pEnv); + pEnv = NULL; + break; + } + else + { +#ifdef CL_DEBUG + printf("Allocated room for %u kernels\n",pEnv->numKernels); +#endif + err = clCreateKernelsInProgram(pEnv->program, pEnv->numKernels, pEnv->kernels, &pEnv->numKernels); +#ifdef CL_DEBUG + printf("Queried for %u kernels\n", pEnv->numKernels); + CL_ERROR(err, "clCreateKernelsInProgram"); +#endif + if (err == CL_SUCCESS) + { + cl_uint j; + char function_name[CL_MAX_STRING]; + size_t len; + cl_uint numArgs; +#ifdef CL_DEBUG + printf("There were %u kernels in the supplied file!\n",pEnv->numKernels); +#endif + for (j = 0; j < pEnv->numKernels; j++) + { + clGetKernelInfo(pEnv->kernels[j], CL_KERNEL_FUNCTION_NAME, sizeof(function_name), function_name, &len); + clGetKernelInfo(pEnv->kernels[j], CL_KERNEL_NUM_ARGS, sizeof(numArgs), &numArgs, &len); + printf("SYMBOL: %s :: %u (%p)\n",function_name, numArgs, pEnv->kernels[j]); + } + } + else if (err == CL_INVALID_KERNEL_DEFINITION) + { + // something is terribly wrong (NVIDIA!!!!) + clDeleteEnvironment(pEnv); + return NULL; + } + else // if (err == CL_INVALID_VALUE) + { + printf("Only %u kernels were returned!\n", pEnv->numKernels); + if (pEnv->kernels[0] != NULL) + printf("WARNING! Some Kernel Values were filled in!\n"); + cl_free(pEnv->kernels); + cl_free(pEnv->retCodes); + pEnv->numKernels++; + } + } + } while (err != CL_SUCCESS); + } + } + else + { + printf("ERROR: Failed to acquire devices of type: %u\n", dev_types); + } + } + return pEnv; +} + +cl_kernel clGetKernelByName(cl_environment_t *pEnv, char *func_name) +{ + cl_uint i = 0; + char name[CL_MAX_STRING]; + size_t len = CL_MAX_STRING * sizeof(cl_char); +#ifdef CL_DEBUG + printf("Looking for kernel %s out of %u\n", func_name, pEnv->numKernels); +#endif + for (i = 0; i < pEnv->numKernels; i++) + { + cl_int err = clGetKernelInfo(pEnv->kernels[i], CL_KERNEL_FUNCTION_NAME, sizeof(name), name, &len); +#ifdef CL_DEBUG + printf("Found SYMBOL[%06u] (%lu) %s\n", i, len, name); +#endif + if (err == CL_SUCCESS && strncmp(name, func_name, CL_MAX_STRING) == 0) + { + return pEnv->kernels[i]; + } + } + return NULL; +} + +cl_int clCallKernel(cl_environment_t *pEnv, cl_kernel_call_t *pCall, cl_uint numCalls) +{ + cl_int err = CL_SUCCESS; + cl_uint i = 0, j = 0, k = 0; + + if (pEnv == NULL || pEnv->kernels == NULL) + return CL_INVALID_ARG_VALUE; + + for (k = 0; k < numCalls; k++) + { + cl_kernel kernel = clGetKernelByName(pEnv, pCall[k].kernel_name); + if (kernel == NULL) + return CL_INVALID_KERNEL_NAME; + + for (j = 0; j < pCall[k].numParams; j++) + { + if (pCall[k].params[j].type == CL_KPARAM_BUFFER_0D) + { + pCall[k].params[j].mem = NULL; + } + else if (pCall[k].params[j].type == CL_KPARAM_BUFFER_1D) + { + pCall[k].params[j].mem = clCreateBuffer(pEnv->context, pCall[k].params[j].flags, pCall[k].params[j].numBytes, NULL, &err); + #ifdef CL_DEBUG + printf("Create Buffer from %p for %lu bytes with 0x%08x flags (mem=%p, err=%d)\n", + pCall[k].params[j].data, + pCall[k].params[j].numBytes, + (cl_uint)pCall[k].params[j].flags, + pCall[k].params[j].mem, + err); + #endif + cl_assert((err == CL_SUCCESS), printf("Failed to create 1D cl_mem object of %u bytes!\n", pCall[k].params[j].numBytes)); + } + else if (pCall[k].params[j].type == CL_KPARAM_BUFFER_2D) + { + cl_nd_buffer_t *pBuf = (cl_nd_buffer_t *)pCall[k].params[j].data; + cl_image_format *pIf = &pBuf->format; + pCall[k].params[j].mem = clCreateImage2D(pEnv->context, pCall[k].params[j].flags, pIf, pBuf->dim[X_DIM], pBuf->dim[Y_DIM], pBuf->strides[Y_DIM], NULL, &err); + #ifdef CL_DEBUG + printf("Create Image2D from %p for %lu bytes with 0x%08x flags (mem=%p, err=%d)\n", + pCall[k].params[j].data, + pCall[k].params[j].numBytes, + (cl_uint)pCall[k].params[j].flags, + pCall[k].params[j].mem, + err); + #endif + cl_assert((err == CL_SUCCESS), printf("Failed to create 2D cl_mem object of %u bytes!\n",pCall[k].params[j].numBytes)); + } + else if (pCall[k].params[j].type == CL_KPARAM_BUFFER_3D) + { + cl_nd_buffer_t *pBuf = (cl_nd_buffer_t *)pCall[k].params[j].data; + cl_image_format *pIf = &pBuf->format; + pCall[k].params[j].mem = clCreateImage3D(pEnv->context, pCall[k].params[j].flags, pIf, pBuf->dim[X_DIM], pBuf->dim[Y_DIM], pBuf->dim[Z_DIM], pBuf->strides[Y_DIM], pBuf->strides[Z_DIM], NULL, &err); + #ifdef CL_DEBUG + printf("Create Image3D from %p for %lu bytes with 0x%08x flags (mem=%p, err=%d)\n", + pCall[k].params[j].data, + pCall[k].params[j].numBytes, + (cl_uint)pCall[k].params[j].flags, + pCall[k].params[j].mem, + err); + #endif + cl_assert((err == CL_SUCCESS), printf("Failed to create cl_mem object!\n")); + } + } + + // enqueue the writes + for (i = 0; i < pEnv->numDevices; i++) + { + for (j = 0; j < pCall[k].numParams; j++) + { + if (pCall[k].params[j].flags == CL_MEM_READ_ONLY || + pCall[k].params[j].flags == CL_MEM_READ_WRITE) + { + #ifdef CL_DEBUG + printf("Copying mem %p from ptr %p for %lu bytes\n", pCall[k].params[j].mem, pCall[k].params[j].data, pCall[k].params[j].numBytes); + #endif + if (pCall[k].params[j].type == CL_KPARAM_BUFFER_1D) + err = clEnqueueWriteBuffer(pEnv->queues[i], pCall[k].params[j].mem, CL_TRUE, 0, pCall[k].params[j].numBytes, pCall[k].params[j].data, 0, NULL, &pCall[k].params[j].event); + else if (pCall[k].params[j].type == CL_KPARAM_BUFFER_2D || pCall[k].params[j].type == CL_KPARAM_BUFFER_3D) + { + cl_nd_buffer_t *pBuf = (cl_nd_buffer_t *)pCall[k].params[j].data; + err = clEnqueueWriteBuffer(pEnv->queues[i], pCall[k].params[j].mem, CL_TRUE, 0, pBuf->size, pBuf->data[0], 0, NULL, &pCall[k].params[j].event); + } + cl_assert((err == CL_SUCCESS),printf("ERROR: Write Enqueue Error = %d\n",err)); + } + } + } + + // finish + for (i = 0; i < pEnv->numDevices; i++) + clFinish(pEnv->queues[i]); + + // enqueue the kernel + for (i = 0; i < pEnv->numDevices; i++) { + for (j = 0; j < pCall[k].numParams; j++) { + #ifdef CL_DEBUG + printf("ARG[%2u] mem %p (%lu)\n", j, pCall[k].params[j].mem, sizeof(cl_mem)); + #endif + if (pCall[k].params[j].type == CL_KPARAM_BUFFER_0D) + err = clSetKernelArg(kernel, j, pCall[k].params[j].numBytes, pCall[k].params[j].data); + else if (pCall[k].params[j].type == CL_KPARAM_LOCAL) + err = clSetKernelArg(kernel, j, pCall[k].params[j].numBytes, NULL); + else + err = clSetKernelArg(kernel, j, sizeof(cl_mem), &pCall[k].params[j].mem); + cl_assert((err == CL_SUCCESS),printf("ERROR: Kernel Arg %d is wrong (Error=%d)\n", j, err)); + } + err = clEnqueueNDRangeKernel(pEnv->queues[i], + kernel, + pCall[k].numDim, + NULL, //pCall[k].global_work_offset, + pCall[k].global_work_size, + pCall[k].local_work_size, + 0, NULL, &pCall[k].event); + cl_assert((err == CL_SUCCESS),printf("ERROR: Work Queue Error = %d\n",err)); + } + + // finish + for (i = 0; inumDevices; i++) + clFinish(pEnv->queues[i]); + + err = clGetEventProfilingInfo(pCall[k].event, CL_PROFILING_COMMAND_START, sizeof(cl_ulong), &pCall[k].start, NULL); + cl_assert(err == CL_SUCCESS,printf("Error=%d\n",err)); + err = clGetEventProfilingInfo(pCall[k].event, CL_PROFILING_COMMAND_END, sizeof(cl_ulong), &pCall[k].stop, NULL); + cl_assert(err == CL_SUCCESS,printf("Error=%d\n",err)); + #ifdef CL_DEBUG + printf("Executed kernel %s!\n",pCall[k].kernel_name); + #endif + + // read the result memory + for (i = 0; inumDevices; i++) + { + for (j = 0; j < pCall[k].numParams; j++) + { + if (pCall[k].params[j].flags == CL_MEM_WRITE_ONLY || + pCall[k].params[j].flags == CL_MEM_READ_WRITE) + { + err = CL_SUCCESS; + if (pCall[k].params[j].type == CL_KPARAM_BUFFER_1D) + err = clEnqueueReadBuffer(pEnv->queues[i], pCall[k].params[j].mem, CL_TRUE, 0, pCall[k].params[j].numBytes, pCall[k].params[j].data, 0, NULL, NULL); + else if (pCall[k].params[j].type == CL_KPARAM_BUFFER_2D || pCall[k].params[j].type == CL_KPARAM_BUFFER_3D) + { + cl_nd_buffer_t *pBuf = (cl_nd_buffer_t *)pCall[k].params[j].data; + err = clEnqueueReadBuffer(pEnv->queues[i], pCall[k].params[j].mem, CL_TRUE, 0, pBuf->size, pBuf->data[0], 0, NULL, &pCall[k].params[j].event); + } + cl_assert((err == CL_SUCCESS),printf("ERROR: Read Enqueue Error=%d\n",err)); + } + } + } + // finish + for (i = 0; inumDevices; i++) + clFinish(pEnv->queues[i]); + + for (i = 0; i < pEnv->numDevices; i++) + clPrintAllKernelWorkInfo(kernel, pEnv->devices[i]); + + for (j = 0; j < pCall[k].numParams; j++) + { + clReleaseMemObject(pCall[k].params[j].mem); + } + pCall[k].err = err; + if (err != CL_SUCCESS) + break; + } + return err; +} + +cl_uint clGetTypeFromString(char *typestring) +{ + if (strncmp(typestring, "all",4) == 0) + return CL_DEVICE_TYPE_ALL; + else if (strncmp(typestring,"gpu",4) == 0) + return CL_DEVICE_TYPE_GPU; + else if (strncmp(typestring,"cpu",4) == 0) + return CL_DEVICE_TYPE_CPU; + else if (strncmp(typestring,"acc",4) == 0 || strncmp(typestring,"accelerator",12) == 0) + return CL_DEVICE_TYPE_ACCELERATOR; + else + return CL_DEVICE_TYPE_DEFAULT; +} diff --git a/libraries/public/ocl/clmath.c b/libraries/public/ocl/clmath.c new file mode 100644 index 0000000..1f053ae --- /dev/null +++ b/libraries/public/ocl/clmath.c @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief The "OpenCL Environment" math library. + * \see http://github.com/emrainey/OpenCL-Environment + * \author Erik Rainey + */ + +#include +#include +#include +#include +#include +#ifdef DARWIN +#include +#else +#include +#endif + +int ipow(int x, int n) +{ + if (n == 0) + return 1; + else if (n == 1) + return x; + else + return x * ipow(x, n - 1); +} + +cl_uint isqrt(cl_int x) +{ + float xp = (float)x; + return (cl_uint)sqrt(xp); +} + +float frand(void) +{ + return (float)(rand()%1000)/999; +} + +float frrand(float low, float hi) +{ + float r = hi + low; + int p = 5; // arbitrary precision + int n = ipow(10,p); + float v = (float)(rand()%n)/(n-1); + float x = (v * r) + low; + //printf("frand [%lf, %lf] n=%d, v=%lf, x=%lf\n", low, hi, n, v,x); + return x; +} + +float fsum(float *a, cl_uint num) +{ + float b = 0.0; + cl_uint i = 0; + for (i = 0; i < num; i++) + b += a[i]; + return b; +} + +int rrand(int low, int hi) +{ + int r = hi - low; + return (rand() % r) + low; +} + +void frand4(cl_float4 f, cl_int l, cl_int h) +{ +#if 0 // defined(DARWIN) + f[0] = frand() * ipow(10, rrand(l,h)); + f[1] = frand() * ipow(10, rrand(l,h)); + f[2] = frand() * ipow(10, rrand(l,h)); + f[3] = frand() * ipow(10, rrand(l,h)); +#else + f.s[0] = frand() * ipow(10, rrand(l,h)); + f.s[1] = frand() * ipow(10, rrand(l,h)); + f.s[2] = frand() * ipow(10, rrand(l,h)); + f.s[3] = frand() * ipow(10, rrand(l,h)); +#endif +} + +void normalize_float(float *a, cl_int low, cl_int hi, cl_uchar *b, cl_uint numPixels) +{ + cl_uint i = 0; + cl_uint range = hi - low; + //printf("Range for %p is %d to %d (%d)\n", a, low, hi, range); + for (i = 0; i < numPixels; i++) + { + cl_int c = (cl_int)((range * a[i]) + low); + //printf("a = %lf, c = %d\n",a[i], c); + if (c > hi) + b[i] = (cl_uchar)hi; + else if (c < low) + b[i] = (cl_uchar)low; + else + b[i] = (cl_uchar)c; + } +} diff --git a/libraries/public/ocl/clquery.c b/libraries/public/ocl/clquery.c new file mode 100644 index 0000000..4a05bed --- /dev/null +++ b/libraries/public/ocl/clquery.c @@ -0,0 +1,398 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/*! \file + * \brief The "OpenCL Environment" query interface + * \see http://github.com/emrainey/OpenCL-Environment + * \author Erik Rainey + */ + +#include +#include +#include +#ifdef DARWIN +#include +#else +#include +#endif +#include + +typedef enum _cl_type_e { + CL_STRING_TYPE, // char[] + CL_ULONG_TYPE, // cl_ulong + CL_SIZET_TYPE, // size_t + CL_UINT_TYPE, // cl_uint + CL_BOOL_TYPE, // cl_bool + CL_DEVFPCFG_TYPE, // cl_device_fp_config + CL_DEVEXCCAP_TYPE, // cl_device_exec_capabilities + CL_DEVMEMCHE_TYPE, // cl_device_mem_cache_type + CL_LCLDEVMEM_TYPE, // cl_device_local_mem_type + CL_PLATFORM_TYPE, // cl_platform_id + CL_CMDQUEUE_TYPE, // cl_command_queue_properties + CL_DEVTYPE_TYPE, // cl_device_type +} cl_type_e; + +#define L_STRINGERIZE(x) #x, x + +typedef struct _cl_info_type_t { + cl_type_e type; + cl_uint count; + char *name; + cl_uint info; +} cl_info_type_t; + +cl_info_type_t clPlatInfoType[] = { + {CL_STRING_TYPE, CL_MAX_STRING, L_STRINGERIZE(CL_PLATFORM_PROFILE)}, + {CL_STRING_TYPE, CL_MAX_STRING, L_STRINGERIZE(CL_PLATFORM_VERSION)}, + {CL_STRING_TYPE, CL_MAX_STRING, L_STRINGERIZE(CL_PLATFORM_NAME)}, + {CL_STRING_TYPE, CL_MAX_STRING, L_STRINGERIZE(CL_PLATFORM_VENDOR)}, + {CL_STRING_TYPE, CL_MAX_STRING, L_STRINGERIZE(CL_PLATFORM_EXTENSIONS)}, +}; +cl_info_type_t clDeviceInfoType[] = { + {CL_DEVTYPE_TYPE, 1, L_STRINGERIZE(CL_DEVICE_TYPE)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_VENDOR_ID)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_MAX_COMPUTE_UNITS)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS)}, + {CL_SIZET_TYPE, 1, L_STRINGERIZE(CL_DEVICE_MAX_WORK_GROUP_SIZE)}, + {CL_SIZET_TYPE, 3, L_STRINGERIZE(CL_DEVICE_MAX_WORK_ITEM_SIZES)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_MAX_CLOCK_FREQUENCY)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_ADDRESS_BITS)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_MAX_READ_IMAGE_ARGS)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_MAX_WRITE_IMAGE_ARGS)}, + {CL_ULONG_TYPE, 1, L_STRINGERIZE(CL_DEVICE_MAX_MEM_ALLOC_SIZE)}, + {CL_SIZET_TYPE, 1, L_STRINGERIZE(CL_DEVICE_IMAGE2D_MAX_WIDTH)}, + {CL_SIZET_TYPE, 1, L_STRINGERIZE(CL_DEVICE_IMAGE2D_MAX_HEIGHT)}, + {CL_SIZET_TYPE, 1, L_STRINGERIZE(CL_DEVICE_IMAGE3D_MAX_WIDTH)}, + {CL_SIZET_TYPE, 1, L_STRINGERIZE(CL_DEVICE_IMAGE3D_MAX_HEIGHT)}, + {CL_SIZET_TYPE, 1, L_STRINGERIZE(CL_DEVICE_IMAGE3D_MAX_DEPTH)}, + {CL_BOOL_TYPE, 1, L_STRINGERIZE(CL_DEVICE_IMAGE_SUPPORT)}, + {CL_SIZET_TYPE, 1, L_STRINGERIZE(CL_DEVICE_MAX_PARAMETER_SIZE)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_MAX_SAMPLERS)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_MEM_BASE_ADDR_ALIGN)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE)}, + {CL_DEVFPCFG_TYPE, 1, L_STRINGERIZE(CL_DEVICE_SINGLE_FP_CONFIG)}, +#if 0 + {CL_DEVFPCFG_TYPE, 1, L_STRINGERIZE(CL_DEVICE_HALF_FP_CONFIG)}, + {CL_DEVFPCFG_TYPE, 1, L_STRINGERIZE(CL_DEVICE_DOUBLE_FP_CONFIG)}, +#endif + {CL_DEVMEMCHE_TYPE, 1, L_STRINGERIZE(CL_DEVICE_GLOBAL_MEM_CACHE_TYPE)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE)}, + {CL_ULONG_TYPE, 1, L_STRINGERIZE(CL_DEVICE_GLOBAL_MEM_CACHE_SIZE)}, + {CL_ULONG_TYPE, 1, L_STRINGERIZE(CL_DEVICE_GLOBAL_MEM_SIZE)}, + {CL_ULONG_TYPE, 1, L_STRINGERIZE(CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE)}, + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_DEVICE_MAX_CONSTANT_ARGS)}, + {CL_LCLDEVMEM_TYPE, 1, L_STRINGERIZE(CL_DEVICE_LOCAL_MEM_TYPE)}, + {CL_ULONG_TYPE, 1, L_STRINGERIZE(CL_DEVICE_LOCAL_MEM_SIZE)}, + {CL_BOOL_TYPE, 1, L_STRINGERIZE(CL_DEVICE_ERROR_CORRECTION_SUPPORT)}, + {CL_SIZET_TYPE, 1, L_STRINGERIZE(CL_DEVICE_PROFILING_TIMER_RESOLUTION)}, + {CL_BOOL_TYPE, 1, L_STRINGERIZE(CL_DEVICE_ENDIAN_LITTLE)}, + {CL_BOOL_TYPE, 1, L_STRINGERIZE(CL_DEVICE_AVAILABLE)}, + {CL_BOOL_TYPE, 1, L_STRINGERIZE(CL_DEVICE_COMPILER_AVAILABLE)}, + {CL_DEVEXCCAP_TYPE, 1, L_STRINGERIZE(CL_DEVICE_EXECUTION_CAPABILITIES)}, + {CL_CMDQUEUE_TYPE, 1, L_STRINGERIZE(CL_DEVICE_QUEUE_PROPERTIES)}, + {CL_STRING_TYPE, CL_MAX_STRING, L_STRINGERIZE(CL_DEVICE_NAME)}, + {CL_STRING_TYPE, CL_MAX_STRING, L_STRINGERIZE(CL_DEVICE_VENDOR)}, + {CL_STRING_TYPE, CL_MAX_STRING, L_STRINGERIZE(CL_DEVICE_VERSION)}, + {CL_STRING_TYPE, CL_MAX_STRING, L_STRINGERIZE(CL_DEVICE_PROFILE)}, + {CL_STRING_TYPE, CL_MAX_STRING, L_STRINGERIZE(CL_DEVICE_EXTENSIONS)}, + {CL_STRING_TYPE, CL_MAX_STRING, L_STRINGERIZE(CL_DRIVER_VERSION)}, + {CL_PLATFORM_TYPE, 1, L_STRINGERIZE(CL_DEVICE_PLATFORM)}, +}; +cl_info_type_t clContextInfoType[] = { + {CL_UINT_TYPE, 1, L_STRINGERIZE(CL_CONTEXT_REFERENCE_COUNT)}, + {CL_ULONG_TYPE, 1, L_STRINGERIZE(CL_CONTEXT_DEVICES)}, + {CL_UINT_TYPE, 10, L_STRINGERIZE(CL_CONTEXT_PROPERTIES)}, +}; +cl_info_type_t clQueueInfoType[] = { + {CL_UINT_TYPE, 1,L_STRINGERIZE(CL_QUEUE_CONTEXT)}, + {CL_UINT_TYPE, 1,L_STRINGERIZE(CL_QUEUE_DEVICE)}, + {CL_UINT_TYPE, 1,L_STRINGERIZE(CL_QUEUE_REFERENCE_COUNT)}, + {CL_UINT_TYPE, 10,L_STRINGERIZE(CL_QUEUE_PROPERTIES)}, +}; +cl_info_type_t clKernelInfoType[] = { + {CL_STRING_TYPE, CL_MAX_STRING, L_STRINGERIZE(CL_KERNEL_FUNCTION_NAME)}, + {CL_UINT_TYPE, 1,L_STRINGERIZE(CL_KERNEL_NUM_ARGS)}, + {CL_UINT_TYPE, 1,L_STRINGERIZE(CL_KERNEL_REFERENCE_COUNT)}, + {CL_UINT_TYPE, 1,L_STRINGERIZE(CL_KERNEL_CONTEXT)}, + {CL_UINT_TYPE, 1,L_STRINGERIZE(CL_KERNEL_PROGRAM)}, +}; +cl_info_type_t clKernelWorkInfoType[] = { + {CL_SIZET_TYPE, 1, L_STRINGERIZE(CL_KERNEL_WORK_GROUP_SIZE)}, + {CL_SIZET_TYPE, 3, L_STRINGERIZE(CL_KERNEL_COMPILE_WORK_GROUP_SIZE)}, + {CL_ULONG_TYPE, 1, L_STRINGERIZE(CL_KERNEL_LOCAL_MEM_SIZE)}, +}; +cl_uint numPlatInfoTypes = dimof(clPlatInfoType); +cl_uint numDeviceInfoTypes = dimof(clDeviceInfoType); +cl_uint numContextInfoTypes = dimof(clContextInfoType); +cl_uint numQueueInfoTypes = dimof(clQueueInfoType); +cl_uint numKernelInfoTypes = dimof(clKernelInfoType); +cl_uint numKernelWorkInfoTypes = dimof(clKernelWorkInfoType); + +/** This function allows us to type-cast the various query functions */ +typedef cl_int (*QueryInfo_f)(void *, cl_uint, size_t, void *, size_t *); + +// atomic or array +// query format or not +// size == sizeof(param) or > 0 +// format string type +// + +#define CL_QUERY_ATOMIC_TYPE(err, type, query, id, info, size, types, index, format) {\ + type param;\ + char format_str[CL_MAX_STRING];\ + memset(¶m, 0, sizeof(param));\ + err = query(id, info, sizeof(param), ¶m, &size);\ + if (size == sizeof(type)) {\ + sprintf(format_str, "%%41s:[%%02lu] %s\n", format);\ + printf(format_str, types[index].name, size, param);\ + } else {\ + printf("%41s:[""] NO RETURNED VALUE! (err = %d)\n", types[index].name, size, err);\ + }\ +} + +#define CL_QUERY_ARRAY_TYPE(err, type, count, query, id, info, size, types, index, format) {\ + type *param = (type *)malloc(sizeof(type)*count);\ + if (param != NULL) {\ + char format_str[CL_MAX_STRING];\ + memset(param, 0, sizeof(type)*count);\ + err = query(id, info, sizeof(type)*count, param, &size);\ + if (size/sizeof(type) > 0) {\ + int j;\ + if (strcmp(format, "%s") == 0) {\ + printf("%41s:["FMT_SIZE_T"] %s\n", types[index].name, size, (char *)param);\ + } else {\ + printf("%41s:["FMT_SIZE_T"] ", types[index].name, size);\ + sprintf(format_str, "%s", format);\ + for (j = 0; j < size/sizeof(type); j++) {\ + printf(format_str, param[j]);\ + } printf("\n");\ + }\ + } else { \ + printf("%41s:["FMT_SIZE_T"] NO RETURNED VALUE (err = %d)\n", types[index].name, size, err);\ + }\ + free(param);\ + }\ +} + +void clPrintQueryInfo(void *id, cl_uint info, QueryInfo_f query, cl_info_type_t *infoTypes, cl_uint numInfoTypes) +{ + cl_int err = CL_SUCCESS; + cl_uint i = 0; + size_t size = 0; + for (i = 0; i < numInfoTypes; i++) + { + if (info == infoTypes[i].info) + { + switch (infoTypes[i].type) + { + case CL_STRING_TYPE: + { + CL_QUERY_ARRAY_TYPE(err, cl_char, infoTypes[i].count, query, id, info, size, infoTypes, i, "%s"); + break; + } + case CL_ULONG_TYPE: + { + if (infoTypes[i].count == 1) { + CL_QUERY_ATOMIC_TYPE(err, cl_ulong, query, id, info, size, infoTypes, i, "%llu"); + } else { + CL_QUERY_ARRAY_TYPE(err, cl_ulong, infoTypes[i].count, query, id, info, size, infoTypes, i, "%llu "); + } + break; + } + case CL_UINT_TYPE: + { + if (infoTypes[i].count == 1) { + CL_QUERY_ATOMIC_TYPE(err, cl_uint, query, id, info, size, infoTypes, i, "%lu"); + } else { + CL_QUERY_ARRAY_TYPE(err, cl_uint, infoTypes[i].count, query, id, info, size, infoTypes, i, "%lu "); + } + break; + } + case CL_SIZET_TYPE: + { + if (infoTypes[i].count == 1) { + CL_QUERY_ATOMIC_TYPE(err, size_t, query, id, info, size, infoTypes, i, "%llu"); + } else { + CL_QUERY_ARRAY_TYPE(err, size_t, infoTypes[i].count, query, id, info, size, infoTypes, i, "%llu "); + } + break; + } + case CL_BOOL_TYPE: + { + CL_QUERY_ATOMIC_TYPE(err, cl_bool, query, id, info, size, infoTypes, i, (param?"TRUE":"FALSE")); + break; + } + case CL_DEVMEMCHE_TYPE: + { + CL_QUERY_ATOMIC_TYPE(err, cl_device_mem_cache_type, query, id, info, size, infoTypes, i, "0x%08x"); + break; + } + case CL_DEVFPCFG_TYPE: + { + CL_QUERY_ATOMIC_TYPE(err, cl_device_fp_config, query, id, info, size, infoTypes, i, "0x%08x"); + break; + } + case CL_DEVEXCCAP_TYPE: + { + CL_QUERY_ATOMIC_TYPE(err, cl_device_exec_capabilities, query, id, info, size, infoTypes, i, "0x%08x"); + break; + } + case CL_LCLDEVMEM_TYPE: + { + CL_QUERY_ATOMIC_TYPE(err, cl_device_local_mem_type, query, id, info, size, infoTypes, i, "0x%08x"); + break; + } + case CL_PLATFORM_TYPE: + { + CL_QUERY_ATOMIC_TYPE(err, cl_platform_id, query, id, info, size, infoTypes, i, "0x%08x"); + break; + } + case CL_CMDQUEUE_TYPE: + { + CL_QUERY_ATOMIC_TYPE(err, cl_command_queue_properties, query, id, info, size, infoTypes, i, "0x%08x"); + break; + } + case CL_DEVTYPE_TYPE: + { + CL_QUERY_ATOMIC_TYPE(err, cl_device_type, query, id, info, size, infoTypes, i, "0x%08x"); + break; + } + } + } + } +} + +void clPrintPlatformInfo(cl_platform_id plat, cl_platform_info info) +{ + clPrintQueryInfo(plat, info, (QueryInfo_f)clGetPlatformInfo, clPlatInfoType, numPlatInfoTypes); +} + +void clPrintDeviceInfo(cl_device_id device, cl_device_info info) +{ + clPrintQueryInfo(device, info, (QueryInfo_f)clGetDeviceInfo, clDeviceInfoType, numDeviceInfoTypes); +} + +void clPrintContextInfo(cl_context context, cl_context_info info) +{ + clPrintQueryInfo(context, info, (QueryInfo_f)clGetContextInfo, clContextInfoType, numContextInfoTypes); +} + +void clPrintQueueInfo(cl_command_queue queue, cl_command_queue_info info) +{ + clPrintQueryInfo(queue, info, (QueryInfo_f)clGetCommandQueueInfo, clQueueInfoType, numQueueInfoTypes); +} + +void clPrintKernelInfo(cl_kernel kernel, cl_kernel_info info) +{ + clPrintQueryInfo(kernel, info, (QueryInfo_f)clGetKernelInfo, clKernelInfoType, numKernelInfoTypes); +} + +void clPrintKernelWorkInfo(cl_kernel kernel, cl_device_id device, cl_kernel_info info) +{ + cl_int err = CL_SUCCESS; + cl_uint i = 0; + size_t size = 0; + for (i = 0; i < numKernelWorkInfoTypes; i++) + { + if (info == clKernelWorkInfoType[i].info) + { + switch (clKernelWorkInfoType[i].type) + { + case CL_ULONG_TYPE: + { + cl_ulong param; + err = clGetKernelWorkGroupInfo(kernel, device, info, sizeof(param), ¶m, &size); + if (size == sizeof(param)) + printf("%41s:["FMT_SIZE_T"] %llu\n", clKernelWorkInfoType[i].name, size, param); + else + printf("%41s:[00] NO RETURNED VALUE! (err = %d)\n",clKernelWorkInfoType[i].name, err); + break; + } + case CL_SIZET_TYPE: + { + if (clKernelWorkInfoType[i].count == 1) + { + size_t param; + err = clGetKernelWorkGroupInfo(kernel, device, info, sizeof(param), ¶m, &size); + if (size == sizeof(param)) + printf("%41s:["FMT_SIZE_T"] "FMT_SIZE_T"\n", clKernelWorkInfoType[i].name, size, param); + else + printf("%41s:[00] NO RETURNED VALUE! (err = %d)\n",clKernelWorkInfoType[i].name, err); + } + else + { + size_t param[3]; + err = clGetKernelWorkGroupInfo(kernel, device, info, sizeof(param), ¶m, &size); + if (size == sizeof(param)) + printf("%41s:["FMT_SIZE_T"] "FMT_SIZE_T" "FMT_SIZE_T" "FMT_SIZE_T"\n", clKernelWorkInfoType[i].name, size, param[0], param[1], param[2]); + else + printf("%41s:[00] NO RETURNED VALUE! (err = %d)\n",clKernelWorkInfoType[i].name, err); + } + break; + } + } + } + } +} + +void clPrintAllPlatformInfo(cl_platform_id platform) +{ + cl_uint i = 0; + for (i = 0; i < numPlatInfoTypes; i++) + clPrintPlatformInfo(platform, clPlatInfoType[i].info); +} + +void clPrintAllDeviceInfo(cl_device_id device) +{ + cl_uint i = 0; + for (i = 0; i < numDeviceInfoTypes; i++) + clPrintDeviceInfo(device,clDeviceInfoType[i].info); +} + +void clPrintAllContextInfo(cl_context context) +{ + cl_uint i = 0; + for (i = 0; i < numContextInfoTypes; i++) + clPrintContextInfo(context, clContextInfoType[i].info); +} + +void clPrintAllQueueInfo(cl_command_queue queue) +{ + cl_uint i = 0; + for (i = 0; i < numQueueInfoTypes; i++) + clPrintQueueInfo(queue, clQueueInfoType[i].info); +} + +void clPrintAllKernelInfo(cl_kernel kernel) +{ + cl_uint i = 0; + for (i = 0; i < numKernelInfoTypes; i++) + clPrintKernelInfo(kernel, clKernelInfoType[i].info); +} + +void clPrintAllKernelWorkInfo(cl_kernel kernel, cl_device_id device) +{ + cl_uint i = 0; + for (i = 0; i < numKernelWorkInfoTypes; i++) + clPrintKernelWorkInfo(kernel, device, clKernelWorkInfoType[i].info); +} diff --git a/libraries/public/ocl/concerto.mak b/libraries/public/ocl/concerto.mak new file mode 100644 index 0000000..fdcccf2 --- /dev/null +++ b/libraries/public/ocl/concerto.mak @@ -0,0 +1,85 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Only PC/PANDA with Full Distro current supports the OpenCL environment. +ifeq ($(TARGET_PLATFORM),PC) + # assume it's available + CL_AVAILABLE := true + # Mac OSX comes with OpenCL by default if you have installed XCode + ifneq ($(TARGET_OS),DARWIN) # Win/Linux + ifndef OPENCL_ROOT # if no SDK defined... + CL_AVAILABLE := false + endif + endif +else ifeq ($(TARGET_PLATFORM),PANDA) + # panda has a package for OpenCL + CL_AVAILABLE := true +else + # We don't support this anywhere else. + CL_AVAILABLE := false +endif + +ifeq ($(CL_AVAILABLE),true) +include $(PRELUDE) + +VISION_LIBRARIES+=ocl +DVP_INC+=$(_MODPATH)/include +DVP_FEATURES+=DVP_USE_OCL + +ifdef DVP_LOCAL_BUILD + +TARGET=ocl +TARGETTYPE=library +DEFS += CL_BUILD_RUNTIME +ifdef CL_DEBUG +DEFS += CL_DEBUG +endif +CSOURCES=$(call all-c-files) +ifeq ($(TARGET_OS),DARWIN) + IDIRS+=/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/OpenCL.framework/Headers + ifdef CL_DEBUG + DEFS+=VECLIB DEBUG _GLIBCXX_DEBUG=1 _GLIBCXX_DEBUG_PEDANTIC=1 + endif +else ifeq ($(TARGET_OS),Windows_NT) + # NVIDIA OpenCL paths + IDIRS += $(OPENCL_ROOT)/inc + ifeq ($(HOST_CPU),X86) + LDIRS += $(OPENCL_ROOT)/lib/Win32 + else ifeq ($(HOST_CPU),X64) + LDIRS += $(OPENCL_ROOT)/lib/x64 + endif +else ifeq ($(TARGET_OS),LINUX) + ifdef OPENCL_ROOT + # NVIDIA OpenCL paths + IDIRS += $(OPENCL_ROOT)/inc + ifeq ($(TARGET_CPU),X86) + LDIRS += $(OPENCL_ROOT)/lib/Linux32 + else ifeq ($(TARGET_CPU),x86_64) + LDIRS += $(OPENCL_ROOT)/lib/Linux64 + endif + else + # Default package in system like panda + endif +endif +IDIRS += $(DVP_INC) +CL_USER_DEVICE_COUNT ?= 1 +CL_USER_DEVICE_TYPE ?= gpu +OCL_ROOT ?= $(realpath $(_MODPATH)) +DEFS += CL_USER_DEVICE_COUNT=$(CL_USER_DEVICE_COUNT) CL_USER_DEVICE_TYPE=\"$(CL_USER_DEVICE_TYPE)\" OCL_ROOT=\"$(OCL_ROOT)/\" +endif # LOCAL + +include $(FINALE) + +endif # CL_AVAILABLE + diff --git a/libraries/public/ocl/imgfilter.c b/libraries/public/ocl/imgfilter.c new file mode 100644 index 0000000..c1bad17 --- /dev/null +++ b/libraries/public/ocl/imgfilter.c @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/*! \file + * \brief The "OpenCL Environment" imgfilter kernel C interface. + * \see http://github.com/emrainey/OpenCL-Environment + * \author Erik Rainey + */ + +#include +#ifdef DARWIN +#include +#else +#include +#endif +#include +#include +#include + +cl_int range_of_operator(cl_char *op, cl_uint n, cl_uint limit) +{ + cl_int range; + cl_uint p,q,r,s; + cl_int max = 0, min = 0x7FFFFFFF; + for (p = 0; p < 2; p++) + { + for (q = 0; q < n; q++) + { + for (r = 0; r < n; r++) + { + s = (p * n * n) + (q * n) + r; + if (op[s] < min) + min = op[s]; + else if (op[s] > max) + max = op[s]; + } + } + } + range = isqrt(ipow(abs(min)*limit,2) + ipow(max*limit,2)); + return range; +} + +cl_int imgfilter1d(cl_environment_t *pEnv, + cl_uint width, + cl_uint height, + cl_uchar *pSrc, + cl_int srcStride, + cl_uchar *pDst, + cl_int dstStride, + cl_char *op, + cl_uint opDim, + cl_uint range, + cl_uint limit) +{ + cl_int err = CL_SUCCESS; + cl_uint numSrcBytes = srcStride * height; + cl_uint numDstBytes = dstStride * height; + cl_uint numOpBytes = 2 * opDim * opDim; + cl_kernel_param_t params[] = { + {CL_KPARAM_BUFFER_0D, sizeof(cl_uint), &width, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_BUFFER_0D, sizeof(cl_uint), &height, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_BUFFER_1D, numSrcBytes, pSrc, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_BUFFER_0D, sizeof(cl_int), &srcStride, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_BUFFER_1D, numDstBytes, pDst, NULL, CL_MEM_WRITE_ONLY}, + {CL_KPARAM_BUFFER_0D, sizeof(cl_int), &dstStride, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_BUFFER_1D, numOpBytes, op, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_BUFFER_0D, sizeof(cl_uint), &opDim, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_BUFFER_0D, sizeof(cl_uint), &range, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_BUFFER_0D, sizeof(cl_uint), &limit, NULL, CL_MEM_READ_ONLY}, + }; + cl_kernel_call_t call = { + "kernel_edge_filter", + params, dimof(params), + 2, + {0,0,0}, + {width, height, 0}, + {1,1,1}, + CL_SUCCESS, 0,0,0 + }; + err = clCallKernel(pEnv, &call,1); + return err; +} + +cl_int imgfilter1d_opt(cl_environment_t *pEnv, + cl_uint width, + cl_uint height, + cl_uchar *pSrc, + cl_int srcStride, + cl_uchar *pDst, + cl_int dstStride, + cl_char *op, + cl_uint opDim, + cl_uint range, + cl_uint limit) +{ + cl_int err = CL_SUCCESS; + cl_uint numSrcBytes = srcStride * height; + cl_uint numDstBytes = dstStride * height; + cl_uint numOpBytes = 2 * opDim * opDim; + cl_kernel_param_t params[] = { + {CL_KPARAM_BUFFER_0D, sizeof(cl_uint), &width, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_BUFFER_0D, sizeof(cl_uint), &height, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_BUFFER_1D, numSrcBytes, pSrc, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_BUFFER_0D, sizeof(cl_int), &srcStride, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_BUFFER_1D, numDstBytes, pDst, NULL, CL_MEM_WRITE_ONLY}, + {CL_KPARAM_BUFFER_0D, sizeof(cl_int), &dstStride, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_BUFFER_1D, numOpBytes, op, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_BUFFER_0D, sizeof(cl_uint), &opDim, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_BUFFER_0D, sizeof(cl_uint), &range, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_BUFFER_0D, sizeof(cl_uint), &limit, NULL, CL_MEM_READ_ONLY}, + {CL_KPARAM_LOCAL, sizeof(cl_uchar)*18, NULL, NULL, CL_MEM_READ_WRITE}, + {CL_KPARAM_LOCAL, sizeof(cl_char)*18, NULL, NULL, CL_MEM_READ_WRITE}, + }; + cl_kernel_call_t call = { + "kernel_edge_filter_opt", + params, dimof(params), + 2, + {0,0,0}, + {width, height, 0}, + {1,1,1}, + CL_SUCCESS, 0,0,0 + }; + err = clCallKernel(pEnv, &call,1); + return err; +} + + diff --git a/libraries/public/ocl/include/ocl/clenvironment.h b/libraries/public/ocl/include/ocl/clenvironment.h new file mode 100644 index 0000000..cd4fb83 --- /dev/null +++ b/libraries/public/ocl/include/ocl/clenvironment.h @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief The "OpenCL Environment" core features header. + * \see http://github.com/emrainey/OpenCL-Environment + * \author Erik Rainey + */ + +#ifndef _CL_ENVIRONMENT_H_ +#define _CL_ENVIRONMENT_H_ + +#define CL_MAX_DEVICES (30) // @TODO determine a better way to limit the max number of devices. +#define CL_MAX_PATHSIZE (256) /**< Similar to Window's MAX_PATH */ +#define CL_MAX_STRING (1024) /**< Maximum length of a string from the command line or elsewhere */ +#define CL_MAX_LINESIZE (1024) /**< Maximum length of a source file line */ + +/** Handy macro to allow you to allocate a structure without all that pesky typecasting! */ +#define cl_malloc_struct(type) (type *)cl_malloc(sizeof(type)) + +/** Handy macro to allow you to allocate an array of a type without peksy typecasting */ +#define cl_malloc_array(type, num) (type *)cl_malloc(sizeof(type) * num) + +/** Macro to create strings from types/enums */ +#ifndef STRINGERIZE +#define STRINGERIZE(x) (#x) +#endif + +/** This pulls the define list and includes from the makefile into the C/C++ files for compilation with the OpenCL kernels at run/compile time */ +#if defined(DEFINES) && defined(INCLUDES) +#define CL_ARGS (STRINGERIZE(DEFINES)" "STRINGERIZE(INCLUDES)) +#else +#define CL_ARGS NULL +#endif + +#ifndef dimof +/** Dimension of */ +#define dimof(x) (sizeof(x)/sizeof(x[0])) +#endif + +#ifndef KDIR +/** Use this incase you don't define the path to your kernels */ +#ifdef Windows_NT +#define KDIR ".\\" +#else +#define KDIR "./" +#endif +#endif + +#ifndef CL_USER_DEVICE_TYPE +#define CL_USER_DEVICE_TYPE "all" +#endif + +#ifndef CL_USER_DEVICE_COUNT +#define CL_USER_DEVICE_COUNT (1) +#endif + +#if defined(ARCH_64) +#pragma OPENCL EXTENSION cl_khr_fp64: enable +#endif + +#if defined(WIN32) +#define FMT_SIZE_T "%llu" +#else +#define FMT_SIZE_T "%zu" +#endif + +/** A byte type */ +typedef unsigned char cl_byte; + +/** This is the data structure which holds precompiled OpenCL kernels for a series of devices */ +typedef struct _cl_kernel_bin_t { + cl_device_type deviceTypes; /**< the device types used in generating this set of kernels */ + size_t numDevices; /**< the number of devices these kernels have been compiled against */ + size_t numBytesSizes; /**< The number of bytes in the sizes array */ + size_t numBytesData; /**< The number of bytes in the data array */ + size_t *sizes; /**< An array of size_t values which indicates the length in bytes of the same indexed data buffer */ + cl_byte **data; /**< An array to precompiled device code, each length is indicated in the same index of sizes. */ +} cl_kernel_bin_t; + +/**< This indicates the type of parameter */ +typedef enum _cl_kernel_param_e { + CL_KPARAM_BUFFER_0D = 0, /**< This is simply a single value to pass to the OpenCL kernel */ + CL_KPARAM_BUFFER_1D, /**< This is an array of values to pass to the OpenCL kernel */ + CL_KPARAM_BUFFER_2D, /**< This is a two dimensional array of values to pass to the OpenCL Kernel */ + CL_KPARAM_BUFFER_3D, /**< This is a three dimensional array of values to pass to the OpenCL kernel */ + CL_KPARAM_LOCAL, /**< This indicates that the memory indicated by this parameter should be local to the device */ +} cl_kernel_param_e ; + +/**< The enumeration of the dimensions for multi-dimensional buffers. */ +typedef enum _cl_dimensions_e { + X_DIM = 0, + Y_DIM, + Z_DIM, + W_DIM, + DIM_MAX, +} clDimensions_e; + +#define PLANE_MAX (4) + +typedef struct _cl_nd_buffer_t { + cl_image_format format; /**< contains the needed formatting information about the type of nD buffer this is */ + void *data[PLANE_MAX]; /**< planar data. for single plane data, just use [0] */ + cl_uint planes; /**< the number of planes */ + cl_uint dim[DIM_MAX]; /**< the size in pixels of each dimension */ + cl_int strides[DIM_MAX]; /**< the stride of each dimension (x stride == channel size, y stride == pitch, z stride == frame separation ) */ + size_t size; /**< the total size of the all the data involved in the buffer */ +} cl_nd_buffer_t; + +typedef struct _cl_kernel_param_t { + cl_kernel_param_e type; /**< @see cl_kernel_param_e */ + size_t numBytes; /**< total number of bytes to allocate */ + void *data; /**< pointer to data type, for 0D, 1D, use normal pointers, for 2+ use cl_nd_buffer_t */ + cl_mem mem; /**< OpenCL memory handle. */ + cl_mem_flags flags; /**< read/write attributes */ + cl_event event; /**< the event handle. This allows the system to time the calls */ +} cl_kernel_param_t; + +typedef struct _cl_kernel_call_t { + char *kernel_name; /**< The name of OpenCL Kernel function you want to call. */ + cl_kernel_param_t *params; /**< The pointer to the parameter list */ + cl_uint numParams; /**< The number of parameters in the params variable */ + cl_uint numDim; /**< The number of dimensions in the problem (not necessarily the number of dimensions in the buffer) */ + size_t global_work_offset[3]; /**< The offset that each kernel call will use (not implemented currently) */ + size_t global_work_size[3]; /**< The size of each dimension */ + size_t local_work_size[3]; /**< The local size of each sub-groups dimension limit */ + cl_int err; /**< The return code from the kernel call */ + cl_event event; /**< The handle to the event which will be used to time the call */ + cl_ulong start; /**< The start time of the call */ + cl_ulong stop; /**< The stop time of the call, subtract start from this too get your diff */ +} cl_kernel_call_t; + +typedef struct _cl_environemnt_t +{ + cl_platform_id platform; /**< The handle to the OpenCL platform reference */ + cl_device_id *devices; /**< The array of devices */ + cl_uint numDevices; /**< The number of devices in the devices array */ + cl_context context; /**< The handle to the context for this grouping of devices */ + cl_context_properties context_props; /**< The properties field for the context */ + cl_command_queue *queues; /**< The command and data queue handle for this environment */ + char **sources; /**< The loaded source code from the source files, if you loaded and build in this runtime. This is blank if you load from binaries */ + cl_uint numLines; /**< The number of lines of source code in sources */ + size_t *lengths; /**< The array of line lengths of sources */ + cl_program program; /**< The handle to the program */ + cl_kernel *kernels; /**< The array of kernel handles */ + cl_uint numKernels; /**< The number of kernel handles in kernels */ + cl_int *retCodes; /**< The array of return codes */ +} cl_environment_t; + +void clPrintEnvironment(cl_environment_t *pEnv); + + +/**< Build Callback Notifier Typedef */ +typedef void (*clnotifier_f)(cl_program program, void *args); + +/** + * This function creates an OpenCL environment from a source file with a set of arguments for the run-time compiler. + * @param filename The name of the file to read the sources from. + * @param dev_type The device types to use to build your kernels. + * @param numDevices The number of devices to build your environment against. (use 0 to indicate to the function to use the max number available) + * @param notifier The function pointer to the notification function which will be called when the build is complete (though not necessarily successfully). + * @param cl_args The string of arguments to give to the runtime compiler. + */ +cl_environment_t *clCreateEnvironment(char *filename, + cl_uint dev_type, + cl_uint numDevices, + clnotifier_f notifier, + char *cl_args); + +/** + * This function creates in OpenCL environment from a series of binaries which have been precompiled by the clCompiler. + * @param bins The pointer to the data structure which houses the precompiled kernels. + * @param notifier The function pointer to the notification function which will be called when the build is complete. Since these binaries were precompiled, no build errors can be reported, though other types of errors may still happen. + * @param cl_args The string of arguments to give to the runtime compiler. This is still used in the precompiled case. + */ +cl_environment_t *clCreateEnvironmentFromBins(cl_kernel_bin_t *bins, + clnotifier_f notifier, + char *cl_args); + +/** This function destroys an environment regardless of how it was created */ +void clDeleteEnvironment(cl_environment_t *pEnv); + +/** This function creates a blank kernel binary structure for use in saving the compiled kernels */ +cl_kernel_bin_t *cl_create_kernel_bin(size_t numDevices); + +/** This function deletes a kernel binary structure */ +void cl_delete_kernel_bin(cl_kernel_bin_t * bins); + +/** This function extracts the compiled kernels from the program */ +cl_kernel_bin_t *cl_extract_kernels(cl_program program); + +/** This function writes the compiled kernel binaries to a file in binary format. + * @see cl_extract_kernels + * @param filename The name of the file to create. + * @param bins The pointer to the kernel binaries. + */ +void cl_dump_kernels(char *filename, cl_kernel_bin_t *bins); + +/** This function writes the compiled kernel binaries to a text header file. Use this to have a statically defined set of kernels for your program. + * @see clCreateEnvironmentFromBins + * @see cl_extract_kernels + * @param filename The name of the header to create. + * @param bins The kernel binaries. + * @return int + * @retval 1 on Success. + * @retval 0 on Failure. + */ +int cl_precompiled_header(char *filename, cl_kernel_bin_t *bins); + +/** + * This function takes the kernel binary structure and flattens it to a single 1D buffer. + * @param bins The pointer to the kernel binaries. + * @param pNumBytes The pointer to the location to store the size of the returned flat buffer. + */ +cl_byte *cl_serialize_kernels(cl_kernel_bin_t *bins, size_t *pNumBytes); + +/** + * This function takes a flattened buffer and creates a kernel binary structure + * @param bin The flat buffer. + * @param numBytes The number of bytes in the flat buffer. + */ +cl_kernel_bin_t *cl_unserialize_kernels(cl_byte * bin, size_t numBytes); + +/** + * This function gets the handle to a kernel function from the environment structure by querying for the name. + * @param pEnv The pointer to the environment created by either clCreateEnvironment or clCreateEnvironmentFromBins + * @param func_name The name of the kernel function. + */ +cl_kernel clGetKernelByName(cl_environment_t *pEnv, char *func_name); + +/** + * This function calls the kernel function as specified by the pCall parameter. + * @note Currently one function call will be made + * @TODO allow function chaining. + * @param pEnv The pointer to the environment. + * @param pCall The pointer to one or more kernel call data structures with all the fields filled in. + * @param numCalls the number of kernels calls in the call chain. + */ +cl_int clCallKernel(cl_environment_t *pEnv, cl_kernel_call_t *pCall, cl_uint numCalls); + +/** A handy wrapper for debugging */ +void *cl_malloc(size_t numBytes); + +/** A handy wrapper for debugging */ +void cl_free(void *ptr); + +/** Converts the string type to the the CL_DEVICE_TYPE_... */ +cl_uint clGetTypeFromString(char *typestring); + +/** Converts an error to a printout */ +cl_int clPrintError(cl_int err, char *label, const char *function, const char *file, int line); + +/** A macro to use to indicate the error */ +#define CL_ERROR(err, label) clPrintError(err, label, __FUNCTION__, __FILE__, __LINE__) + +/** Assertion to allow the developer to print an error message then take an action. */ +#define cl_assert(expr, action) { if (!(expr)) {printf("ERROR! "#expr" is false! %s:%u\n",__FILE__,__LINE__); action;} } + +#endif diff --git a/libraries/public/ocl/include/ocl/clkernels.h b/libraries/public/ocl/include/ocl/clkernels.h new file mode 100644 index 0000000..e0ceeff --- /dev/null +++ b/libraries/public/ocl/include/ocl/clkernels.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief The "OpenCL Environment" Image Filter Prototypes + * \see http://github.com/emrainey/OpenCL-Environment + * \author Erik Rainey + */ + +#ifndef _OCL_KERNELS_H_ +#define _OCL_KERNELS_H_ + +cl_int range_of_operator(cl_char *op, cl_uint n, cl_uint limit); + +cl_int imgfilter1d(cl_environment_t *pEnv, + cl_uint width, + cl_uint height, + cl_uchar *pSrc, + cl_int srcStride, + cl_uchar *pDst, + cl_int dstStride, + cl_char *op, + cl_uint opDim, + cl_uint range, + cl_uint limit); + +cl_int imgfilter1d_opt(cl_environment_t *pEnv, + cl_uint width, + cl_uint height, + cl_uchar *pSrc, + cl_int srcStride, + cl_uchar *pDst, + cl_int dstStride, + cl_char *op, + cl_uint opDim, + cl_uint range, + cl_uint limit); + +#endif + diff --git a/libraries/public/ocl/include/ocl/clmath.h b/libraries/public/ocl/include/ocl/clmath.h new file mode 100644 index 0000000..bab731e --- /dev/null +++ b/libraries/public/ocl/include/ocl/clmath.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief The "OpenCL Environment" math prototypes. + * \see http://github.com/emrainey/OpenCL-Environment + * \author Erik Rainey + */ + +#ifndef _CL_MATH_H_ +#define _CL_MATH_H_ + +/** Integer Square Root Function */ +cl_uint isqrt(cl_int x); + +/** Integer Power Function */ +int ipow(int x, int n); + +/** Float Random Number Generator */ +float frand(void); + +/** Float Random Number Generator with a low and hi bounds */ +float frrand(float low, float hi); + +/** Float Summation of an array of float values */ +float fsum(float *a, cl_uint num); + +/** Integer Random Number Generator with a low and hi bounds */ +int rrand(int low, int hi); + +/** Float[4] Random Number Generator for a single float[4] array with a low and hi bound */ +void frand4(cl_float4 f, cl_int l, cl_int h); + +/** Normalizes an array of floats with a low and hi bounds into an output array of bytes */ +void normalize_float(float *a, cl_int low, cl_int hi, cl_uchar *b, cl_uint numPixels); + +#endif diff --git a/libraries/public/ocl/include/ocl/clquery.h b/libraries/public/ocl/include/ocl/clquery.h new file mode 100644 index 0000000..41fb87f --- /dev/null +++ b/libraries/public/ocl/include/ocl/clquery.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief The "OpenCL Environment" query protoypes. + * \see http://github.com/emrainey/OpenCL-Environment + * \author Erik Rainey + */ + + +#ifndef _CL_QUERY_H_ +#define _CL_QUERY_H_ + +void clPrintAllPlatformInfo(cl_platform_id platform); +void clPrintAllDeviceInfo(cl_device_id device); +void clPrintAllContextInfo(cl_context context); +void clPrintAllQueueInfo(cl_command_queue queue); +void clPrintAllKernelInfo(cl_kernel kernel); +void clPrintAllEventInfo(cl_event event); +void clPrintAllKernelWorkInfo(cl_kernel kernel, cl_device_id device); + +#endif diff --git a/libraries/public/ocl/include/ocl/dvp_kl_ocl.h b/libraries/public/ocl/include/ocl/dvp_kl_ocl.h new file mode 100644 index 0000000..a476cab --- /dev/null +++ b/libraries/public/ocl/include/ocl/dvp_kl_ocl.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! + * \file + * \brief This file decribes the exact set of kernels supported by the OCL + * algorithm library as exported through DVP. + * \note When using these enums, only the OCL kernels will be used! + * \defgroup group_algo_ocl Algos: OpenCL Kernels + * \brief This only works on platforms with OpenCL! + */ + +#ifndef _DVP_KL_OCL_H_ +#define _DVP_KL_OCL_H_ + +#ifdef DVP_USE_OCL + +#include + +/*! \brief The explicit list of kernels supported by the OCL algorithm library. + * \see DVP_Transform_t + */ +enum { + DVP_KN_OCL_BASE = DVP_KN_LIBRARY_BASE(DVP_KL_OCL), + + /*! + * Image Convolution of FOURCC_Y800 of data using the Sobel Gx and Gy operators\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_OCL_SOBEL, + + /*! + * Image Convolution of FOURCC_Y800 of data using the Scharr Gx and Gy operators\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_OCL_SCHARR, + + /*! + * Image Convolution of FOURCC_Y800 of data using the Scharr Gx and Gy operators\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_OCL_KROON, + + /*! + * Image Convolution of FOURCC_Y800 of data using the Prewitt Gx and Gy operators\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_OCL_PREWITT, + +}; + +#endif // DVP_USE_OCL + +#endif // _DVP_KL_OCL_H_ + diff --git a/libraries/public/ocl/include/ocl/ocl.h b/libraries/public/ocl/include/ocl/ocl.h new file mode 100644 index 0000000..816767c --- /dev/null +++ b/libraries/public/ocl/include/ocl/ocl.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief The "OpenCL Environment" Vision Header + * \see http://github.com/emrainey/OpenCL-Environment + * \author Erik Rainey + */ + +/*! + * \page page_ocl OpenCL Image Filter Library + * This library implements a 3x3 convolution operation on 8 bit data in fixed OpenCL kernels. + */ + +#ifndef _OCL_VISION_H_ +#define _OCL_VISION_H_ + +#include + +#ifndef _OCL_T_DEFINED +typedef void * ocl_t; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +ocl_t *ocl_init(); +void ocl_fini(ocl_t *ocl); + +DVP_Error_e ocl_Sobel8(ocl_t *ocl, DVP_Image_t *pInput, DVP_Image_t *pOutput); +DVP_Error_e ocl_Scharr8(ocl_t *ocl, DVP_Image_t *pInput, DVP_Image_t *pOutput); +DVP_Error_e ocl_Prewitt8(ocl_t *ocl, DVP_Image_t *pInput, DVP_Image_t *pOutput); +DVP_Error_e ocl_Kroon8(ocl_t *ocl, DVP_Image_t *pInput, DVP_Image_t *pOutput); + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/libraries/public/ocl/kernels.cl b/libraries/public/ocl/kernels.cl new file mode 100644 index 0000000..010b5fe --- /dev/null +++ b/libraries/public/ocl/kernels.cl @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief The "OpenCL Environment" Kernels for Edge Filters. + * \see http://github.com/emrainey/OpenCL-Environment + * \author Erik Rainey + */ + +uchar clamp_uc(float a, uchar l, uchar h) +{ + if ((uint)a > (uint)h) + return h; + if ((int)a < (int)l) + return l; + return (uchar)a; +} + +__kernel void kernel_edge_filter(uint width, + uint height, + __global uchar *pSrc, // planar 1 byte pixel data + int srcStride, + __global uchar *pDst, // planar 1 byte pixel data + int dstStride, + __global char *operator, // a fixed sized array of 2xNxN elements + uint n, + uint range, + uint limit) +{ + // these are the coordinates in the image + const int x = get_global_id(0); + const int y = get_global_id(1); + int i,j; // linear indexes for pSrc and pDst + int a, b; // relative x,y pixel index + int p,q,r; // operator pixel indexes + int s; // linear index for operator + int nh = n >> 1; // rounded half-dimension size i.e. n = 3, nh = 1 + int grad = 0; + int sum = 0; + float g = 0; + for (p = 0; p < 2; p++) + { + grad = 0; + for (q = 0, b = y-nh; q < n, b <= y+nh; q++, b++) + { + if (b < 0) continue; + if (b >= height) continue; + + for (r = 0, a = x-nh; r < n, a <= x+nh; r++, a++) + { + if (a < 0) continue; + if (a >= width) continue; + + i = (b * srcStride) + a; + //if (pSrc[i] == 0) continue; + + s = (p * n * n) + (q * n) + r; + grad += (int)((int)operator[s] * (uint)pSrc[i]); + } + } + sum += (grad * grad); + } + j = (y * dstStride) + x; + g = sqrt((float)sum); + pDst[j] = ((g/range) * limit); +} + +__kernel void kernel_edge_filter_opt(uint width, + uint height, + __global uchar *pSrc, // planar 1 byte pixel data + int srcStride, + __global uchar *pDst, // planar 1 byte pixel data + int dstStride, + __global char *operator, // a fixed sized array of 2xNxN elements + uint n, + uint range, + uint limit, + __local uchar *plA, + __local char *plOp) +{ + // these are the coordinates in the image + const int x = get_global_id(0); + const int y = get_global_id(1); + int i,j; // linear indexes for pSrc and pDst + int a, b; // relative x,y pixel index + int p,q,r; // operator pixel indexes + int s; // linear index for operator + int nh = n >> 1; // rounded half-dimension size i.e. n = 3, nh = 1 + int grad = 0; + int sum = 0; + float g = 0; + + for (p = 0; p < 2; p++) + { + for (q = 0, b = y-nh; q < n, b <= y+nh; q++, b++) + { + for (r = 0, a = x-nh; r < n, a <= x+nh; r++, a++) + { + i = (b * srcStride) + a; + s = (p * n * n) + (q * n) + r; + + if ((b < 0) || (b >= height) || (a < 0) || (a >= width)) + { + plA[s] = 0; + } + else + { + plA[s] = pSrc[i]; + } + plOp[s] = operator[s]; + } + } + } + barrier(CLK_LOCAL_MEM_FENCE); + + grad += plOp[0]*plA[0] + plOp[1]*plA[1] + plOp[2]*plA[2]; + grad += plOp[3]*plA[3] + plOp[4]*plA[4] + plOp[5]*plA[5]; + grad += plOp[6]*plA[6] + plOp[7]*plA[7] + plOp[8]*plA[8]; + sum += (grad * grad); + + grad += plOp[9]*plA[0] + plOp[10]*plA[1] + plOp[11]*plA[2]; + grad += plOp[12]*plA[3] + plOp[13]*plA[4] + plOp[14]*plA[5]; + grad += plOp[15]*plA[6] + plOp[16]*plA[7] + plOp[17]*plA[8]; + sum += (grad * grad); + + g = sqrt((float)sum); + + j = (y * dstStride) + x; + + pDst[j] = ((g/range) * limit); +} + diff --git a/libraries/public/ocl/ocl.c b/libraries/public/ocl/ocl.c new file mode 100644 index 0000000..3760af6 --- /dev/null +++ b/libraries/public/ocl/ocl.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/*! \file + * \brief The "OpenCL Environment" wrapper for accessing OpenCL kernels. + * \see http://github.com/emrainey/OpenCL-Environment + * \author Erik Rainey + */ + +#ifdef DARWIN +#include +#else +#include +#endif + +#include +#include + +typedef struct _ocl_t { + cl_environment_t *env; +} ocl_t; + +#define _OCL_T_DEFINED +#include +#include +#include + +static void cl_notifier(cl_program program, void *args) +{ + DVP_PRINT(DVP_ZONE_API, "OpenCL Program %p compiled!\n", program); +} + +void ocl_fini(ocl_t *ocl) +{ + if (ocl) + { + clDeleteEnvironment(ocl->env); + } +} + +ocl_t *ocl_init() +{ + ocl_t *ocl = (ocl_t *)calloc(1, sizeof(ocl_t)); + if (ocl) + { + ocl->env = clCreateEnvironment(OCL_ROOT"kernels.cl", clGetTypeFromString(CL_USER_DEVICE_TYPE), CL_USER_DEVICE_COUNT, cl_notifier, CL_ARGS); + } + return ocl; +} + +DVP_Error_e ocl_Sobel8(ocl_t *ocl, DVP_Image_t *pInput, DVP_Image_t *pOutput) +{ + DVP_PRINT(DVP_ZONE_API, "OCL: %p (env=%p) SOBEL in %p out %p\n", ocl, ocl->env, pInput, pOutput); + if (ocl && ocl->env) + { + cl_char operator[2][3][3] = { { {1,2,1}, {0,0,0}, {-1,-2,-1} }, { {-1,0,1}, {-2,0,2}, {-1,0,1} } }; + cl_uint limit = 255; + cl_uint range = range_of_operator((cl_char *)operator, 3, limit); + cl_int err = imgfilter1d_opt(ocl->env, + pInput->width, + pInput->height, + pInput->pData[0], + pInput->y_stride, + pOutput->pData[0], + pOutput->y_stride, + (cl_char *)operator, + 3, + range,limit); + return DVP_SUCCESS; + } + return DVP_ERROR_INVALID_PARAMETER; +} + +DVP_Error_e ocl_Scharr8(ocl_t *ocl, DVP_Image_t *pInput, DVP_Image_t *pOutput) +{ + DVP_PRINT(DVP_ZONE_API, "OCL: %p (env=%p) SCHARR in %p out %p\n", ocl, ocl->env, pInput, pOutput); + if (ocl && ocl->env) + { + cl_char operator[2][3][3] = { { {3,10,3}, {0,0,0}, {-3,-10,-3} }, { {3,0,-3}, {10,0,-10}, {3,0,-3} } }; + cl_uint limit = 255; + cl_uint range = range_of_operator((cl_char *)operator, 3, limit); + cl_int err = imgfilter1d_opt(ocl->env, + pInput->width, + pInput->height, + pInput->pData[0], + pInput->y_stride, + pOutput->pData[0], + pOutput->y_stride, + (cl_char *)operator, + 3, + range,limit); + return DVP_SUCCESS; + } + return DVP_ERROR_INVALID_PARAMETER; +} + +DVP_Error_e ocl_Prewitt8(ocl_t *ocl, DVP_Image_t *pInput, DVP_Image_t *pOutput) +{ + DVP_PRINT(DVP_ZONE_API, "OCL: %p (env=%p) PREWITT in %p out %p\n", ocl, ocl->env, pInput, pOutput); + if (ocl && ocl->env) + { + cl_char operator[2][3][3] = { { {1,1,1}, {0,0,0}, {-1,-1,-1} }, { {-1,0,1}, {-1,0,1}, {-1,0,1} } }; + cl_uint limit = 255; + cl_uint range = range_of_operator((cl_char *)operator, 3, limit); + cl_int err = imgfilter1d_opt(ocl->env, + pInput->width, + pInput->height, + pInput->pData[0], + pInput->y_stride, + pOutput->pData[0], + pOutput->y_stride, + (cl_char *)operator, + 3, + range,limit); + return DVP_SUCCESS; + } + return DVP_ERROR_INVALID_PARAMETER; +} + +DVP_Error_e ocl_Kroon8(ocl_t *ocl, DVP_Image_t *pInput, DVP_Image_t *pOutput) +{ + DVP_PRINT(DVP_ZONE_API, "OCL: %p (env=%p) KROON in %p out %p\n", ocl, ocl->env, pInput, pOutput); + if (ocl && ocl->env) + { + cl_char operator[2][3][3] = { { {17,61,17}, {0,0,0}, {-17,-61,-17} }, { {17,0,-17}, {61,0,-61}, {17,0,-17} } }; + cl_uint limit = 255; + cl_uint range = range_of_operator((cl_char *)operator, 3, limit); + cl_int err = imgfilter1d_opt(ocl->env, + pInput->width, + pInput->height, + pInput->pData[0], + pInput->y_stride, + pOutput->pData[0], + pOutput->y_stride, + (cl_char *)operator, + 3, + range,limit); + return DVP_SUCCESS; + } + return DVP_ERROR_INVALID_PARAMETER; +} + diff --git a/libraries/public/vrun/Android.mk b/libraries/public/vrun/Android.mk new file mode 100644 index 0000000..cf9a20e --- /dev/null +++ b/libraries/public/vrun/Android.mk @@ -0,0 +1,16 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +VISION_LIBRARIES += vrun + diff --git a/libraries/public/vrun/concerto.mak b/libraries/public/vrun/concerto.mak new file mode 100644 index 0000000..3ebb506 --- /dev/null +++ b/libraries/public/vrun/concerto.mak @@ -0,0 +1,23 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_CPU),ARM) + +# VRUN is only present on the OMAP platform. +VISION_LIBRARIES += vrun +DVP_FEATURES += DVP_USE_VRUN +DVP_INC += $(DVP_ROOT)/libraries/public/vrun/include + +endif + diff --git a/libraries/public/vrun/include/vrun/dvp_kl_vrun.h b/libraries/public/vrun/include/vrun/dvp_kl_vrun.h new file mode 100644 index 0000000..7a59fe5 --- /dev/null +++ b/libraries/public/vrun/include/vrun/dvp_kl_vrun.h @@ -0,0 +1,595 @@ +/* ==================================================================== + * Copyright (C) 2012 Texas Instruments Incorporated + * ==================================================================== */ + +/*! + * \file + * \brief This file decribes the exact set of kernels supported by the VRUN + * algorithm library as exported through DVP. + * \note When using these enums, only the VRUN kernels will be used! + * \defgroup group_algo_vrun Algos: VRUN (SIMCOP) + * \brief This only works on platforms with a Ducati/Benelli firmware with + * the enabled DVP KGM. + */ + +#ifndef _DVP_KL_VRUN_H_ +#define _DVP_KL_VRUN_H_ + +#ifdef DVP_USE_VRUN + +#include + +/*! \brief The explicit list of kernels supported by the VRUN algorithm library. + * \see DVP_Transform_t + * \ingroup group_algo_vrun + */ +enum { + DVP_KN_VRUN_BASE = DVP_KN_LIBRARY_BASE(DVP_KL_VRUN), + + /*! + * Image Dilation using a 3x3 Cross Pattern : [0,1,0],[1,1,1],[0,1,0] (VLIB-API.Sec 14.0)\n + * Configuration Structure: DVP_Morphology_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Not applicable + */ + DVP_KN_VRUN_DILATE_CROSS, + + /*! + * Image Dilation using a user specified 3x3 Mask pattern (VLIB-API.Sec 14.0)\n + * Configuration Structure: DVP_Morphology_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_DILATE_MASK, + + /*! + * Image Dilation using a 3x3 Square pattern : [1,1,1],[1,1,1],[1,1,1] (VLIB-API.Sec 14.0) \n + * Configuration Structure: DVP_Morphology_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Not applicable + */ + DVP_KN_VRUN_DILATE_SQUARE, + + /*! + * Image Erosion using a 3x3 Cross Pattern : [0,1,0],[1,1,1],[0,1,0] (VLIB-API.Sec 15.0) \n + * Configuration Structure: DVP_Morphology_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Not applicable + */ + DVP_KN_VRUN_ERODE_CROSS, + + /*! + * Image Erosion using a user specified 3x3 Mask pattern (VLIB-API.Sec 15.0) \n + * Configuration Structure: DVP_Morphology_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_ERODE_MASK, + + /*! + * Image Erosion using a 3x3 Square pattern : [1,1,1],[1,1,1],[1,1,1] (VLIB-API.Sec 15.0) \n + * Configuration Structure: DVP_Morphology_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Not applicable + */ + DVP_KN_VRUN_ERODE_SQUARE, + + /*! + * Recursive First Order IIR Filter, Horizontal, FOURCC_Y800 input and output (VLIB-API.Sec 27.0) \n + * Configuration Structure: DVP_IIR_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [scratch] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_IIR_HORZ, + + /*! + * Recursive First Order IIR Filter, Vertical, FOURCC_Y800 input and output (VLIB-API.Sec 29.0)\n + * Configuration Structure: DVP_IIR_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [scratch] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_IIR_VERT, + + /*! + * Non-maximum suppression using 3x3 (VLIB-API.Sec 35.0)\n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_NONMAXSUPPRESS_3x3_S16, + + /*! + * Non-maximum suppression using 5x5 (VLIB-API.Sec 35.0)\n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_NONMAXSUPPRESS_5x5_S16, + + /*! + * Non-maximum suppression using 7x7 (VLIB-API.Sec 35.0)\n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_NONMAXSUPPRESS_7x7_S16, + + /*! + * Image Convolution using an arbitrary 3x3 matrix on FOURCC_Y800 data (IMGLIB-API.Sec 6.1) \n + * Configuration Structure: DVP_ImageConvolution_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_CONV_3x3, + + /*! + * Image Convolution using an arbitrary 5x5 matrix on FOURCC_Y800 data (IMGLIB-API.Sec 6.4)\n + * Configuration Structure: DVP_ImageConvolution_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_CONV_5x5, + + /*! + * Image Convolution using an arbitrary 7x7 matrix on FOURCC_Y800 data (IMGLIB-API.Sec 6.7)\n + * Configuration Structure: DVP_ImageConvolution_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_CONV_7x7, + + /*! + * Image Convolution using an arbitrary MxN matrix on FOURCC_Y800 data\n + * Configuration Structure: DVP_ImageConvolution_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_CONV_MxN, + + /*! + * Image Thresholding : {out[i] = (in[i] > thr) ? 255 : in[i]} for 8-bit input (IMGLIB-API.Sec 5.20) \n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_THR_GT2MAX_8, + + /*! + * Image Thresholding : {out[i] = (in[i] > thr) ? 65535 : in[i]} for 16-bit input (IMGLIB-API.Sec 5.21) \n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_VRUN_THR_GT2MAX_16, + + /*! + * Image Thresholding : {out[i] = (in[i] > thr) ? thr : in[i]} for 8-bit input (IMGLIB-API.Sec 5.22) \n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_THR_GT2THR_8, + + /*! + * Image Thresholding : {out[i] = (in[i] > thr) ? thr : in[i]} for 16-bit input (IMGLIB-API.Sec 5.23) \n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_VRUN_THR_GT2THR_16, + + /*! + * Image Thresholding : {out[i] = (in[i] <= thr) ? 0 : in[i]} for 8-bit input (IMGLIB-API.Sec 5.24) \n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_THR_LE2MIN_8, + + /*! + * Image Thresholding : {out[i] = (in[i] <= thr) ? 0 : in[i]} for 16-bit input (IMGLIB-API.Sec 5.25) \n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_VRUN_THR_LE2MIN_16, + + /*! + * Image Thresholding : {out[i] = (in[i] <= thr) ? thr : in[i]} for 8-bit input (IMGLIB-API.Sec 5.26) \n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_THR_LE2THR_8, + + /*! + * Image Thresholding : {out[i] = (in[i] <= thr) ? thr : in[i]} for 16-bit input (IMGLIB-API.Sec 5.27) \n + * Configuration Structure: DVP_Threshold_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_VRUN_THR_LE2THR_16, + + /*! + * Image Sobel : 3x3 for 8-bit signed input\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_SOBEL_3x3_8s, + + /*! + * Image Sobel : 3x3 for 8-bit unsigned input (IMGLIB-API.Sec 5.15)\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_SOBEL_3x3_8, + + /*! + * Image Sobel : 3x3 for 16-bit signed input (IMGLIB-API.Sec 5.16)\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_VRUN_SOBEL_3x3_16s, + + /*! + * Image Sobel : 3x3 for 16-bit unsigned input (IMGLIB-API.Sec 5.17)\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_SOBEL_3x3_16, + + /*! + * Image Sobel : 5x5 for 8-bit signed input \n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_SOBEL_5x5_8s, + + /*! + * Image Sobel : 5x5 for 8-bit unsigned input \n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_SOBEL_5x5_8, + + /*! + * Image Sobel : 5x5 for 16-bit signed input (IMGLIB-API.Sec 5.18) \n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_VRUN_SOBEL_5x5_16s, + + /*! + * Image Sobel : 5x5 for 16-bit unsigned input \n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_VRUN_SOBEL_5x5_16, + + /*! + * Image Sobel : 7x7 for 8-bit signed input \n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_SOBEL_7x7_8s, + + /*! + * Image Sobel : 7x7 for 8-bit unsigned input \n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_SOBEL_7x7_8, + + /*! + * Image Sobel : 7x7 for 16-bit signed input (IMGLIB-API.Sec 5.19)\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_VRUN_SOBEL_7x7_16s, + + /*! + * Image Sobel : 7x7 for 16-bit unsigned input\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y16 + */ + DVP_KN_VRUN_SOBEL_7x7_16, + + /*! + * Harris Corners\n + * Configuration Structure: DVP_HarrisCorners_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [tempBuf1] Image color type supported: FOURCC_Y16 + * \param [tempBuf2] Image color type supported: FOURCC_Y16 + * \param [tempBuf3] Image color type supported: FOURCC_Y16 + * \param [tempBuf4] Image color type supported: FOURCC_Y16 + */ + DVP_KN_VRUN_HARRIS_CORNERS, + + /*! + * Harris Corner Score 7x7\n + * Configuration Structure: DVP_Harris_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [harrisScore] Image color type supported: FOURCC_Y16 + */ + DVP_KN_VRUN_HARRIS_SCORE_7x7, + + /*! + * Compute block maxima, FOURCC_Y16 input\n + * Configuration Structure: DVP_BlockMaxima_t + * \param [input] Image color type supported: FOURCC_Y16 + * \param [blockMaximaMAX] Image color type supported: FOURCC_Y16 + * \param [blockMaximaX] Image color type supported: FOURCC_Y16 + * \param [blockMaximaY] Image color type supported: FOURCC_Y16 + */ + DVP_KN_VRUN_BLOCK_MAXIMA, + + /*! + * Non maximum suppression step1 for 16-bit X and Y input from block_maxima\n + * Configuration Structure: DVP_NMSStep1_t + * \param [nmsStep1X] Image color type supported: FOURCC_Y16 + * \param [nmsStep1Y] Image color type supported: FOURCC_Y16 + * \param [nmsStep1Dst] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_NMS_STEP1, + + /*! + * Image Convolution using an arbitrary 7x7 matrix on FOURCC_Y800 data (IMGLIB-API.Sec 6.7)\n + * Configuration Structure: DVP_ImageConvolution_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [mask] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_CANNY_IMAGE_SMOOTHING, + + /*! + * Canny 2D Gradient from FOURCC_Y800 to FOURCC_Y16 (VLIB-API.Sec 19.0) \n + * Configuration Structure: DVP_Canny2dGradient_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [outGradX] Image color type supported: FOURCC_Y16 + * \param [outGradY] Image color type supported: FOURCC_Y16 + * \param [outMag] Image color type supported: FOURCC_Y16 + */ + DVP_KN_VRUN_CANNY_2D_GRADIENT, + + /*! + * Canny Non-Maximum Suppression from FOURCC_Y16 data to FOURCC_Y800 data (VLIB-API.Sec 20.0) \n + * Configuration Structure: DVP_CannyNonMaxSuppression_t + * \param [inGradX] Image color type supported: FOURCC_Y16 + * \param [inGradY] Image color type supported: FOURCC_Y16 + * \param [inMag] Image color type supported: FOURCC_Y16 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_CANNY_NONMAX_SUPPRESSION, + + /*! + * Canny Hysterisis Threshholding from FOURCC_Y800 edge map data to FOURCC_Y800 edge image (VLIB-API.Sec 21.0) \n + * Configuration Structure: DVP_CannyHystThresholding_t + * \param [inMag] Image color type supported: FOURCC_Y16 + * \param [inEdgeMap] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_CANNY_HYST_THRESHHOLD, + + /*! + * Converts FOURCC_UYVY format to FOURCC_YU24 or FOURCC_YV24 format. + * Depending on the output size ratio to input size, chroma planes can upsampled or + * luma plane can be downsampled.\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_YU24 or FOURCC_YV24 + */ + DVP_KN_VRUN_UYVY_TO_YUV444p, + + /*! + * Converts FOURCC_UYVY format to 8 bits per pixels planar RGB using BT.601. (VLIB-API.Sec 58.0)\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_RGBP + */ + DVP_KN_VRUN_UYVY_TO_RGBp, + + /*! + * Converts FOURCC_UYVY format to FOURCC_IYUV or FOURCC_YV12 format. Chroma planes are downsampled vertically. (VLIB-API.Sec 55.0)\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_IYUV or FOURCC_YV12 + */ + DVP_KN_VRUN_UYVY_TO_YUV420p, + + /*! + * Converts FOURCC_UYVY or FOURCC_VYUY to FOURCC_Y800 image (luma extraction)\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_YVYU or FOURCC_YUY2 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_XYXY_TO_Y800, + + /*! + * Converts FOURCC_NV12 format to FOURCC_YU24 or FOURCC_YV24 format. + * Depending on the output size ratio to input size, chroma planes can upsampled or + * luma plane can be downsampled.\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_NV12 + * \param [output] Image color type supported: FOURCC_YU24 or FOURCC_YV24 + */ + DVP_KN_VRUN_NV12_TO_YUV444p, + + /*! + * Converts FOURCC_YU24 or FOURCC_YV24 format to FOURCC_YU24 or FOURCC_YV24 format to 8 bits per pixels planar RGB using BT.601\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_YU24 or FOURCC_YV24 + * \param [output] Image color type supported: FOURCC_RGBP + */ + DVP_KN_VRUN_YUV444p_TO_RGBp, + + /*! + * Computes a Integral Image over the FOURCC_Y800 data. 32 bit output (VLIB-API.Sec 31.0)\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y32 + */ + DVP_KN_VRUN_INTEGRAL_IMAGE_8, + + /*! + * Programmable affine Transformation \n + * Configuration Structure: DVP_Affine_t + * \param [input] Image color type supported: FOURCC_UYVY or FOURCC_NV12 + * \param [output] Image color type supported: FOURCC_UYVY or FOURCC_NV12 + */ + DVP_KN_LDC_AFFINE_TRANSFORM, + + /*! + * SAD with 8x8 reference image 8-bit unsigned input \n + * Configuration Structure: DVP_SAD_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [refImg] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_SAD_8x8, + + /*! + * SAD with 16x16 reference image 8-bit unsigned input \n + * Configuration Structure: DVP_SAD_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [refImg] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_SAD_16x16, + + /*! + * SAD with 3x3 reference image 8-bit unsigned input \n + * Configuration Structure: DVP_SAD_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [refImg] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_SAD_3x3, + + /*! + * SAD with 5x5 reference image 8-bit unsigned input \n + * Configuration Structure: DVP_SAD_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [refImg] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_SAD_5x5, + + /*! + * SAD with 7x7 reference image 8-bit unsigned input \n + * Configuration Structure: DVP_SAD_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_Y800 + * \param [refImg] Image color type supported: FOURCC_Y800 + */ + DVP_KN_VRUN_SAD_7x7, +}; + +/*! + * This structure is used with Affine Transformation Kernels. + * \ingroup group_algo_vrun + */ +typedef struct _dvp_affine_t { + DVP_Image_t input; /*!< Input image (FOURCC_UYVY or FOURCC_NV12) */ + DVP_Image_t output; /*!< Output image (must be same format as input) */ + DVP_S16 affine[6]; /*!< Affine parameters */ + /* ======================================================================= */ + /* affine[6] - Affine transform parameters + * -- -- -- -- -- -- -- -- + * | h_affine | = | affine[0] affine[1] | * | h_input | + | affine[2] | + * | v_affine | | affine[3] affine[4] | | v_input | | affine[5] | + * -- -- -- -- -- -- -- -- + * where (h_affine, v_affine) denotes the tranformed coordinates after applying affine transformation + * (h_input, v_input) denotes the coordinates of the input pixels (can be distorted or distortion corrected pixels) + * + * If s & r denote the desired scaling factor and rotation angle that needs to be applied via affine transform to the input, + * affine[0] = s * cos(r); + * affine[1] = s * sin(r); + * affine[3] = -s * sin(r); + * affine[4] = s * cos(r); + * affine[2] = h_0 - h_0 * A - v_0 * B; + * affine[5] = v_0 - h_0 * D - v_0 * E; + * + * where (h_0, v_0) denotes the coordinates of the lens center + */ + /* ======================================================================= */ + DVP_U16 pixpad; /*!< Pixel padding parameter */ +} DVP_Affine_t; + +/*! + * This structure is used with Harris Corner Kernel in VRUN. + * \ingroup group_algo_vrun + */ +typedef struct _dvp_harriscorner_t { + DVP_Image_t input; /*!< Luma image */ + DVP_Image_t output; /*!< Harris Corner NMS step1 output */ + DVP_Image_t tempBuf1; + DVP_Image_t tempBuf2; + DVP_Image_t tempBuf3; + DVP_Image_t tempBuf4; + DVP_S16 nplus1; + DVP_S16 k; /*!< Sensitivity parameter */ +} DVP_HarrisCorners_t; + +/*! + * This structure is used with Harris Corner Score Kernels. + * \ingroup group_algo_vrun + */ +typedef struct _dvp_harris_t { + DVP_Image_t input; /*!< Luma image */ + DVP_Image_t harrisScore; /*!< Harris (corneress) score */ + DVP_S16 k; /*!< Sensitivity parameter */ +} DVP_Harris_t; + +/*! + * This structure is used with Block Maxima Kernels. + * \ingroup group_algo_vrun + */ +typedef struct _dvp_blockmaxima_t { + DVP_Image_t input; /*!< Luma image */ + DVP_Image_t blockMaximaX; + DVP_Image_t blockMaximaY; + DVP_Image_t blockMaximaMAX; + DVP_S16 nplus1; +} DVP_BlockMaxima_t; + +/*! + * This structure is used with NMS_step1 Kernels. + * \ingroup group_algo_vrun + */ +typedef struct _dvp_nmsstep1_t { + DVP_Image_t nmsStep1X; + DVP_Image_t nmsStep1Y; + DVP_Image_t nmsStep1Dst; + DVP_S16 nplus1; +} DVP_NMSStep1_t; + +#endif // DVP_USE_VRUN + +#endif // _DVP_KL_VRUN_H_ + + diff --git a/libraries/public/yuv/Android.mk b/libraries/public/yuv/Android.mk new file mode 100644 index 0000000..12e55db --- /dev/null +++ b/libraries/public/yuv/Android.mk @@ -0,0 +1,32 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This can only be included when NEON is present +ifeq ($(TARGET_ARCH_VARIANT),armv7-a-neon) +VISION_LIBRARIES += yuv + +ifdef DVP_LOCAL_BUILD +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(DVP_DEBUGGING) $(DVP_CFLAGS) +LOCAL_SRC_FILES := $(notdir $(wildcard $(LOCAL_PATH)/*.S)) +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_MODULE := libyuv +include $(BUILD_STATIC_LIBRARY) +endif +endif + diff --git a/libraries/public/yuv/__argb_to_uyvy_image_bt601.S b/libraries/public/yuv/__argb_to_uyvy_image_bt601.S new file mode 100644 index 0000000..f2777ae --- /dev/null +++ b/libraries/public/yuv/__argb_to_uyvy_image_bt601.S @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __argb_to_uyvy_image_bt601 + +.include "yuv.inc" + +__argb_to_uyvy_image_bt601: +width .req r0 +height .req r1 +pSrc .req r2 +srcStride .req r3 +srcStep .req r3 +pDst .req r4 +dstStride .req r5 +dstStep .req r5 +pixelsLeft .req r6 +linesLeft .req r7 +tmp .req r8 + + PROLOG r0, r12 + + ldr pDst, [sp,#(14 * 4)] + ldr dstStride, [sp,#(15 * 4)] + mov linesLeft, height + + sub srcStep, srcStride, width, lsl #2 /* srcStep = srcStride - (width << 2) */ + sub dstStep, dstStride, width, lsl #1 /* dstStep = dstStride - (width << 1) */ + + FILL_RGB_TO_YCBCR_BT601 q15, q14, q13, q12, q11, q10, q9, q8 + +__argb_to_uyvy_image_bt601_line: + mov pixelsLeft, width +__argb_to_uyvy_image_bt601_pixel: + + pld [pSrc] + pld [pSrc, #L2_LINE_SIZE] + pld [pSrc, srcStride] + add tmp, srcStride, #L2_LINE_SIZE + pld [pSrc, tmp] + + vld4.8 {d0, d1, d2, d3},[pSrc]! + /* d0 = don't care */ + /* d3 = [b0,b1,b2,b3,b4,b5,b6,b7] */ + /* d2 = [g0,g1,g2,g3,g4,g5,g6,g7] */ + /* d1 = [r0,r1,r2,r3,r4,r5,r6,r7] */ + + vmovl.u8 q2, d3 /* q0 = [r0,r1,r2,r3,r4,r5,r6,r7] */ + vmovl.u8 q1, d2 /* q1 = [g0,g1,g2,g3,g4,g5,g6,g7] */ + vmovl.u8 q0, d1 /* q2 = [b0,b1,b2,b3,b4,b5,b6,b7] */ + + vmov.i16 q3, #1024 /* Y = 16 */ + vmov.i16 q4, #8192 /* Cb = 128 */ + vmov.i16 q5, #8192 /* Cr = 128 */ + + vmla.s16 q3, q0, q15 /* Y += 0.257*R */ + vmla.s16 q3, q1, q14 /* Y += 0.504*G */ + vmla.s16 q3, q2, q13 /* Y += 0.098*B */ + + vmls.s16 q4, q0, q12 /* Cb += -0.148*R */ + vmls.s16 q4, q1, q11 /* Cb += -0.291*G */ + vmla.s16 q4, q2, q10 /* Cb += 0.439*B */ + + vmla.s16 q5, q0, q10 /* Cr += 0.439*R */ + vmls.s16 q5, q1, q9 /* Cr += -0.368*G */ + vmls.s16 q5, q2, q8 /* Cr += -0.071*B */ + + /* compress the YUV >> 6 */ + vrshrn.i16 d1, q3, #6 /* d1 = [y0,y1,y2,y3,y4,y5,y6,y7] = q3 >> 6 */ + vrshrn.i16 d7, q4, #6 /* d7 = [u0,u1,u2,u3,u4,u5,u6,u7] = q4 >> 6 */ + vrshrn.i16 d8, q5, #6 /* d8 = [v0,v1,v2,v3,v4,v5,v6,v7] = q5 >> 6 */ + + /* Interleave */ + vtrn.8 d7, d8 /* d7 = [u0,v0,u2,v2,u4,v4,u6,v6] */ + /* d8 = [u1,v1,u3,v3,u5,v5,u7,v7] */ + vhadd.u8 d0, d7, d8 /* d7 = [u0,v0,u2,v2,u4,v4,u6,v6] (average) */ + /* d6 = [y0,y1,y2,y3,y4,y5,y6,y7] */ + vtrn.8 d0, d1 /* d0 = [u0,y0,u2,y2,u4,y4,u6,y6] */ + /* d1 = [v0,y1,v2,y3,v4,y5,v4,y7] */ + vtrn.16 d0, d1 /* d0 = [u0,y0,v0,y1,u4,y4,v4,y5] */ + /* d1 = [u2,y2,v2,y3,u6,y6,v6,y7] */ + /* Writeback */ + vst2.32 {d0, d1}, [pDst]! + + /* LOOP */ + + subs pixelsLeft, pixelsLeft, #8 + bgt __argb_to_uyvy_image_bt601_pixel + + add pSrc, pSrc, srcStep + add pDst, pDst, dstStep + + subs linesLeft, linesLeft, #1 + bgt __argb_to_uyvy_image_bt601_line + + EPILOG r0, r12 +.unreq width +.unreq height +.unreq pSrc +.unreq srcStride +.unreq srcStep +.unreq pDst +.unreq dstStride +.unreq dstStep +.unreq pixelsLeft +.unreq linesLeft +.unreq tmp + +.end diff --git a/libraries/public/yuv/__argb_to_uyvy_image_bt601_c.c b/libraries/public/yuv/__argb_to_uyvy_image_bt601_c.c new file mode 100644 index 0000000..1381cd5 --- /dev/null +++ b/libraries/public/yuv/__argb_to_uyvy_image_bt601_c.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief The "C" verison of an assembly optimized function. + * \author Erik Rainey + */ + +#include "yuv_c.h" + +void __argb_to_uyvy_image_bt601(uint32_t width, + uint32_t height, + uint8_t *pSrc, + int32_t srcStride, + uint8_t *pDst, + int32_t dstStride) +{ + uint32_t x, y; + int32_t i, j; + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x+=2) // writing macro pixels + { + RGB8888 a,b; + YUV422 yuv; + uint8_t u0,u1,v0,v1; + + i = (y * srcStride) + (x * sizeof(RGB8888)); + j = (y * dstStride) + (x * sizeof(uint16_t)); + + a = *(RGB8888 *)(&pSrc[i]); + b = *(RGB8888 *)(&pSrc[i+sizeof(RGB8888)]); + + CONVERT_RGB_TO_YUV_BT601_Q14(a.ARGB.R,a.ARGB.G,a.ARGB.B,yuv.UYVY.Y0,u0,v0); + CONVERT_RGB_TO_YUV_BT601_Q14(b.ARGB.R,b.ARGB.G,b.ARGB.B,yuv.UYVY.Y1,u1,v1); + + yuv.UYVY.U0 = (u0 + u1)>1; + yuv.UYVY.V0 = (v0 + v1)>1; + + *(YUV422 *)(&pDst[j]) = yuv; + } + } +} diff --git a/libraries/public/yuv/__bgr_to_iyuv_image_bt601.S b/libraries/public/yuv/__bgr_to_iyuv_image_bt601.S new file mode 100644 index 0000000..7bd18b4 --- /dev/null +++ b/libraries/public/yuv/__bgr_to_iyuv_image_bt601.S @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __bgr_to_iyuv_image_bt601 + +.include "yuv.inc" + +/** This subroutine converts BGR (byte ordered) data to UYVY Data */ +__bgr_to_iyuv_image_bt601: +width .req r0 +height .req r1 +pSrc .req r2 +srcStride .req r3 +pY .req r4 +pU .req r5 +pV .req r6 +pixelsLeft .req r7 +linesLeft .req r8 +tmp .req r9 +tmp2 .req r10 +srcStep .req r11 + PROLOG r0, r12 + + ldr pY, [sp,#(14 * 4)] + ldr pU, [sp,#(15 * 4)] + ldr pV, [sp,#(16 * 4)] + + mov linesLeft, height + + add tmp, width, width, lsl #1 /* tmp = 3 * width */ + sub srcStep, srcStride, tmp /* srcStep = srcStride - tmp */ + + FILL_RGB_TO_YCBCR_BT601 q5, q14, q13, q12, q11, q10, q9, q8 + +__bgr_to_iyuv_image_bt601_line: + mov pixelsLeft, width +__bgr_to_iyuv_image_bt601_pixel: + pld [pSrc] + pld [pSrc, #L2_LINE_SIZE] + pld [pSrc, srcStride] + add tmp, srcStride, #L2_LINE_SIZE + pld [pSrc, tmp] + + vld3.8 {d1, d2, d3},[pSrc] + /* d1 = [b0,b1,b2,b3,b4,b5,b6,b7] */ + /* d2 = [g0,g1,g2,g3,g4,g5,g6,g7] */ + /* d3 = [r0,r1,r2,r3,r4,r5,r6,r7] */ + + vmovl.u8 q2, d3 /* q2 = [r0,r1,r2,r3,r4,r5,r6,r7] */ + vmovl.u8 q1, d2 /* q1 = [g0,g1,g2,g3,g4,g5,g6,g7] */ + vmovl.u8 q0, d1 /* q0 = [b0,b1,b2,b3,b4,b5,b6,b7] */ + + vmov.i16 q3, #1024 /* Y = 16 */ + vmov.i16 q4, #8192 /* Cb = 128 */ + vmov.i16 q5, #8192 /* Cr = 128 */ + + vmla.s16 q3, q2, q15 /* Y += 0.257*R */ + vmla.s16 q3, q1, q14 /* Y += 0.504*G */ + vmla.s16 q3, q0, q13 /* Y += 0.098*B */ + + vmls.s16 q4, q2, q12 /* Cb += -0.148*R */ + vmls.s16 q4, q1, q11 /* Cb += -0.291*G */ + vmla.s16 q4, q0, q10 /* Cb += 0.439*B */ + + vmla.s16 q5, q2, q10 /* Cr += 0.439*R */ + vmls.s16 q5, q1, q9 /* Cr += -0.368*G */ + vmls.s16 q5, q0, q8 /* Cr += -0.071*B */ + + /* compress the YUV >> 6 */ + vrshrn.i16 d6, q3, #6 /* d6 = ([y0,y1,y2,y3,y4,y5,y6,y7] >> 6) */ + vrshrn.i16 d8, q4, #6 /* d8 = ([u0,u1,u2,u3,u4,u5,u6,u7] >> 6) */ + vrshrn.i16 d9, q5, #6 /* d9 = ([v0,v1,v2,v3,v4,v5,v6,v7] >> 6) */ + + /* Average the U's and V's */ + vtrn.8 d8, d9 + vhadd.u8 d8, d8, d9 /* d8 = [u0,v0,u2,v2,u4,v4,u6,v6] (average) */ + + add tmp, pSrc, srcStride + vld3.8 {d1, d2, d3},[tmp] + /* d1 = [b0,b1,b2,b3,b4,b5,b6,b7] */ + /* d2 = [g0,g1,g2,g3,g4,g5,g6,g7] */ + /* d3 = [r0,r1,r2,r3,r4,r5,r6,r7] */ + + vmovl.u8 q2, d3 /* q2 = [r0,r1,r2,r3,r4,r5,r6,r7] */ + vmovl.u8 q1, d2 /* q1 = [g0,g1,g2,g3,g4,g5,g6,g7] */ + vmovl.u8 q0, d1 /* q0 = [b0,b1,b2,b3,b4,b5,b6,b7] */ + + vmov.i16 q5, #1024 /* Y = 16 */ + vmov.i16 q6, #8192 /* Cb = 128 */ + vmov.i16 q7, #8192 /* Cr = 128 */ + + vmla.s16 q5, q2, q15 /* Y += 0.257*R */ + vmla.s16 q5, q1, q14 /* Y += 0.504*G */ + vmla.s16 q5, q0, q13 /* Y += 0.098*B */ + + vmls.s16 q6, q2, q12 /* Cb += -0.148*R */ + vmls.s16 q6, q1, q11 /* Cb += -0.291*G */ + vmla.s16 q6, q0, q10 /* Cb += 0.439*B */ + + vmla.s16 q7, q2, q10 /* Cr += 0.439*R */ + vmls.s16 q7, q1, q9 /* Cr += -0.368*G */ + vmls.s16 q7, q0, q8 /* Cr += -0.071*B */ + + /* compress the YUV >> 6 */ + vrshrn.i16 d7, q5, #6 /* d7 = ([y8,y9,yA,yB,yC,yD,yE,yF] >> 6) */ + vrshrn.i16 d10,q6, #6 /* d10 = ([u8,u9,uA,uB,uC,uD,uE,uF] >> 6) */ + vrshrn.i16 d11,q7, #6 /* d11 = ([v8,v9,vA,vB,vC,vD,vE,vF] >> 6) */ + + /* Average the U's and V's */ + vtrn.8 d10,d11 + vhadd.u8 d10,d10,d11 /* d10 = [u8,v8,uA,vA,uC,vC,uE,vE] (average) */ + + /* Store Y's */ + vst1.8 {d6}, [pY] + add tmp, pY, width + vst1.8 {d7}, [tmp] + + /* Now Average the averages */ + vhadd.u8 d8, d8, d10 /* d8 = [u0,v0,u2,v2,u4,v4,u6,v6] (average) */ + + /* Arrange the U's and V's for writing */ + vmov.u8 d9, #0 + vmov.u8 d10,#0 + vmov.u8 d11,#0 + vtrn.8 d8, d10 /* d8 = [u0,xx,u2,xx,u4,xx,u6,xx] */ + /* d10= [v0,xx,v2,xx,v4,xx,v6,xx] */ + vmovn.i16 d8, q4 /* d8 = [u0,u2,u4,u6,xx,xx,xx,xx] */ + vmovn.i16 d10,q5 /* d10= [v0,v2,v4,v6,xx,xx,xx,xx] */ + /* Store U's */ + vmov tmp, tmp2, d8 + str tmp, [pU] + + /* Store V's */ + vmov tmp, tmp2, d10 + str tmp, [pV] + + /* Pointer Arithmetic for pixel group */ + add pSrc, pSrc, #24 /* pSrc += (8 * sizeof(BGR)) */ + add pY, pY, #8 + add pU, pU, #4 + add pV, pV, #4 + + /* LOOP */ + subs pixelsLeft, pixelsLeft, #8 /* process 8 pixels at a time. */ + bgt __bgr_to_iyuv_image_bt601_pixel + + /* Pointer Arithmetic for the lines */ + add pSrc, pSrc, srcStep /* pSrc += srcStep */ + add pSrc, pSrc, srcStride /* pSrc += srcStride (skips a line) */ + add pY, pY, width /* pY += width (skips a line) */ + /* pU, and pV are in the correct places */ + + subs linesLeft, linesLeft, #2 /* process 2 lines at a time. */ + bgt __bgr_to_iyuv_image_bt601_line + + EPILOG r0, r12 +.unreq width +.unreq height +.unreq pSrc +.unreq srcStride +.unreq pY +.unreq pU +.unreq pV +.unreq pixelsLeft +.unreq linesLeft +.unreq tmp +.unreq tmp2 +.unreq srcStep + +.end diff --git a/libraries/public/yuv/__bgr_to_uyvy_image_bt601.S b/libraries/public/yuv/__bgr_to_uyvy_image_bt601.S new file mode 100644 index 0000000..dda294b --- /dev/null +++ b/libraries/public/yuv/__bgr_to_uyvy_image_bt601.S @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __bgr_to_uyvy_image_bt601 + +.include "yuv.inc" + +/** This subroutine converts BGR (byte ordered) data to UYVY Data */ +__bgr_to_uyvy_image_bt601: +width .req r0 +height .req r1 +pSrc .req r2 +srcStride .req r3 +srcStep .req r3 +pDst .req r4 +dstStride .req r5 +dstStep .req r5 +pixelsLeft .req r6 +linesLeft .req r7 +tmp .req r8 + + PROLOG r0, r12 + + ldr pDst, [sp,#(14 * 4)] + ldr dstStride, [sp,#(15 * 4)] + mov linesLeft, height + + add tmp, width, width, lsl #1 /* tmp = 3 * width */ + sub srcStep, srcStride, tmp /* srcStep = srcStride - tmp */ + add tmp, width, width /* tmp = 2 * width */ + sub dstStep, dstStride, tmp /* dstStep = dstStride - tmp */ + + FILL_RGB_TO_YCBCR_BT601 q15, q14, q13, q12, q11, q10, q9, q8 + +__bgr_to_uyvy_image_bt601_line: + mov pixelsLeft, width +__bgr_to_uyvy_image_bt601_pixel: + + pld [pSrc] + pld [pSrc, #L2_LINE_SIZE] + pld [pSrc, srcStride] + add tmp, srcStride, #L2_LINE_SIZE + pld [pSrc, tmp] + + vld3.8 {d1, d2, d3},[pSrc]! + /* d1 = [b0,b1,b2,b3,b4,b5,b6,b7] */ + /* d2 = [g0,g1,g2,g3,g4,g5,g6,g7] */ + /* d3 = [r0,r1,r2,r3,r4,r5,r6,r7] */ + + vmovl.u8 q2, d3 /* q2 = [r0,r1,r2,r3,r4,r5,r6,r7] */ + vmovl.u8 q1, d2 /* q1 = [g0,g1,g2,g3,g4,g5,g6,g7] */ + vmovl.u8 q0, d1 /* q0 = [b0,b1,b2,b3,b4,b5,b6,b7] */ + + vmov.i16 q3, #1024 /* Y = 16 */ + vmov.i16 q4, #8192 /* Cb = 128 */ + vmov.i16 q5, #8192 /* Cr = 128 */ + + vmla.s16 q3, q2, q15 /* Y += 0.257*R */ + vmla.s16 q3, q1, q14 /* Y += 0.504*G */ + vmla.s16 q3, q0, q13 /* Y += 0.098*B */ + + vmls.s16 q4, q2, q12 /* Cb += -0.148*R */ + vmls.s16 q4, q1, q11 /* Cb += -0.291*G */ + vmla.s16 q4, q0, q10 /* Cb += 0.439*B */ + + vmla.s16 q5, q2, q10 /* Cr += 0.439*R */ + vmls.s16 q5, q1, q9 /* Cr += -0.368*G */ + vmls.s16 q5, q0, q8 /* Cr += -0.071*B */ + + /* compress the YUV >> 6 */ + vrshrn.i16 d1, q3, #6 /* d1 = [y0,y1,y2,y3,y4,y5,y6,y7] = q3 >> 6 */ + vrshrn.i16 d7, q4, #6 /* d7 = [u0,u1,u2,u3,u4,u5,u6,u7] = q4 >> 6 */ + vrshrn.i16 d8, q5, #6 /* d8 = [v0,v1,v2,v3,v4,v5,v6,v7] = q5 >> 6 */ + + /* Interleave */ + vtrn.8 d7, d8 /* d7 = [u0,v0,u2,v2,u4,v4,u6,v6] */ + /* d8 = [u1,v1,u3,v3,u5,v5,u7,v7] */ + vhadd.u8 d0, d7, d8 /* d7 = [u0,v0,u2,v2,u4,v4,u6,v6] (average) */ + /* d6 = [y0,y1,y2,y3,y4,y5,y6,y7] */ + vtrn.8 d0, d1 /* d0 = [u0,y0,u2,y2,u4,y4,u6,y6] */ + /* d1 = [v0,y1,v2,y3,v4,y5,v4,y7] */ + vtrn.16 d0, d1 /* d0 = [u0,y0,v0,y1,u4,y4,v4,y5] */ + /* d1 = [u2,y2,v2,y3,u6,y6,v6,y7] */ + /* Writeback */ + vst2.32 {d0, d1}, [pDst]! + + /* LOOP */ + + subs pixelsLeft, pixelsLeft, #8 + bgt __bgr_to_uyvy_image_bt601_pixel + + add pSrc, pSrc, srcStep + add pDst, pDst, dstStep + + subs linesLeft, linesLeft, #1 + bgt __bgr_to_uyvy_image_bt601_line + + EPILOG r0, r12 +.unreq width +.unreq height +.unreq pSrc +.unreq srcStride +.unreq srcStep +.unreq pDst +.unreq dstStride +.unreq dstStep +.unreq pixelsLeft +.unreq linesLeft +.unreq tmp + +.end diff --git a/libraries/public/yuv/__iyuv_to_bgr_image_bt601.S b/libraries/public/yuv/__iyuv_to_bgr_image_bt601.S new file mode 100644 index 0000000..09a2517 --- /dev/null +++ b/libraries/public/yuv/__iyuv_to_bgr_image_bt601.S @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __iyuv_to_bgr_image_bt601 + +.include "yuv.inc" + +__iyuv_to_bgr_image_bt601: +width .req r0 +height .req r1 +pY .req r2 +pU .req r3 +pV .req r4 +pDst .req r5 +dstStride .req r6 +dstStep .req r7 +pixelsLeft .req r8 +linesLeft .req r9 +uvIndex .req r10 +tmp .req r11 +tmp2 .req r12 + PROLOG r0, r12 + ldr pV, [sp,#(14 * 4)] + ldr pDst, [sp,#(15 * 4)] + ldr dstStride, [sp,#(16 * 4)] + mov linesLeft, height + mov uvIndex, #0 + mov tmp2, #0 + add tmp, width, width /* tmp = 2 * width */ + sub dstStep, dstStride, tmp /* dstStep = dstStride - tmp */ + + FILL_YCBCR_TO_RGB_BT601 q15,q14,q13,q12,q11,d21,d20 +__iyuv_to_bgr_image_bt601_line: + mov pixelsLeft, width +__iyuv_to_bgr_image_bt601_pixel: + + pld [pY] + pld [pY, #L2_LINE_SIZE] + pld [pU] + pld [pV] + + vld1.u8 {d2}, [pY]! /* d2 = [y0,y1,y2,y3,y4,y5,y6,y7] */ + ldr tmp, [pU, uvIndex] + vmov d1, tmp, tmp2 /* d1 = [u0,u2,u4,u6,xx,xx,xx,xx] */ + DUPLICATE_EACH_BYTE d1,d3 /* d1 = [u0,u0,u2,u2,v4,u4,u6,u6] */ + ldr tmp, [pV, uvIndex] + vmov d0, tmp, tmp2 /* d0 = [v0,v2,v4,v6,xx,xx,xx,xx] */ + DUPLICATE_EACH_BYTE d0,d3 /* d0 = [v0,v0,v2,v2,v4,v4,v6,v6] */ + + vsubl.u8 q2, d2, d20 /* q2 = Y - 16 */ + vsubl.u8 q1, d1, d21 /* q1 = Cb - 128 */ + vsubl.u8 q0, d0, d21 /* q0 = Cr - 128 */ + + vmul.s16 q4, q2, q15 /* R = 74*Ye */ + vmla.s16 q4, q0, q12 /* R += 102*Cr */ + vmul.s16 q5, q2, q15 /* G = 74*Ye */ + vmls.s16 q5, q0, q13 /* G -= 52*Cr */ + vmls.s16 q5, q1, q14 /* G -= 25*Cb */ + vmul.s16 q6, q2, q15 /* B = 74*Ye */ + vmla.s16 q6, q1, q11 /* B += 129*Cb */ + + /* Create RGB888 */ + vqshrun.s16 d0, q6, #6 /* B >> 6 */ + vqshrun.s16 d1, q5, #6 /* G >> 6 */ + vqshrun.s16 d2, q4, #6 /* R >> 6 */ + + vst3.8 {d0,d1,d2},[pDst]! + + add uvIndex, uvIndex, #4 + + subs pixelsLeft, pixelsLeft, #8 + bgt __iyuv_to_bgr_image_bt601_pixel + + sub tmp, height, linesLeft + mov tmp, tmp, asr #1 + mul tmp, tmp, width + mov uvIndex, tmp, asr #1 /* reset the uvIndex to the right spot (we'll double process each U/V line) */ + add pDst, pDst, dstStep + + subs linesLeft, linesLeft, #1 + bgt __iyuv_to_bgr_image_bt601_line + + EPILOG r0, r12 +.unreq width +.unreq height +.unreq pY +.unreq pU +.unreq pV +.unreq pDst +.unreq dstStride +.unreq dstStep +.unreq pixelsLeft +.unreq linesLeft +.unreq uvIndex +.unreq tmp +.unreq tmp2 + +.end diff --git a/libraries/public/yuv/__iyuv_to_rgb565_image_bt601.S b/libraries/public/yuv/__iyuv_to_rgb565_image_bt601.S new file mode 100644 index 0000000..4874a0e --- /dev/null +++ b/libraries/public/yuv/__iyuv_to_rgb565_image_bt601.S @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __iyuv_to_rgb565_image_bt601 + +.include "yuv.inc" + +__iyuv_to_rgb565_image_bt601: +width .req r0 +height .req r1 +pY .req r2 +pU .req r3 +pV .req r4 +pDst .req r5 +dstStride .req r6 +dstStep .req r7 +pixelsLeft .req r8 +linesLeft .req r9 +uvIndex .req r10 +tmp .req r11 +tmp2 .req r12 + PROLOG r0, r12 + + ldr pV, [sp,#(14 * 4)] + ldr pDst, [sp,#(15 * 4)] + ldr dstStride, [sp,#(16 * 4)] + mov linesLeft, height + mov uvIndex, #0 + mov tmp2, #0 + add tmp, width, width /* tmp = 2 * width */ + sub dstStep, dstStride, tmp /* dstStep = dstStride - tmp */ + + FILL_YCBCR_TO_RGB_BT601 q15,q14,q13,q12,q11,d21,d20 +__iyuv_to_rgb565_image_bt601_line: + mov pixelsLeft, width +__iyuv_to_rgb565_image_bt601_pixel: + + pld [pY] + pld [pY, #L2_LINE_SIZE] + pld [pU] + pld [pV] + + vld1.u8 {d2}, [pY]! /* d2 = [y0,y1,y2,y3,y4,y5,y6,y7] */ + ldr tmp, [pU, uvIndex] + vmov d1, tmp, tmp2 /* d1 = [u0,u2,u4,u6,xx,xx,xx,xx] */ + DUPLICATE_EACH_BYTE d1,d3 /* d1 = [u0,u0,u2,u2,v4,u4,u6,u6] */ + ldr tmp, [pV, uvIndex] + vmov d0, tmp, tmp2 /* d0 = [v0,v2,v4,v6,xx,xx,xx,xx] */ + DUPLICATE_EACH_BYTE d0,d3 /* d0 = [v0,v0,v2,v2,v4,v4,v6,v6] */ + + vsubl.u8 q2, d2, d20 /* q2 = Y - 16 */ + vsubl.u8 q1, d1, d21 /* q1 = Cb - 128 */ + vsubl.u8 q0, d0, d21 /* q0 = Cr - 128 */ + + vmul.s16 q4, q2, q15 /* R = 74*Ye */ + vmla.s16 q4, q0, q12 /* R += 102*Cr */ + vmul.s16 q5, q2, q15 /* G = 74*Ye */ + vmls.s16 q5, q0, q13 /* G -= 52*Cr */ + vmls.s16 q5, q1, q14 /* G -= 25*Cb */ + vmul.s16 q6, q2, q15 /* B = 74*Ye */ + vmla.s16 q6, q1, q11 /* B += 129*Cb */ + + /* Create RGB888 */ + vqshrun.s16 d0, q6, #6 /* B >> 6 */ + vqshrun.s16 d1, q5, #6 /* G >> 6 */ + vqshrun.s16 d2, q4, #6 /* R >> 6 */ + + RGB888_TO_RGB565 d0, d1, d2, q4, q5, q6, q3 + + vst1.16 {d6}, [pDst]! + vst1.16 {d7}, [pDst]! + + add uvIndex, uvIndex, #4 + + subs pixelsLeft, pixelsLeft, #8 + bne __iyuv_to_rgb565_image_bt601_pixel + + sub tmp, height, linesLeft + mov tmp, tmp, asr #1 + mul tmp, tmp, width + mov uvIndex, tmp, asr #1 /* reset the uvIndex to the right spot (we'll double process each U/V line) */ + add pDst, pDst, dstStep + + subs linesLeft, linesLeft, #1 + bne __iyuv_to_rgb565_image_bt601_line + + EPILOG r0, r12 +.unreq width +.unreq height +.unreq pY +.unreq pU +.unreq pV +.unreq pDst +.unreq dstStride +.unreq dstStep +.unreq pixelsLeft +.unreq linesLeft +.unreq uvIndex +.unreq tmp +.unreq tmp2 + +.end diff --git a/libraries/public/yuv/__iyuv_to_rgbp_image_bt601.S b/libraries/public/yuv/__iyuv_to_rgbp_image_bt601.S new file mode 100644 index 0000000..472a312 --- /dev/null +++ b/libraries/public/yuv/__iyuv_to_rgbp_image_bt601.S @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __iyuv_to_rgbp_image_bt601 + +.include "yuv.inc" + +__iyuv_to_rgbp_image_bt601: +width .req r0 +height .req r1 +pY .req r2 +pU .req r3 +pV .req r4 +srcStride .req r5 +srcStep .req r5 +pR .req r6 +pG .req r7 +pB .req r8 +dstStride .req r9 +dstStep .req r9 +pixelsLeft .req r10 +linesLeft .req r11 +tmp .req r12 + + PROLOG r0, r12 + ldr r4, [sp, #(14*4)] /* pV */ + ldr r5, [sp, #(15*4)] /* srcStride */ + ldr r6, [sp, #(16*4)] /* pR */ + ldr r7, [sp, #(17*4)] /* pG */ + ldr r8, [sp, #(18*4)] /* pB */ + ldr r9, [sp, #(19*4)] /* dstStride */ + mov linesLeft, height + sub srcStep, srcStride, width + sub dstStep, dstStride, width + mov tmp, #L2_LINE_SIZE + FILL_YCBCR_TO_RGB_BT601 q15,q14,q13,q12,q11,d21,d20 +__iyuv_to_rgbp_image_bt601_line: + mov pixelsLeft, width + pld [pY] + pld [pU] + pld [pV] +__iyuv_to_rgbp_image_bt601_pixels: + pld [pY, tmp] + vld1.8 {d2}, [pY]! /* d2 = [y0,y1,y2,y3,y4,y5,y6,y7] */ + vld1.8 {d1}, [pU]! /* d1 = [u0,u1,u2,u3,u4,u5,u6,u7] */ + vld1.8 {d0}, [pV]! /* d0 = [v0,v1,v2,v3,v4,v5,v6,v7] */ + pld [pU, tmp] + vsubl.u8 q2, d2, d20 /* q2 = Y - 16 */ + vsubl.u8 q1, d1, d21 /* q1 = Cb - 128 */ + vsubl.u8 q0, d0, d21 /* q0 = Cr - 128 */ + vmul.s16 q4, q2, q15 /* R = 74*Ye */ + vmla.s16 q4, q0, q12 /* R += 102*Cr */ + vmul.s16 q5, q2, q15 /* G = 74*Ye */ + vmls.s16 q5, q0, q13 /* G -= 52*Cr */ + vmls.s16 q5, q1, q14 /* G -= 25*Cb */ + vmul.s16 q6, q2, q15 /* B = 74*Ye */ + vmla.s16 q6, q1, q11 /* B += 129*Cb */ + pld [pV, tmp] + vqshrun.s16 d0, q6, #6 /* B >> 6 */ + vqshrun.s16 d1, q5, #6 /* G >> 6 */ + vqshrun.s16 d2, q4, #6 /* R >> 6 */ + vst1.8 {d2}, [pR]! + vst1.8 {d1}, [pG]! + vst1.8 {d2}, [pB]! + subs pixelsLeft, pixelsLeft, #8 + bgt __iyuv_to_rgbp_image_bt601_pixels + add pY, pY, srcStep + add pU, pU, srcStep + add pV, pV, srcStep + add pR, pR, dstStep + add pG, pG, dstStep + add pB, pB, dstStep + subs linesLeft, linesLeft, #1 + bgt __iyuv_to_rgbp_image_bt601_line + EPILOG r0, r12 + +.unreq width +.unreq height +.unreq pY +.unreq pU +.unreq pV +.unreq srcStride +.unreq srcStep +.unreq pR +.unreq pG +.unreq pB +.unreq dstStride +.unreq dstStep +.unreq pixelsLeft +.unreq linesLeft +.unreq tmp + +.end diff --git a/libraries/public/yuv/__iyuv_to_uyvy_line.S b/libraries/public/yuv/__iyuv_to_uyvy_line.S new file mode 100644 index 0000000..6419b2d --- /dev/null +++ b/libraries/public/yuv/__iyuv_to_uyvy_line.S @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __yuv420_to_yuv422_line + +.include "yuv.inc" + +__yuv420_to_yuv422_line: +yptr .req r0 +uptr .req r1 +vptr .req r2 +dstptr .req r3 +width .req r4 +ystride .req r5 +dststride .req r6 +tmp7 .req r7 +tmp8 .req r8 +tmp9 .req r9 +tmp10 .req r10 +tmp11 .req r11 +tmp12 .req r12 + + PROLOG r0, r12 + /* load the extra arguments from stack to the register*/ + ldr width, [sp, #(14 * 4)] + ldr ystride, [sp, #(15 * 4)] + ldr dststride, [sp, #(16 * 4)] + + mov tmp7, width /* preserve width register */ + + /* in a given iteration 16 bytes X 2 of yptr is processed, which means 8 x 2 macropixels */ +__yuv420_to_yuv422_line_loop: + + pld [yptr] + pld [yptr, #L2_LINE_SIZE] + pld [uptr] + pld [vptr] + + /* ROW1 processing */ + vld2.8 {d1,d3}, [yptr] /* d1 = y0 y2 y4 y6 y8 yA yC yE */ + /* d3 = y1 y3 y5 y7 y9 yB yD yF */ + add yptr, yptr, ystride + vld1.u8 {d0}, [uptr]! /* d0 = u01xx u23xx u45xx u67xx u89xx uABxx uCDxx uEFxx (xx = next line) */ + vld1.u8 {d2}, [vptr]! /* d2 = v01xx v23xx v45xx v67xx v89xx vABxx vCDxx vEFxx */ + vst4.8 {d0,d1,d2,d3}, [dstptr] /* u01xx y0 v01xx y2... */ + + /* ROW2 processing */ + add dstptr, dstptr, dststride + vld2.8 {d1,d3}, [yptr]! /* d1 = yx yx yx..., d3 = yx yx yx... */ + sub yptr, yptr, ystride /* peg back the yptr back to the original position + PROCESSBYTES */ + vst4.8 {d0,d1,d2,d3}, [dstptr]! /* u01xx yx v01xx yx... (ROW 2) */ + sub dstptr, dstptr, dststride /* peg back the yptr back to the original position + (PROCESSBYTES*2) */ + + subs tmp7, tmp7, #16 + bgt __yuv420_to_yuv422_line_loop + + EPILOG r0, r12 +.unreq yptr +.unreq uptr +.unreq vptr +.unreq dstptr +.unreq width +.unreq ystride +.unreq dststride +.unreq tmp7 +.unreq tmp8 +.unreq tmp9 +.unreq tmp10 +.unreq tmp11 +.unreq tmp12 + +.end diff --git a/libraries/public/yuv/__luma_to_uyvy_image.S b/libraries/public/yuv/__luma_to_uyvy_image.S new file mode 100644 index 0000000..531e602 --- /dev/null +++ b/libraries/public/yuv/__luma_to_uyvy_image.S @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __luma_to_uyvy_image + +.include "yuv.inc" + +__luma_to_uyvy_image: +width .req r0 +height .req r1 +pY .req r2 +srcStride .req r3 +pUYVY .req r4 +dstStride .req r5 +linesLeft .req r6 +srcStep .req r7 +dstStep .req r8 +tmp .req r9 +pixelsLeft .req r10 + PROLOG r0, r10 + ldr pUYVY, [sp, #(12 * 4)] + ldr dstStride, [sp, #(13 * 4)] + mov linesLeft, height + add tmp, width, width + sub srcStep, srcStride, width + sub dstStep, dstStride, tmp + /* Prime q1 with U/V values that are "zero" */ + vmov.u16 q2, #0x0080 +__luma_to_uyvy_image_lines: + mov pixelsLeft, width + pld [pY] + pld [pY, srcStride] +__luma_to_uyvy_image_pixels: + pld [pY, #L2_LINE_SIZE] + add tmp, pY, srcStride + pld [tmp, #L2_LINE_SIZE] + vld1.8 {d0}, [pY]! + vld1.8 {d1}, [pY]! + /* Load q1 first so that d1 isn't corrupted */ + vshll.u16 q1, d1, #8 + vshll.u16 q0, d0, #8 + vorr.16 q1, q1, q2 + vorr.16 q0, q0, q2 + vst1.8 {d0}, [pUYVY]! + vst1.8 {d1}, [pUYVY]! + vst1.8 {d2}, [pUYVY]! + vst1.8 {d3}, [pUYVY]! + subs pixelsLeft, #16 + bgt __luma_to_uyvy_image_pixels + add pY, pY, srcStep + add pUYVY, pUYVY, dstStep + subs linesLeft, linesLeft, #1 + bgt __luma_to_uyvy_image_lines + EPILOG r0, r10 +.unreq width +.unreq height +.unreq pY +.unreq srcStride +.unreq pUYVY +.unreq dstStride +.unreq linesLeft +.unreq srcStep +.unreq dstStep +.unreq tmp +.unreq pixelsLeft + +.end diff --git a/libraries/public/yuv/__nv12_to_half_yuv444_image.S b/libraries/public/yuv/__nv12_to_half_yuv444_image.S new file mode 100644 index 0000000..81b6d87 --- /dev/null +++ b/libraries/public/yuv/__nv12_to_half_yuv444_image.S @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __nv12_to_half_yuv444_image + +.include "yuv.inc" + +/** This function takes a NV12 image and 1/2 scales the Luma plane and separates the UV plane. The function assumes a packed set of Y/UV planes */ +__nv12_to_half_yuv444_image: +width .req r0 +height .req r1 +pY0 .req r2 +pUV .req r3 +srcStride .req r4 +pY .req r5 +pU .req r6 +pV .req r7 +dstStride .req r8 +linesLeft .req r9 +pixelsLeft .req r10 +tmp .req r11 +preLoadIdx .req r12 + PROLOG r0, r12 + ldr srcStride, [sp, #(14 * 4)] + ldr pY, [sp, #(15 * 4)] + ldr pU, [sp, #(16 * 4)] + ldr pV, [sp, #(17 * 4)] + ldr dstStride, [sp, #(18 * 4)] + + /* Use the height of the destination to control the loop */ + mov linesLeft, height, lsr #1 + +__nv12_to_half_yuv444_image_lines: + + /* Use the width of the destination to control the loop */ + mov pixelsLeft, width, lsr #1 + + /* Force the preload on the next block */ + mov preLoadIdx, #(L2_LINE_SIZE/16) + + /* Preload first block for 3 lines worth */ + mov tmp, pY0 + pld [tmp] + add tmp, pY0, srcStride + pld [tmp] + mov tmp, pUV + pld [tmp] + ldr tmp, [tmp] /* wait for the preload to finish */ + +__nv12_to_half_yuv444_image_pixels: + + /* Preload the next block if the index is correct */ + subs preLoadIdx, preLoadIdx, #(L2_LINE_SIZE/16) + bne __nv12_to_half_yuv444_image_algo + add tmp, pY0, #L2_LINE_SIZE + pld [tmp] + add tmp, tmp, srcStride + pld [tmp] + add tmp, pUV, #L2_LINE_SIZE + pld [tmp] + +__nv12_to_half_yuv444_image_algo: + add preLoadIdx, preLoadIdx, #1 + + add tmp, pY0, srcStride + vld1.8 {d0}, [pY0]! + vld1.8 {d1}, [pY0]! + vld1.8 {d2}, [tmp]! + vld1.8 {d3}, [tmp]! + + /* Average 16x2 to 8x1 */ + vpaddl.u8 d0, d0 + vpaddl.u8 d1, d1 + vpaddl.u8 d2, d2 + vpaddl.u8 d3, d3 + vqadd.u16 d0, d0, d2 + vqadd.u16 d1, d1, d3 + vshrn.u16 d0, q0, #2 + /* Store 8x1 */ + vst1.8 {d0}, [pY]! + + /* Split UV plane into U/V planes */ + vld2.8 {d4, d5}, [pUV]! + vst1.8 {d4}, [pU]! + vst1.8 {d5}, [pV]! + + subs pixelsLeft, pixelsLeft, #8 + bgt __nv12_to_half_yuv444_image_pixels + + /* update the pY0, pUV with the correct step */ + sub tmp, srcStride, width + add pY0, pY0, tmp + add pY0, pY0, srcStride + add pUV, pUV, tmp /* since this is a packed plane, the "step" is the same */ + + /* update the pY,pU,pV pointers */ + sub tmp, dstStride, width, lsr #1 + add pY, pY, tmp + add pU, pU, tmp + add pV, pV, tmp + + subs linesLeft, linesLeft, #1 + bgt __nv12_to_half_yuv444_image_lines + + EPILOG r0, r12 + +.unreq preLoadIdx +.unreq tmp +.unreq pixelsLeft +.unreq linesLeft +.unreq dstStride +.unreq pY +.unreq pU +.unreq pV +.unreq srcStride +.unreq pUV +.unreq pY0 +.unreq height +.unreq width + +.end diff --git a/libraries/public/yuv/__planar_rotate_ccw90.S b/libraries/public/yuv/__planar_rotate_ccw90.S new file mode 100644 index 0000000..b2a64c0 --- /dev/null +++ b/libraries/public/yuv/__planar_rotate_ccw90.S @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __planar_rotate_ccw90 + +.include "yuv.inc" + +/** These are the VTBL constants for a 90 counterclockwise rotation. */ +COUNTERCLOCKWISE_90_ROTATE: + .long 0x1F170F07 + .long 0x1E160E06 + .long 0x1D150D05 + .long 0x1C140C04 + .long 0x1B130B03 + .long 0x1A120A02 + .long 0x19110901 + .long 0x18100800 + +/** + * This subroutine rotates YUV420P data in 8x8 byte blocks. This means that the + * U,V fields will be rotated this way as well which means that the image + * dimensions must be a multiple of 16. + */ +__planar_rotate_ccw90: +width .req r0 +dstHeight .req r0 +height .req r1 +dstWidth .req r1 +pSrc .req r2 +pDst .req r3 +pixelsLeft .req r4 +linesLeft .req r5 +tmp .req r6 +dstStride .req r7 +pTmp1 .req r8 +pTmp2 .req r9 +pTmp3 .req r10 +pTmp4 .req r11 +count .req r12 + PROLOG r0, r12 + + mov pixelsLeft, width + mov linesLeft, height + mov count, #0 + + ldr tmp, =COUNTERCLOCKWISE_90_ROTATE + vld1.u8 {d8}, [tmp]! + vld1.u8 {d9}, [tmp]! + vld1.u8 {d10},[tmp]! + vld1.u8 {d11},[tmp]! + + /* dstStride = height# */ + mov dstStride, height + +__planar_rotate_ccw90_height: + + /* move the pDst to the bottom of the first column */ + sub tmp, dstHeight, #8 + mul tmp, tmp, dstStride + add pTmp1, pDst, tmp + + /* move the pTmp1 to the correct column of the pDst. */ + sub tmp, dstWidth, linesLeft + add pTmp4, pTmp1, tmp + + /* reset pixelsLeft */ + mov pixelsLeft, width + +__planar_rotate_ccw90_width: + + mov pTmp2, pSrc + mov pTmp3, pSrc + preload_L2_4x64bytes pTmp3, width, tmp + + /* load the first half of the block */ + vld1.u8 {d0}, [pTmp2], width + vld1.u8 {d1}, [pTmp2], width + vld1.u8 {d2}, [pTmp2], width + vld1.u8 {d3}, [pTmp2], width + + mov pTmp3, pTmp2 + preload_L2_4x64bytes pTmp3, width, tmp + + /* start the transpose */ + vtbl.8 d12, {d0,d1,d2,d3}, d8 + vtbl.8 d14, {d0,d1,d2,d3}, d9 + vtbl.8 d16, {d0,d1,d2,d3}, d10 + vtbl.8 d18, {d0,d1,d2,d3}, d11 + + /* load the second half of the block */ + vld1.u8 {d4}, [pTmp2], width + vld1.u8 {d5}, [pTmp2], width + vld1.u8 {d6}, [pTmp2], width + vld1.u8 {d7}, [pTmp2] + + /* complete the transpose of the block indexes */ + vtbl.8 d13, {d4,d5,d6,d7}, d8 + vtbl.8 d15, {d4,d5,d6,d7}, d9 + vtbl.8 d17, {d4,d5,d6,d7}, d10 + vtbl.8 d19, {d4,d5,d6,d7}, d11 + + /* swap the indexes around */ + vtrn.32 d12, d13 + vtrn.32 d14, d15 + vtrn.32 d16, d17 + vtrn.32 d18, d19 + + /* now store the rotated data */ + vst1.8 {d12}, [pTmp4], dstStride + vst1.8 {d13}, [pTmp4], dstStride + vst1.8 {d14}, [pTmp4], dstStride + vst1.8 {d15}, [pTmp4], dstStride + vst1.8 {d16}, [pTmp4], dstStride + vst1.8 {d17}, [pTmp4], dstStride + vst1.8 {d18}, [pTmp4], dstStride + vst1.8 {d19}, [pTmp4], dstStride + + /* LOOP UPKEEP */ + add count, count, #1 + + /* move the pTmp4 pointer up 16 lines */ + mov tmp, #16 + mul tmp, dstStride, tmp + sub pTmp4, pTmp4, tmp + + /* move source pointer */ + add pSrc, pSrc, #8 + + subs pixelsLeft, pixelsLeft, #8 + bgt __planar_rotate_ccw90_width + + /* move the source pointer around the line */ + mov tmp, #7 + mul tmp, tmp, width + add pSrc, pSrc, tmp + + subs linesLeft, linesLeft, #8 + bgt __planar_rotate_ccw90_height + mov r0, count + + EPILOG r0, r12 +.unreq width +.unreq dstHeight +.unreq height +.unreq dstWidth +.unreq pSrc +.unreq pDst +.unreq pixelsLeft +.unreq linesLeft +.unreq tmp +.unreq dstStride +.unreq pTmp1 +.unreq pTmp2 +.unreq pTmp3 +.unreq pTmp4 +.unreq count + +.end diff --git a/libraries/public/yuv/__planar_rotate_cw90.S b/libraries/public/yuv/__planar_rotate_cw90.S new file mode 100644 index 0000000..9027dfe --- /dev/null +++ b/libraries/public/yuv/__planar_rotate_cw90.S @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __planar_rotate_cw90 + +.include "yuv.inc" + +/** These are the VTBL constants for a 90 clockwise rotation. */ +CLOCKWISE_90_ROTATE: + .long 0x00081018 + .long 0x01091119 + .long 0x020A121A + .long 0x030B131B + .long 0x040C141C + .long 0x050D151D + .long 0x060E161E + .long 0x070F171F + +/** + * This subroutine rotates YUV420P data in 8x8 byte blocks. This means that the + * U,V fields will be rotated this way as well which means that the image + * diensions must be a multiple of 16. + */ +__planar_rotate_cw90: +width .req r0 +dstHeight .req r0 +height .req r1 +dstWidth .req r1 +pSrc .req r2 +pDst .req r3 +pixelsLeft .req r4 +linesLeft .req r5 +tmp .req r6 +dstStride .req r7 +pTmp1 .req r8 +pTmp2 .req r9 +pTmp3 .req r10 +pTmp4 .req r11 +count .req r12 + PROLOG r0, r12 + + mov pixelsLeft, width + mov linesLeft, height + + ldr tmp, =CLOCKWISE_90_ROTATE + vld1.u8 {d8}, [tmp]! + vld1.u8 {d9}, [tmp]! + vld1.u8 {d10},[tmp]! + vld1.u8 {d11},[tmp]! + + /* dstStride = height# */ + mov dstStride, height + +__planar_rotate_cw90_height: + + /* move the pTmp4 to the correct column of the pDst. */ + sub tmp, linesLeft, #8 + add pTmp4, pDst, tmp + + /* reset pixelsLeft */ + mov pixelsLeft, width + +__planar_rotate_cw90_width: + + mov pTmp2, pSrc + mov pTmp3, pSrc + preload_L2_4x64bytes pTmp3, width, tmp + + /* load the first half of the block */ + vld1.u8 {d0}, [pTmp2], width + vld1.u8 {d1}, [pTmp2], width + vld1.u8 {d2}, [pTmp2], width + vld1.u8 {d3}, [pTmp2], width + + mov pTmp3, pTmp2 + preload_L2_4x64bytes pTmp3, width, tmp + + /* start the transpose */ + vtbl.8 d13, {d0,d1,d2,d3}, d8 + vtbl.8 d15, {d0,d1,d2,d3}, d9 + vtbl.8 d17, {d0,d1,d2,d3}, d10 + vtbl.8 d19, {d0,d1,d2,d3}, d11 + + /* load the second half of the block */ + vld1.u8 {d4}, [pTmp2], width + vld1.u8 {d5}, [pTmp2], width + vld1.u8 {d6}, [pTmp2], width + vld1.u8 {d7}, [pTmp2] + + /* complete the transpose of the block indexes */ + vtbl.8 d12, {d4,d5,d6,d7}, d8 + vtbl.8 d14, {d4,d5,d6,d7}, d9 + vtbl.8 d16, {d4,d5,d6,d7}, d10 + vtbl.8 d18, {d4,d5,d6,d7}, d11 + + /* swap the indexes around */ + vtrn.32 d12, d13 + vtrn.32 d14, d15 + vtrn.32 d16, d17 + vtrn.32 d18, d19 + + /* now store the rotated data */ + vst1.8 {d12}, [pTmp4], dstStride + vst1.8 {d13}, [pTmp4], dstStride + vst1.8 {d14}, [pTmp4], dstStride + vst1.8 {d15}, [pTmp4], dstStride + vst1.8 {d16}, [pTmp4], dstStride + vst1.8 {d17}, [pTmp4], dstStride + vst1.8 {d18}, [pTmp4], dstStride + vst1.8 {d19}, [pTmp4], dstStride + + add count, count, #1 + + /* pTmp4 will simply continue to increment in the vst1.8 above */ + /* no extra fixup is needed. */ + + /* move source pointer */ + add pSrc, pSrc, #8 + + subs pixelsLeft, pixelsLeft, #8 + bgt __planar_rotate_cw90_width + + /* move the source pointer around the line */ + mov tmp, #7 + mul tmp, tmp, width + add pSrc, pSrc, tmp + + subs linesLeft, linesLeft, #8 + bgt __planar_rotate_cw90_height + mov r0, count + + EPILOG r0, r12 +.unreq width +.unreq dstHeight +.unreq height +.unreq dstWidth +.unreq pSrc +.unreq pDst +.unreq pixelsLeft +.unreq linesLeft +.unreq tmp +.unreq dstStride +.unreq pTmp1 +.unreq pTmp2 +.unreq pTmp3 +.unreq pTmp4 +.unreq count + +.end diff --git a/libraries/public/yuv/__uyvy_half_scale_image.S b/libraries/public/yuv/__uyvy_half_scale_image.S new file mode 100644 index 0000000..df13b97 --- /dev/null +++ b/libraries/public/yuv/__uyvy_half_scale_image.S @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __uyvy_half_scale_image + +.include "yuv.inc" + +/** + * A subroutine to scale down a UYVY Image by half (in a 32x2 pixel block) + */ +__uyvy_half_scale_image: +width .req r0 +height .req r1 +pSrc .req r2 +srcStride .req r3 +pDst .req r4 +dstStride .req r5 +dstStep .req r5 +pSrcNext .req r6 +linesLeft .req r7 +pixelsLeft .req r8 +subwidth .req r9 +tmp .req r10 +tmp2 .req r11 +srcStep .req r12 + PROLOG r0, r12 + + ldr pDst, [sp, #(14 * 4)] + ldr dstStride, [sp, #(15 * 4)] + mov linesLeft, height + mov tmp, width, lsl #1 /* tmp = 2 * width */ + sub srcStep, srcStride, tmp /* srcStep = srcStride - (2 * width) */ + sub dstStep, dstStride, width /* dstStep = dstStride - (2 * width/2) */ + +__uyvy_half_scale_image_loop_line: + add pSrcNext, pSrc, srcStride + mov tmp, #0x1F + and subwidth, width, tmp /* subwidth = width % 32 (tells us if there's a problem with doing this by 32) */ + + /* Update the number of pixels left for this line. */ + sub pixelsLeft, width, subwidth /* pixelsLeft = width - subwidth */ + + /* Does this width even divide by 32? if not we'll operate on a 4 pixel group until we clear the subwidth */ + mov tmp, #0 + cmp subwidth, tmp + beq __uyvy_half_scale_image_loop_32pixels + +__uyvy_half_scale_image_loop_4pixels: + + pld [pSrc] + pld [pSrc, #L2_LINE_SIZE] + pld [pSrcNext] + pld [pSrcNext, #L2_LINE_SIZE] + + /* can't use ARMv6 code as we don't have enough registers and we don't want to have to push/pop here */ + vld1.64 {d0},[pSrc]! /* Load 2 macro pixels on row n */ + vld1.64 {d1},[pSrcNext]! /* Load 2 macro pixels on row n+1 */ + + vhadd.u8 d2, d0, d1 /* Average of Rows U/V */ + vmov.u8 d3, #0 /* Clear out D1 */ + vtrn.32 d2, d3 + vhadd.u8 d4, d2, d3 /* Average of Columns U/V */ + vtrn.16 d2, d3 + vhadd.u8 d5, d2, d3 /* Average of Columns Y's */ + vshr.u16 d5, d5, #8 /* Move the Y's down */ + vtrn.8 d4, d5 + vmov tmp, tmp2, d4 + str tmp, [pDst]! + + subs subwidth, subwidth, #4 + bgt __uyvy_half_scale_image_loop_4pixels + +__uyvy_half_scale_image_loop_32pixels: + + pld [pSrc] + pld [pSrc, #L2_LINE_SIZE] + pld [pSrcNext] + pld [pSrcNext, #L2_LINE_SIZE] + + vld4.8 {d0, d1, d2, d3},[pSrc]! + vld4.8 {d4, d5, d6, d7},[pSrc]! + vld4.8 {d8, d9, d10,d11},[pSrcNext]! + vld4.8 {d12,d13,d14,d15},[pSrcNext]! + + /* See macro for load/store conventions. */ + uyvy_32x2_average d0,d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15 + + vst2.16 {d0,d1}, [pDst]! + vst2.16 {d4,d5}, [pDst]! + + /* END OF LOOP */ + + subs pixelsLeft, pixelsLeft, #32 + bgt __uyvy_half_scale_image_loop_32pixels + + add pSrc, pSrc, srcStep + add pSrc, pSrc, srcStride + add pDst, pDst, dstStep + + subs linesLeft, linesLeft, #2 + bgt __uyvy_half_scale_image_loop_line + + EPILOG r0, r12 +.unreq width +.unreq height +.unreq pSrc +.unreq srcStride +.unreq pDst +.unreq dstStride +.unreq dstStep +.unreq pSrcNext +.unreq linesLeft +.unreq pixelsLeft +.unreq subwidth +.unreq tmp +.unreq tmp2 +.unreq srcStep + +.end diff --git a/libraries/public/yuv/__uyvy_horizontal_mirror_image.S b/libraries/public/yuv/__uyvy_horizontal_mirror_image.S new file mode 100644 index 0000000..3fb4510 --- /dev/null +++ b/libraries/public/yuv/__uyvy_horizontal_mirror_image.S @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __uyvy_horizontal_mirror_image + +.include "yuv.inc" + +/** This function mirror's a UYVY image horizontally. */ +__uyvy_horizontal_mirror_image: +width .req r0 +height .req r1 +pSrc .req r2 +srcStride .req r3 +pDst .req r4 +dstStride .req r5 +linesLeft .req r6 +pixelsLeft .req r7 +tmp .req r8 +dstStep .req r9 +tmp2 .req r10 +srcStep .req r11 + + PROLOG r0, r12 + + ldr pDst, [sp, #(14 * 4)] + ldr dstStride, [sp, #(15 * 4)] + + /* inititalize the lines count */ + mov linesLeft, height + + /* initialize the srcStep */ + mov tmp, width + mov tmp, tmp, lsl #1 + sub srcStep, srcStride, tmp + +__uyvy_horizontal_mirror_image_line: + + preload_L2_1x256bytes pSrc + + /* reset the pixels */ + mov pixelsLeft, width + + /* move pDst to the end of the line (last UYVY) */ + sub tmp, width, #2 + mov tmp, tmp, lsl #1 + add pDst, pDst, tmp /* pDst += ((width-2)*2) */ + + /* find out if there's an non-multiple number of units */ + mov tmp, #0x1F + and tmp2, width, tmp /* tmp2 = width%32 */ + + /* if there arent't then go to pre_blocks */ + mov tmp, #0 + cmp tmp2, tmp + beq __uyvy_horizontal_mirror_image_pre_blocks + +__uyvy_horizontal_mirror_image_spare: + + /* reverse a single DWORD and write it out */ + ldr tmp, [pSrc] /* tmp = *pSrc */ + add pSrc, pSrc, #4 + /* tmp = U0 Y0 V0 Y1 */ + rev16 tmp, tmp /* tmp = Y0 U0 Y1 V0 */ + mov tmp, tmp, ror #8 /* tmp = U0 Y1 V0 Y0 */ + str tmp, [pDst] /* *pDst = tmp */ + + sub pDst, pDst, #4 + sub pixelsLeft, pixelsLeft, #2 + subs tmp2, tmp2, #2 + bgt __uyvy_horizontal_mirror_image_spare + +__uyvy_horizontal_mirror_image_pre_blocks: + + /* move pDst back 28 more bytes to account for the block size */ + sub pDst, pDst, #28 + mov tmp, #-32 + +__uyvy_horizontal_mirror_image_blocks: + + mov tmp2, #0xFF + add tmp2, tmp2, #1 + add tmp2, pSrc, tmp2 + preload_L2_1x256bytes tmp2 + + vld4.8 {d0,d1,d2,d3}, [pSrc]! + vswp.8 d1,d3 + REVERSE d0, d0 + REVERSE d1, d1 + REVERSE d2, d2 + REVERSE d3, d3 + vst4.8 {d0,d1,d2,d3}, [pDst], tmp + + subs pixelsLeft, pixelsLeft, #16 + bgt __uyvy_horizontal_mirror_image_blocks + + /* add a stride to the pDst */ + mov tmp, #0x20 /* tmp = 32 */ + add tmp, dstStride, tmp /* tmp += dstStride */ + add pDst, pDst, tmp /* pDst += tmp */ + add pSrc, pSrc, srcStep /* pSrc += srcStep */ + + subs linesLeft, linesLeft, #1 + bgt __uyvy_horizontal_mirror_image_line + + EPILOG r0, r12 +.unreq width +.unreq height +.unreq pSrc +.unreq srcStride +.unreq pDst +.unreq dstStride +.unreq linesLeft +.unreq pixelsLeft +.unreq tmp +.unreq dstStep +.unreq tmp2 +.unreq srcStep + +.end diff --git a/libraries/public/yuv/__uyvy_luma_extract.S b/libraries/public/yuv/__uyvy_luma_extract.S new file mode 100644 index 0000000..0a80a5d --- /dev/null +++ b/libraries/public/yuv/__uyvy_luma_extract.S @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __uyvy_luma_extract + +.include "yuv.inc" + +__uyvy_luma_extract: + +width .req r0 +height .req r1 +pYUV .req r2 +srcStride .req r3 +pY .req r4 +dstStride .req r5 +linesLeft .req r6 +srcStep .req r7 +dstStep .req r8 +tmp .req r9 +pixelsLeft .req r10 + PROLOG r0, r10 + ldr pY, [sp, #(12 * 4)] + ldr dstStride, [sp, #(13 * 4)] + mov linesLeft, height + add tmp, width, width + sub srcStep, srcStride, tmp + sub dstStep, dstStride, width +__uyvy_luma_extract_lines: + mov pixelsLeft, width + pld [pYUV] + pld [pYUV, srcStride] +__uyvy_luma_extract_pixels: + pld [pYUV, #L2_LINE_SIZE] + add tmp, pYUV, srcStride + pld [tmp, #L2_LINE_SIZE] + vld4.8 {d0,d1,d2,d3}, [pYUV]! + vst2.8 {d1,d3}, [pY]! + subs pixelsLeft, #16 + bgt __uyvy_luma_extract_pixels + add pYUV, pYUV, srcStep + add pY, pY, dstStep + subs linesLeft, linesLeft, #1 + bgt __uyvy_luma_extract_lines + EPILOG r0, r10 +.unreq width +.unreq height +.unreq pYUV +.unreq srcStride +.unreq pY +.unreq dstStride +.unreq linesLeft +.unreq srcStep +.unreq dstStep +.unreq tmp +.unreq pixelsLeft + +.end diff --git a/libraries/public/yuv/__uyvy_qtr_scale_image.S b/libraries/public/yuv/__uyvy_qtr_scale_image.S new file mode 100644 index 0000000..acace03 --- /dev/null +++ b/libraries/public/yuv/__uyvy_qtr_scale_image.S @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __uyvy_qtr_scale_image + +.include "yuv.inc" + +__uyvy_qtr_scale_image: +width .req r0 +height .req r1 +pSrc .req r2 +srcStride .req r3 +pDst .req r4 +dstStride .req r5 +dstStep .req r5 +preLoadIdx .req r6 +linesLeft .req r7 +pixelsLeft .req r8 +tmp .req r9 +tmp2 .req r10 +tmp3 .req r11 +srcStep .req r12 + PROLOG r0, r12 + + /* FAULT + mov tmp, #0 + ldr tmp, [tmp] + */ + ldr pDst, [sp, #(14 * 4)] + ldr dstStride, [sp, #(15 * 4)] + mov linesLeft, height + mov tmp, width, lsl #1 /* tmp = 2 * width */ + sub srcStep, srcStride, tmp /* srcStep = srcStride - (2 * width) */ + mov tmp, tmp, lsr #2 /* tmp = (2 * width) / 4 */ + sub dstStep, dstStride, tmp /* dstStep = dstStride - (2 * width / 4) */ + +__uyvy_qtr_scale_image_loop_line: + + /* Update the number of pixels left for this line. */ + mov pixelsLeft, width + + /* Force the preload on the next block */ + mov preLoadIdx, #(L2_LINE_SIZE/16) + + /* Preload first block for 4 lines worth */ + mov tmp, pSrc + pld [tmp] + add tmp, tmp, srcStride + pld [tmp] + add tmp, tmp, srcStride + pld [tmp] + add tmp, tmp, srcStride + pld [tmp] + ldr tmp2, [tmp] /* wait for the preload to finish */ + +__uyvy_qtr_scale_image_loop_pixels: + + /* Preload the next block if the index is correct */ + subs preLoadIdx, preLoadIdx, #(L2_LINE_SIZE/16) + bne __uyvy_qtr_scale_image_loop_algo + add tmp, pSrc, #L2_LINE_SIZE + pld [tmp] + add tmp, tmp, srcStride + pld [tmp] + add tmp, tmp, srcStride + pld [tmp] + add tmp, tmp, srcStride + pld [tmp] +__uyvy_qtr_scale_image_loop_algo: + add preLoadIdx, preLoadIdx, #1 + + /* Loads U/V into D(even), Y0,Y1 into D(odd) */ + mov tmp, pSrc + vld2.8 {d0, d1}, [tmp] + add tmp, tmp, srcStride + vld2.8 {d2, d3}, [tmp] + add tmp, tmp, srcStride + vld2.8 {d4, d5}, [tmp] + add tmp, tmp, srcStride + vld2.8 {d6, d7}, [tmp] + add pSrc, pSrc, #16 + + /* Horizontally Average the Y values */ + vpaddl.u8 d1, d1 + vpaddl.u8 d3, d3 + vpaddl.u8 d5, d5 + vpaddl.u8 d7, d7 + vpaddl.u16 d1, d1 + vpaddl.u16 d3, d3 + vpaddl.u16 d5, d5 + vpaddl.u16 d7, d7 + + /* Vertically Average the Y's */ + vadd.u32 d1, d3, d1 + vadd.u32 d1, d5, d1 + vadd.u32 d1, d7, d1 + vshr.u32 d1, d1, #4 + + /* Y0 and Y1 are in D1 as U32's but should be u8 values */ + + /* Rearrange the U/V to U's and V's */ + vuzp.u8 d0, d2 + vuzp.u8 d4, d6 + + /* Average all U's and all V's into one U0, V0 value */ + vpaddl.u8 d0, d0 + vpaddl.u8 d2, d2 + vpaddl.u8 d4, d4 + vpaddl.u8 d6, d6 + vadd.u16 d0, d4, d0 + vadd.u16 d2, d6, d2 + vpaddl.u16 d0, d0 + vpaddl.u16 d2, d2 + vpaddl.u32 d0, d0 + vpaddl.u32 d2, d2 + vshr.u64 d0, d0, #4 + vshr.u64 d2, d2, #4 + + /* U0 is in D0 as a u64 but should be u8 value */ + /* V0 is in D2 as a u64 but should be u8 value */ + + /* Transfer the UYVY Data to an ARM register */ + vmov tmp, tmp2, d1 /* Move Y0 to tmp, Y1 to tmp */ + usat tmp, #8, tmp + usat tmp2, #8, tmp2 + mov tmp, tmp, lsl #8 + mov tmp2, tmp2, lsl #24 + orr tmp, tmp, tmp2 + vmov tmp2, tmp3, d0 /* Move U0 to tmp2 */ + usat tmp2, #8, tmp2 + orr tmp, tmp, tmp2 + vmov tmp2, tmp3, d2 /* Move V0 to tmp2 */ + usat tmp2, #8, tmp2 + mov tmp2, tmp2, lsl #16 + orr tmp, tmp, tmp2 + + str tmp, [pDst] /* *pDst = tmp */ + add pDst, pDst, #4 /* pDst += 4 */ + + /* END OF LOOP */ + + subs pixelsLeft, pixelsLeft, #8 + bgt __uyvy_qtr_scale_image_loop_pixels + + add pSrc, pSrc, srcStep + add pSrc, pSrc, srcStride + add pSrc, pSrc, srcStride + add pSrc, pSrc, srcStride /* skip 3 extra lines */ + add pDst, pDst, dstStep + + subs linesLeft, linesLeft, #4 + bgt __uyvy_qtr_scale_image_loop_line + + EPILOG r0, r12 +.unreq width +.unreq height +.unreq pSrc +.unreq srcStride +.unreq pDst +.unreq dstStride +.unreq dstStep +.unreq linesLeft +.unreq pixelsLeft +.unreq tmp +.unreq tmp2 +.unreq tmp3 +.unreq srcStep + +.end diff --git a/libraries/public/yuv/__uyvy_rotate_ccw90.S b/libraries/public/yuv/__uyvy_rotate_ccw90.S new file mode 100644 index 0000000..831a78b --- /dev/null +++ b/libraries/public/yuv/__uyvy_rotate_ccw90.S @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __uyvy_rotate_ccw90 + +.include "yuv.inc" + +/** + * These indexes allow the YUV422 CW90 rotate for UV values to work, use with VTBX + * TABLE (LSB) + * d[n+0] = XX Y0 XX Y1 XX Y2 XX Y3 + * d[n+1] = XX Y8 XX Y9 XX YA XX YB + * d[n+2] = U0 XX V0 XX U2 XX V2 XX + */ +XYXY_CCW90_INDEXES: +/* (MSB) */ + .long 0x0F160710 /* LSB MSB */ + .long 0xFFFFFFFF /* d[m+0] = [10][07][16][0F][XX][XX][XX][XX] */ + .long 0x0D160510 + .long 0xFFFFFFFF /* d[m+1] = [10][05][16][0D][XX][XX][XX][XX] */ + .long 0x0B120314 + .long 0xFFFFFFFF /* d[m+2] = [14][03][12][0B][XX][XX][XX][XX] */ + .long 0x09120114 + .long 0xFFFFFFFF /* d[m+3] = [14][01][12][09][XX][XX][XX][XX] */ +/* (MSB) */ + .long 0xFFFFFFFF /* LSB MSB */ + .long 0x0F160710 /* d[m+4] = [XX][XX][XX][XX][10][07][16][0F] */ + .long 0xFFFFFFFF + .long 0x0D160510 /* d[m+5] = [XX][XX][XX][XX][10][05][16][0D] */ + .long 0xFFFFFFFF + .long 0x0B120314 /* d[m+6] = [XX][XX][XX][XX][14][03][12][0B] */ + .long 0xFFFFFFFF + .long 0x09120114 /* d[m+7] = [XX][XX][XX][XX][14][01][12][09] */ + +/** + * This subroutine rotates YUV422I data in 4x8 pixel blocks. + */ +__uyvy_rotate_ccw90: +width .req r0 +dstHeight .req r0 +height .req r1 +dstWidth .req r1 +pSrc .req r2 +pDst .req r3 +srcStride .req r4 +dstStride .req r5 +pixelsLeft .req r6 +linesLeft .req r7 +tmp .req r8 +pSrcTmp .req r9 +pDstTmp .req r10 +count .req r11 + PROLOG r0, r12 + ldr srcStride, [sp, #(14 * 4)] + ldr dstStride, [sp, #(15 * 4)] + mov pixelsLeft, width + mov linesLeft, height + mov count, #0 + + ldr tmp, =XYXY_CCW90_INDEXES + vld1.u8 {d12}, [tmp]! + vld1.u8 {d13}, [tmp]! + vld1.u8 {d14}, [tmp]! + vld1.u8 {d15}, [tmp]! + vld1.u8 {d16}, [tmp]! + vld1.u8 {d17}, [tmp]! + vld1.u8 {d18}, [tmp]! + vld1.u8 {d19}, [tmp]! + + /* move the pDst to the bottom of the first column */ + sub tmp, dstHeight, #1 + mul tmp, tmp, dstStride + add pDst, pDst, tmp + + /* invert the dstStride */ + mov tmp, #0 + sub dstStride, tmp, dstStride + +__uyvy_rotate_ccw90_height: + + /* move the Destination pointer to it's location */ + sub tmp, height, linesLeft + mov tmp, tmp, lsl #1 + add pDstTmp, pDst, tmp + + /* reset the number of pixels left on each line */ + mov pixelsLeft, width + +__uyvy_rotate_ccw90_width: + + mov pSrcTmp, pSrc + + /* preload the data */ + pld [pSrcTmp] + pld [pSrcTmp, srcStride] + + /* load the line */ + vld1.u8 {d0,d1}, [pSrcTmp], srcStride + vld1.u8 {d3,d4}, [pSrcTmp], srcStride + + /* preload the next 2 lines */ + pld [pSrcTmp] + pld [pSrcTmp, srcStride] + + /* create the average U/V's */ + vswp.8 d1, d3 /* prep the data */ + vhadd.u8 d2, d0, d1 + vhadd.u8 d5, d3, d4 + + /* index the data into the destination YUV422 buffer */ + vtbx.8 d24, {d0,d1,d2}, d12 + vtbx.8 d25, {d0,d1,d2}, d13 + vtbx.8 d26, {d0,d1,d2}, d14 + vtbx.8 d27, {d0,d1,d2}, d15 + /* index the second half of the output */ + vtbx.8 d20, {d3,d4,d5}, d12 + vtbx.8 d21, {d3,d4,d5}, d13 + vtbx.8 d22, {d3,d4,d5}, d14 + vtbx.8 d23, {d3,d4,d5}, d15 + + /* load the next set of input data */ + vld1.u8 {d0,d1}, [pSrcTmp], srcStride + vld1.u8 {d3,d4}, [pSrcTmp], srcStride + + /* create the average U/V's */ + vswp.8 d1, d3 /* prep the data */ + vhadd.u8 d2, d0, d1 + vhadd.u8 d5, d3, d4 + + /* index the data into the destination YUV422 buffer */ + vtbx.8 d24, {d0,d1,d2}, d16 + vtbx.8 d25, {d0,d1,d2}, d17 + vtbx.8 d26, {d0,d1,d2}, d18 + vtbx.8 d27, {d0,d1,d2}, d19 + /* index the second half of the output */ + vtbx.8 d20, {d3,d4,d5}, d16 + vtbx.8 d21, {d3,d4,d5}, d17 + vtbx.8 d22, {d3,d4,d5}, d18 + vtbx.8 d23, {d3,d4,d5}, d19 + + /* store the rotated data (and increment the destintation pointer) */ + vst1.8 {d27}, [pDstTmp], dstStride + vst1.8 {d26}, [pDstTmp], dstStride + vst1.8 {d25}, [pDstTmp], dstStride + vst1.8 {d24}, [pDstTmp], dstStride + vst1.8 {d23}, [pDstTmp], dstStride + vst1.8 {d22}, [pDstTmp], dstStride + vst1.8 {d21}, [pDstTmp], dstStride + vst1.8 {d20}, [pDstTmp], dstStride + + add pSrc, pSrc, #16 + add count, count, #1 + + subs pixelsLeft, pixelsLeft, #8 + bgt __uyvy_rotate_ccw90_width + + /* wrap the source pointer to the next line */ + mov tmp, width, lsl #1 + sub tmp, srcStride, tmp /* tmp = srcStride - (width << 1) */ + add pSrc, pSrc, tmp /* pSrc += tmp */ + add tmp, srcStride, srcStride + add tmp, tmp, srcStride + add pSrc, pSrc, tmp /* move the line 3 lines down */ + + subs linesLeft, linesLeft, #4 + bgt __uyvy_rotate_ccw90_height + + EPILOG r0, r12 +.unreq width +.unreq dstHeight +.unreq height +.unreq dstWidth +.unreq pSrc +.unreq pDst +.unreq srcStride +.unreq dstStride +.unreq pixelsLeft +.unreq linesLeft +.unreq tmp +.unreq pSrcTmp +.unreq pDstTmp +.unreq count + +.end diff --git a/libraries/public/yuv/__uyvy_rotate_cw90.S b/libraries/public/yuv/__uyvy_rotate_cw90.S new file mode 100644 index 0000000..946628d --- /dev/null +++ b/libraries/public/yuv/__uyvy_rotate_cw90.S @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __uyvy_rotate_cw90 + +.include "yuv.inc" + +/** + * These indexes allow the YUV422 CW90 rotate for Y values to work, use with VTBX + * TABLE (LSB) + * d[n+0] = Y0 Y2 Y4 Y6 Y8 YA YC YE = 00 02 04 06 08 0A 0C 0E + * d[n+1] = Y1 Y3 Y5 Y7 Y9 YB YD YF = 01 03 05 07 09 0B 0D 0F + * d[n+2] = Y0 Y2 Y4 Y6 Y8 YA YC YE = 10 12 14 16 18 1A 1C 1E + * d[n+3] = Y1 Y3 Y5 Y7 Y9 YB YD YF = 11 13 15 17 19 1B 1D 1F + * + * d[m+0] = XX 18 XX 10 XX 08 XX 00 + * d[m+1] = XX 19 XX 11 XX 09 XX 01 + * d[m+2] = XX 1A XX 12 XX 0A XX 02 + * d[m+3] = XX 1B XX 13 XX 0B XX 03 + * + * d[m+4] = XX 1C XX 14 XX 0C XX 04 + * d[m+5] = XX 1D XX 15 XX 0D XX 05 + * d[m+6] = XX 1E XX 16 XX 0E XX 06 + * d[m+7] = XX 1F XX 17 XX 0F XX 07 + */ +Y_CW90_INDEXES: +/* (MSB) */ + .long 0x00FF08FF + .long 0x10FF18FF + .long 0x01FF09FF + .long 0x11FF19FF + .long 0x02FF0AFF + .long 0x12FF1AFF + .long 0x03FF0BFF + .long 0x13FF1BFF + + .long 0x04FF0CFF + .long 0x14FF1CFF + .long 0x05FF0DFF + .long 0x15FF1DFF + .long 0x06FF0EFF + .long 0x16FF1EFF + .long 0x07FF0FFF + .long 0x17FF1FFF + +/** + * These indexes allow the YUV422 CW90 rotate for UV values to work, use with VTBX + * TABLE (LSB) + * d[n+0] = U0 U1 U2 U3 U4 U5 U6 U7 (averaged + * d[n+1] = U8 U9 UA UB UC UD UE UF + * d[n+2] = V0 V1 V2 V3 V4 V5 V6 V7 + * d[n+3] = V8 V9 VA VB VC VD VE VF + * + * d[m+0] = XX 18 XX 10 XX 08 XX 00 + * d[m+1] = XX 19 XX 11 XX 09 XX 01 + * d[m+2] = XX 1A XX 12 XX 0A XX 02 + * d[m+3] = XX 1B XX 13 XX 0B XX 03 + * + * d[m+4] = XX 1C XX 14 XX 0C XX 04 + * d[m+5] = XX 1D XX 15 XX 0D XX 05 + * d[m+6] = XX 1E XX 16 XX 0E XX 06 + * d[m+7] = XX 1F XX 17 XX 0F XX 07 + */ +UV_CW90_INDEXES: +/* (MSB) */ + .long 0x00FF08FF + .long 0x10FF18FF + .long 0x01FF09FF + .long 0x11FF19FF + .long 0x02FF0AFF + .long 0x12FF1AFF + .long 0x03FF0BFF + .long 0x13FF1BFF + + .long 0x04FF0CFF + .long 0x14FF1CFF + .long 0x05FF0DFF + .long 0x15FF1DFF + .long 0x06FF0EFF + .long 0x16FF1EFF + .long 0x07FF0FFF + .long 0x17FF1FFF + +/** + * These indexes allow the YUV422 CW90 rotate for UV values to work, use with VTBX + * TABLE (LSB) + * d[n+0] = XX Y0 XX Y1 XX Y2 XX Y3 + * d[n+1] = XX Y8 XX Y9 XX YA XX YB + * d[n+2] = U0 XX V0 XX U2 XX V2 XX + */ +XYXY_CW90_INDEXES: +/* (MSB) */ + .long 0xFFFFFFFF /* LSB MSB */ + .long 0x01120910 /* d[m+0] = [XX][XX][XX][XX][10][09][12][01] */ + .long 0xFFFFFFFF + .long 0x03120B10 /* d[m+1] = [XX][XX][XX][XX][10][0B][12][03] */ + .long 0xFFFFFFFF + .long 0x05160D14 /* d[m+2] = [XX][XX][XX][XX][14][0D][16][05] */ + .long 0xFFFFFFFF + .long 0x07160F14 /* d[m+3] = [XX][XX][XX][XX][14][0F][16][07] */ +/* (MSB) */ + .long 0x01120910 /* LSB MSB */ + .long 0xFFFFFFFF /* d[m+4] = [10][09][12][01][XX][XX][XX][XX] */ + .long 0x03120B10 + .long 0xFFFFFFFF /* d[m+5] = [10][0B][12][03][XX][XX][XX][XX] */ + .long 0x05160D14 + .long 0xFFFFFFFF /* d[m+6] = [14][0D][16][05][XX][XX][XX][XX] */ + .long 0x07160F14 + .long 0xFFFFFFFF /* d[m+7] = [14][0F][16][07][XX][XX][XX][XX] */ + +/** + * This subroutine rotates YUV422I data in 4x8 pixel blocks. + */ +__uyvy_rotate_cw90: +width .req r0 +dstHeight .req r0 +height .req r1 +dstWidth .req r1 +pSrc .req r2 +pDst .req r3 +srcStride .req r4 +dstStride .req r5 +pixelsLeft .req r6 +linesLeft .req r7 +tmp .req r8 +pSrcTmp .req r9 +pDstTmp .req r10 +count .req r11 + PROLOG r0, r12 + ldr srcStride, [sp, #(14 * 4)] + ldr dstStride, [sp, #(15 * 4)] + mov pixelsLeft, width + mov linesLeft, height + mov count, #0 + + ldr tmp, =XYXY_CW90_INDEXES + vld1.u8 {d12}, [tmp]! + vld1.u8 {d13}, [tmp]! + vld1.u8 {d14}, [tmp]! + vld1.u8 {d15}, [tmp]! + vld1.u8 {d16}, [tmp]! + vld1.u8 {d17}, [tmp]! + vld1.u8 {d18}, [tmp]! + vld1.u8 {d19}, [tmp]! + + +__uyvy_rotate_cw90_height: + + /* move the Destination pointer to it's location */ + mov tmp, linesLeft, lsl #1 + sub tmp, tmp, #8 + add pDstTmp, pDst, tmp + + /* reset the number of pixels left on each line */ + mov pixelsLeft, width + +__uyvy_rotate_cw90_width: + + mov pSrcTmp, pSrc + + /* preload the data */ + pld [pSrcTmp] + pld [pSrcTmp, srcStride] + + /* load the line */ + vld1.u8 {d0,d1}, [pSrcTmp], srcStride + vld1.u8 {d3,d4}, [pSrcTmp], srcStride + + /* preload the next 2 lines */ + pld [pSrcTmp] + pld [pSrcTmp, srcStride] + + /* create the average U/V's */ + vswp.8 d1, d3 /* prep the data */ + vhadd.u8 d2, d0, d1 + vhadd.u8 d5, d3, d4 + + /* index the data into the destination YUV422 buffer */ + vtbx.8 d20, {d0,d1,d2}, d12 + vtbx.8 d21, {d0,d1,d2}, d13 + vtbx.8 d22, {d0,d1,d2}, d14 + vtbx.8 d23, {d0,d1,d2}, d15 + /* index the second half of the output */ + vtbx.8 d24, {d3,d4,d5}, d12 + vtbx.8 d25, {d3,d4,d5}, d13 + vtbx.8 d26, {d3,d4,d5}, d14 + vtbx.8 d27, {d3,d4,d5}, d15 + + /* load the next set of input data */ + vld1.u8 {d0,d1}, [pSrcTmp], srcStride + vld1.u8 {d3,d4}, [pSrcTmp], srcStride + + /* create the average U/V's */ + vswp.8 d1, d3 /* prep the data */ + vhadd.u8 d2, d0, d1 + vhadd.u8 d5, d3, d4 + + /* index the data into the destination YUV422 buffer */ + vtbx.8 d20, {d0,d1,d2}, d16 + vtbx.8 d21, {d0,d1,d2}, d17 + vtbx.8 d22, {d0,d1,d2}, d18 + vtbx.8 d23, {d0,d1,d2}, d19 + /* index the second half of the output */ + vtbx.8 d24, {d3,d4,d5}, d16 + vtbx.8 d25, {d3,d4,d5}, d17 + vtbx.8 d26, {d3,d4,d5}, d18 + vtbx.8 d27, {d3,d4,d5}, d19 + + /* store the rotated data (and increment the destintation pointer) */ + vst1.8 {d20}, [pDstTmp], dstStride + vst1.8 {d21}, [pDstTmp], dstStride + vst1.8 {d22}, [pDstTmp], dstStride + vst1.8 {d23}, [pDstTmp], dstStride + vst1.8 {d24}, [pDstTmp], dstStride + vst1.8 {d25}, [pDstTmp], dstStride + vst1.8 {d26}, [pDstTmp], dstStride + vst1.8 {d27}, [pDstTmp], dstStride + + add pSrc, pSrc, #16 + add count, count, #1 + + subs pixelsLeft, pixelsLeft, #8 + bgt __uyvy_rotate_cw90_width + + /* wrap the source pointer to the next line */ + mov tmp, width, lsl #1 + sub tmp, srcStride, tmp /* tmp = srcStride - (width << 1) */ + add pSrc, pSrc, tmp /* pSrc += tmp */ + add tmp, srcStride, srcStride + add tmp, tmp, srcStride + add pSrc, pSrc, tmp /* move the line 3 lines down */ + + subs linesLeft, linesLeft, #4 + bgt __uyvy_rotate_cw90_height + + EPILOG r0, r12 + +.unreq width +.unreq dstHeight +.unreq height +.unreq dstWidth +.unreq pSrc +.unreq pDst +.unreq srcStride +.unreq dstStride +.unreq pixelsLeft +.unreq linesLeft +.unreq tmp +.unreq pSrcTmp +.unreq pDstTmp +.unreq count + +.end diff --git a/libraries/public/yuv/__uyvy_to_bgr_image_bt601.S b/libraries/public/yuv/__uyvy_to_bgr_image_bt601.S new file mode 100644 index 0000000..430cf5d --- /dev/null +++ b/libraries/public/yuv/__uyvy_to_bgr_image_bt601.S @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __uyvy_to_bgr_image_bt601 + +.include "yuv.inc" + +__uyvy_to_bgr_image_bt601: +width .req r0 +height .req r1 +pSrc .req r2 +srcStride .req r3 +srcStep .req r3 +pDst .req r4 +dstStride .req r5 +dstStep .req r5 +pixelsLeft .req r6 +linesLeft .req r7 +tmp .req r8 + + PROLOG r0, r12 + + ldr pDst, [sp,#(14 * 4)] + ldr dstStride, [sp,#(15 * 4)] + mov linesLeft, height + + add tmp, width, width /* tmp = 2 * width */ + sub srcStep, srcStride, tmp /* srcStep = srcStride - tmp */ + add tmp, tmp, width /* tmp = 3 * width */ + sub dstStep, dstStride, tmp /* dstStep = dstStride - tmp */ + + FILL_YCBCR_TO_RGB_BT601 q15,q14,q13,q12,q11,d21,d20 + +__uyvy_to_bgr_image_bt601_line: + mov pixelsLeft, width +__uyvy_to_bgr_image_bt601_pixel: + + preload_L2_1x256bytes pSrc + + vld4.8 {d0,d1,d2,d3},[pSrc]! + /* d0 = {u0,u1,u2,u3,u4,u5,u6,u7] */ + /* d1 = {y0,y2,y4,y6,y8,yA,yC,yE] */ + /* d2 = [v0,v1,v2,v3,v4,v5,v6,v7] */ + /* d3 = [y1,y3,y5,y7,y9,yB,yD,yF] */ + + vsubl.u8 q2, d1, d20 /* q2 = Ye - 16 */ + vsubl.u8 q3, d3, d20 /* q3 = Yo - 16 */ + vsubl.u8 q0, d0, d21 /* q0 = Cb - 128 */ + vsubl.u8 q1, d2, d21 /* q1 = Cr - 128 */ + + vmul.s16 q4, q2, q15 /* Re = 74*Ye */ + vmla.s16 q4, q1, q12 /* Re += 102*Cr */ + vmul.s16 q5, q3, q15 /* Ro = 74*Yo */ + vmla.s16 q5, q1, q12 /* Ro += 102*Cr */ + vmul.s16 q6, q2, q15 /* Ge = 74*Ye */ + vmls.s16 q6, q1, q13 /* Ge -= 52*Cr */ + vmls.s16 q6, q0, q14 /* Ge -= 25*Cb */ + vmul.s16 q7, q3, q15 /* Go = 74*Yo */ + vmls.s16 q7, q1, q13 /* Go -= 52*Cr */ + vmls.s16 q7, q0, q14 /* Go -= 25*Cb */ + vmul.s16 q8, q2, q15 /* Be = 74*Ye */ + vmla.s16 q8, q0, q11 /* Be += 129*Cb */ + vmul.s16 q9, q3, q15 /* Bo = 74*Yo */ + vmla.s16 q9, q0, q11 /* Bo += 129*Cb */ + + vqshrun.s16 d0, q8, #6 /* Be >> 6 */ + vqshrun.s16 d3, q9, #6 /* Bo >> 6 */ + vqshrun.s16 d1, q6, #6 /* Ge >> 6 */ + vqshrun.s16 d4, q7, #6 /* Go >> 6 */ + vqshrun.s16 d2, q4, #6 /* Re >> 6 */ + vqshrun.s16 d5, q5, #6 /* Ro >> 6 */ + + vzip.8 d0, d3 /* Be:Bo to Bl:Bh */ + vzip.8 d1, d4 /* Ge:Go to Gl:Gh */ + vzip.8 d2, d5 /* Re:Ro to Rl:Rh */ + + vst3.8 {d0,d1,d2},[pDst]! + vst3.8 {d3,d4,d5},[pDst]! + + subs pixelsLeft, pixelsLeft, #16 + bgt __uyvy_to_bgr_image_bt601_pixel + + add pSrc, pSrc, srcStep + add pDst, pDst, dstStep + + subs linesLeft, linesLeft, #1 + bgt __uyvy_to_bgr_image_bt601_line + + EPILOG r0, r12 +.unreq width +.unreq height +.unreq pSrc +.unreq srcStride +.unreq srcStep +.unreq pDst +.unreq dstStride +.unreq dstStep +.unreq pixelsLeft +.unreq linesLeft +.unreq tmp + +.end diff --git a/libraries/public/yuv/__uyvy_to_rgb565_image_bt601.S b/libraries/public/yuv/__uyvy_to_rgb565_image_bt601.S new file mode 100644 index 0000000..bd5a9b7 --- /dev/null +++ b/libraries/public/yuv/__uyvy_to_rgb565_image_bt601.S @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __uyvy_to_rgb565_image_bt601 + +.include "yuv.inc" + +/** This function converts a UYVY image to a RGB565 image with the BT601 constants. */ +__uyvy_to_rgb565_image_bt601: +width .req r0 +height .req r1 +pSrc .req r2 +srcStride .req r3 +srcStep .req r3 +pDst .req r4 +dstStride .req r5 +dstStep .req r5 +pixelsLeft .req r6 +linesLeft .req r7 +tmp .req r8 + + PROLOG r0, r12 + + ldr pDst, [sp,#(14 * 4)] + ldr dstStride, [sp,#(15 * 4)] + mov linesLeft, height + + add tmp, width, width /* tmp = 2 * width */ + sub srcStep, srcStride, tmp /* srcStep = srcStride - tmp */ + sub dstStep, dstStride, tmp /* dstStep = dstStride - tmp */ + + FILL_YCBCR_TO_RGB_BT601 q15,q14,q13,q12,q11,d21,d20 +__uyvy_to_rgb565_image_bt601_line: + mov pixelsLeft, width +__uyvy_to_rgb565_image_bt601_pixel: + +/* + Remember: + r = 1.164*(y0 - 16) + 1.596(v0 - 128) + g = 1.164*(y0 - 16) - 0.813(v0 - 128) - 0.391(u0 - 128) + b = 1.164*(y0 - 16) + 2.018(u0 - 128) +*/ + preload_L2_1x256bytes pSrc + + vld4.8 {d0,d1,d2,d3},[pSrc]! + /* d0 = {u0,u1,u2,u3,u4,u5,u6,u7] */ + /* d1 = {y0,y2,y4,y6,y8,yA,yC,yE] */ + /* d2 = [v0,v1,v2,v3,v4,v5,v6,v7] */ + /* d3 = [y1,y3,y5,y7,y9,yB,yD,yF] */ + + vsubl.u8 q2, d1, d20 /* q2 = Ye - 16 */ + vsubl.u8 q3, d3, d20 /* q3 = Yo - 16 */ + vsubl.u8 q0, d0, d21 /* q0 = Cb - 128 */ + vsubl.u8 q1, d2, d21 /* q1 = Cr - 128 */ + + vmul.s16 q4, q2, q15 /* Re = 74*Ye */ + vmla.s16 q4, q1, q12 /* Re += 102*Cr */ + vmul.s16 q5, q3, q15 /* Ro = 74*Yo */ + vmla.s16 q5, q1, q12 /* Ro += 102*Cr */ + vmul.s16 q6, q2, q15 /* Ge = 74*Ye */ + vmls.s16 q6, q1, q13 /* Ge -= 52*Cr */ + vmls.s16 q6, q0, q14 /* Ge -= 25*Cb */ + vmul.s16 q7, q3, q15 /* Go = 74*Yo */ + vmls.s16 q7, q1, q13 /* Go -= 52*Cr */ + vmls.s16 q7, q0, q14 /* Go -= 25*Cb */ + vmul.s16 q8, q2, q15 /* Be = 74*Ye */ + vmla.s16 q8, q0, q11 /* Be += 129*Cb */ + vmul.s16 q9, q3, q15 /* Bo = 74*Yo */ + vmla.s16 q9, q0, q11 /* Bo += 129*Cb */ + + /* Create RGB888 */ + vqshrun.s16 d0, q8, #6 /* Be >> 6 */ + vqshrun.s16 d3, q9, #6 /* Bo >> 6 */ + vqshrun.s16 d1, q6, #6 /* Ge >> 6 */ + vqshrun.s16 d4, q7, #6 /* Go >> 6 */ + vqshrun.s16 d2, q4, #6 /* Re >> 6 */ + vqshrun.s16 d5, q5, #6 /* Ro >> 6 */ + + vzip.8 d0, d3 /* Be:Bo to Bl:Bh */ + vzip.8 d1, d4 /* Ge:Go to Gl:Gh */ + vzip.8 d2, d5 /* Re:Ro to Rl:Rh */ + + RGB888_TO_RGB565 d0, d1, d2, q8, q6, q4, q3 + RGB888_TO_RGB565 d3, d4, d5, q9, q7, q5, q4 + + vst1.16 {d6}, [pDst]! + vst1.16 {d7}, [pDst]! + vst1.16 {d8}, [pDst]! + vst1.16 {d9}, [pDst]! + + subs pixelsLeft, pixelsLeft, #16 + bgt __uyvy_to_rgb565_image_bt601_pixel + + add pSrc, pSrc, srcStep + add pDst, pDst, dstStep + + subs linesLeft, linesLeft, #1 + bgt __uyvy_to_rgb565_image_bt601_line + + EPILOG r0, r12 +.unreq width +.unreq height +.unreq pSrc +.unreq srcStride +.unreq srcStep +.unreq pDst +.unreq dstStride +.unreq dstStep +.unreq pixelsLeft +.unreq linesLeft +.unreq tmp + +.end diff --git a/libraries/public/yuv/__uyvy_to_rgbp_image_bt601.S b/libraries/public/yuv/__uyvy_to_rgbp_image_bt601.S new file mode 100644 index 0000000..465e6f1 --- /dev/null +++ b/libraries/public/yuv/__uyvy_to_rgbp_image_bt601.S @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __uyvy_to_rgbp_image_bt601 + +.include "yuv.inc" + +__uyvy_to_rgbp_image_bt601: +width .req r0 +height .req r1 +pSrc .req r2 +srcStride .req r3 +srcStep .req r3 +pR .req r4 +pG .req r5 +pB .req r6 +dstStride .req r7 +dstStep .req r7 +linesLeft .req r8 +pixelsLeft .req r9 +tmp .req r10 + PROLOG r0, r12 + ldr pR, [sp, #(14 * 4)] + ldr pG, [sp, #(15 * 4)] + ldr pB, [sp, #(16 * 4)] + ldr dstStride, [sp, #(17 * 4)] + add tmp, width, width /* tmp = 2 * width */ + sub srcStep, srcStride, tmp /* srcStep = srcStride - tmp */ + sub dstStep, dstStride, width + mov linesLeft, height + + FILL_YCBCR_TO_RGB_BT601 q15,q14,q13,q12,q11,d21,d20 + +__uyvy_to_rgbp_image_bt601_line: + mov pixelsLeft, width +__uyvy_to_rgbp_image_bt601_pixel: + + preload_L2_1x256bytes pSrc + + vld4.8 {d0,d1,d2,d3},[pSrc]! + /* d0 = {u0,u1,u2,u3,u4,u5,u6,u7] = Cb */ + /* d1 = {y0,y2,y4,y6,y8,yA,yC,yE] = Ye */ + /* d2 = [v0,v1,v2,v3,v4,v5,v6,v7] = Cr */ + /* d3 = [y1,y3,y5,y7,y9,yB,yD,yF] = Yo */ + + vsubl.u8 q2, d1, d20 /* q2 = Ye - 16 */ + vsubl.u8 q3, d3, d20 /* q3 = Yo - 16 */ + vsubl.u8 q0, d0, d21 /* q0 = Cb - 128 */ + vsubl.u8 q1, d2, d21 /* q1 = Cr - 128 */ + + vmul.s16 q4, q2, q15 /* Re = 74*Ye */ + vmla.s16 q4, q1, q12 /* Re += 102*Cr */ + vmul.s16 q5, q3, q15 /* Ro = 74*Yo */ + vmla.s16 q5, q1, q12 /* Ro += 102*Cr */ + vmul.s16 q6, q2, q15 /* Ge = 74*Ye */ + vmls.s16 q6, q1, q13 /* Ge -= 52*Cr */ + vmls.s16 q6, q0, q14 /* Ge -= 25*Cb */ + vmul.s16 q7, q3, q15 /* Go = 74*Yo */ + vmls.s16 q7, q1, q13 /* Go -= 52*Cr */ + vmls.s16 q7, q0, q14 /* Go -= 25*Cb */ + vmul.s16 q8, q2, q15 /* Be = 74*Ye */ + vmla.s16 q8, q0, q11 /* Be += 129*Cb */ + vmul.s16 q9, q3, q15 /* Bo = 74*Yo */ + vmla.s16 q9, q0, q11 /* Bo += 129*Cb */ + + vqshrun.s16 d0, q8, #6 /* Be >> 6 */ + vqshrun.s16 d3, q9, #6 /* Bo >> 6 */ + vqshrun.s16 d1, q6, #6 /* Ge >> 6 */ + vqshrun.s16 d4, q7, #6 /* Go >> 6 */ + vqshrun.s16 d2, q4, #6 /* Re >> 6 */ + vqshrun.s16 d5, q5, #6 /* Ro >> 6 */ + + vzip.8 d0, d3 /* Be:Bo to Bl:Bh */ + vzip.8 d1, d4 /* Ge:Go to Gl:Gh */ + vzip.8 d2, d5 /* Re:Ro to Rl:Rh */ + + vst1.8 {d0}, [pB]! + vst1.8 {d3}, [pB]! + vst1.8 {d1}, [pG]! + vst1.8 {d4}, [pG]! + vst1.8 {d2}, [pR]! + vst1.8 {d5}, [pR]! + + subs pixelsLeft, pixelsLeft, #16 + bgt __uyvy_to_rgbp_image_bt601_pixel + + add pSrc, pSrc, srcStep + add pR, pR, dstStep + add pG, pG, dstStep + add pB, pB, dstStep + + subs linesLeft, linesLeft, #1 + bgt __uyvy_to_rgbp_image_bt601_line + + EPILOG r0, r12 +.unreq tmp +.unreq pixelsLeft +.unreq linesLeft +.unreq dstStep +.unreq dstStride +.unreq pB +.unreq pG +.unreq pR +.unreq srcStep +.unreq srcStride +.unreq pSrc +.unreq height +.unreq width + +.end diff --git a/libraries/public/yuv/__uyvy_to_rgbp_luma_yuv444p_image.S b/libraries/public/yuv/__uyvy_to_rgbp_luma_yuv444p_image.S new file mode 100644 index 0000000..1b51fba --- /dev/null +++ b/libraries/public/yuv/__uyvy_to_rgbp_luma_yuv444p_image.S @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __uyvy_to_rgbp_luma_yuv444p_image + +.include "yuv.inc" + +__uyvy_to_rgbp_luma_yuv444p_image: +width .req r0 +height .req r1 +pUYVY .req r2 +srcStride .req r3 +srcStep .req r3 +pR .req r4 +pG .req r5 +pB .req r6 +pL .req r7 +pY .req r8 +pU .req r9 +pV .req r10 +tmp .req r11 +pixelsLeft .req r12 + PROLOG r0, r12 + ldr pR, [sp, #(14 * 4)] + ldr pG, [sp, #(15 * 4)] + ldr pB, [sp, #(16 * 4)] + ldr pL, [sp, #(17 * 4)] + ldr pY, [sp, #(18 * 4)] + ldr pU, [sp, #(19 * 4)] + ldr pV, [sp, #(20 * 4)] + add tmp, width, width + sub srcStep, srcStride, tmp + FILL_YCBCR_TO_RGB_BT601 q15,q14,q13,q12,q11,d21,d20 +__uyvy_to_rgbp_luma_yuv444p_image_lines: + mov pixelsLeft, width +__uyvy_to_rgbp_luma_yuv444p_image_pixels: + vld4.8 {d0, d1, d2, d3}, [pUYVY]! + + vst2.8 {d1,d3},[pL]! + vst2.8 {d1,d3},[pY]! + vmov d5,d0 + vmov d4,d0 + vst2.8 {d4,d5},[pU]! + vmov d4,d2 + vst2.8 {d2,d4},[pV]! + + vsubl.u8 q2, d1, d20 /* q2 = Ye - 16 */ + vsubl.u8 q3, d3, d20 /* q3 = Yo - 16 */ + vsubl.u8 q0, d0, d21 /* q0 = Cb - 128 */ + vsubl.u8 q1, d2, d21 /* q1 = Cr - 128 */ + + vmul.s16 q4, q2, q15 /* Re = 74*Ye */ + vmla.s16 q4, q1, q12 /* Re += 102*Cr */ + vmul.s16 q5, q3, q15 /* Ro = 74*Yo */ + vmla.s16 q5, q1, q12 /* Ro += 102*Cr */ + vmul.s16 q6, q2, q15 /* Ge = 74*Ye */ + vmls.s16 q6, q1, q13 /* Ge -= 52*Cr */ + vmls.s16 q6, q0, q14 /* Ge -= 25*Cb */ + vmul.s16 q7, q3, q15 /* Go = 74*Yo */ + vmls.s16 q7, q1, q13 /* Go -= 52*Cr */ + vmls.s16 q7, q0, q14 /* Go -= 25*Cb */ + vmul.s16 q8, q2, q15 /* Be = 74*Ye */ + vmla.s16 q8, q0, q11 /* Be += 129*Cb */ + vmul.s16 q9, q3, q15 /* Bo = 74*Yo */ + vmla.s16 q9, q0, q11 /* Bo += 129*Cb */ + + vqshrun.s16 d0, q8, #6 /* Be >> 6 */ + vqshrun.s16 d3, q9, #6 /* Bo >> 6 */ + vqshrun.s16 d1, q6, #6 /* Ge >> 6 */ + vqshrun.s16 d4, q7, #6 /* Go >> 6 */ + vqshrun.s16 d2, q4, #6 /* Re >> 6 */ + vqshrun.s16 d5, q5, #6 /* Ro >> 6 */ + + vzip.8 d0, d3 /* Be:Bo to Bl:Bh */ + vzip.8 d1, d4 /* Ge:Go to Gl:Gh */ + vzip.8 d2, d5 /* Re:Ro to Rl:Rh */ + + vst1.8 {d0},[pB]! + vst1.8 {d3},[pB]! + vst1.8 {d1},[pG]! + vst1.8 {d4},[pG]! + vst1.8 {d2},[pR]! + vst1.8 {d5},[pR]! + + subs pixelsLeft, pixelsLeft, #16 + bgt __uyvy_to_rgbp_luma_yuv444p_image_pixels + add pUYVY, pUYVY, srcStep + subs height, height, #1 + bgt __uyvy_to_rgbp_luma_yuv444p_image_lines + + EPILOG r0, r12 +.unreq width +.unreq height +.unreq pUYVY +.unreq srcStride +.unreq srcStep +.unreq pR +.unreq pG +.unreq pB +.unreq pL +.unreq pY +.unreq pU +.unreq pV +.unreq pixelsLeft + +.end diff --git a/libraries/public/yuv/__uyvy_to_yuv420_image.S b/libraries/public/yuv/__uyvy_to_yuv420_image.S new file mode 100644 index 0000000..05b34ef --- /dev/null +++ b/libraries/public/yuv/__uyvy_to_yuv420_image.S @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __uyvy_to_yuv420_image + +.include "yuv.inc" + +__uyvy_to_yuv420_image: +width .req r0 +height .req r1 +pSrc .req r2 +srcStride .req r3 +pY .req r4 +pU .req r5 +pV .req r6 +linesLeft .req r7 +pixelsLeft .req r8 +y_stride .req r9 +srcStep .req r10 +tmp .req r11 +uv_stride .req r12 + PROLOG r0, r12 + ldr pY, [sp, #(14 * 4)] + ldr pU, [sp, #(15 * 4)] + ldr pV, [sp, #(16 * 4)] + ldr y_stride, [sp, #(17 * 4)] + ldr uv_stride, [sp, #(18 * 4)] + add tmp, width, width + sub srcStep, srcStride, tmp + mov linesLeft, height +__uyvy_to_iyuv_image_loop_line: + mov pixelsLeft, width +__uyvy_to_iyuv_image_loop_pixel: + + preload_L2_1x256bytes pSrc + + /* read in 8 macro pixels */ + vld4.8 {d0,d1,d2,d3},[pSrc] + /* d0 = [u0,u1,u2,u3,u4,u5,u6,u7] */ + /* d1 = [y0,y2,y4,y6,y8,yA,yC,yE] */ + /* d2 = [v0,v1,v2,v3,v4,v5,v6,v7] */ + /* d3 = [y1,y3,y5,y7,y9,yB,yD,yF] */ + + preload_L2_1x256bytes tmp + + add tmp, pSrc, srcStride + vld4.8 {d4,d5,d6,d7},[tmp] + /* d4 = [u0,u1,u2,u3,u4,u5,u6,u7] */ + /* d5 = [y0,y2,y4,y6,y8,yA,yC,yE] */ + /* d6 = [v0,v1,v2,v3,v4,v5,v6,v7] */ + /* d7 = [y1,y3,y5,y7,y9,yB,yD,yF] */ + + /* store the Y pixels */ + vst2.8 {d1,d3},[pY] + add tmp, pY, y_stride + vst2.8 {d5,d7},[tmp] + + /* Create an average u and v pixels */ + vhadd.u8 d0, d0, d4 + vhadd.u8 d2, d2, d6 + + /* Store the U/V pixels (and update the pointers) */ + vst1.8 {d0},[pU]! + vst1.8 {d2},[pV]! + + /* Increment Pointers */ + add pSrc, pSrc, #32 + add pY, pY, #16 + + subs pixelsLeft, pixelsLeft, #16 + bgt __uyvy_to_iyuv_image_loop_pixel + + add pSrc, pSrc, srcStep + add pSrc, pSrc, srcStride /* (skip the next line) */ + sub tmp, y_stride, width + add pY, pY, tmp + add pY, pY, y_stride /* (skip the next line) */ + sub tmp, uv_stride, width, lsr #1 /* The UV plane is w/2 */ + add pU, pU, tmp + add pV, pV, tmp + + subs linesLeft, linesLeft, #2 + bgt __uyvy_to_iyuv_image_loop_line + + EPILOG r0, r12 +.unreq width +.unreq height +.unreq pSrc +.unreq srcStride +.unreq pY +.unreq pU +.unreq pV +.unreq y_stride +.unreq uv_stride +.unreq linesLeft +.unreq pixelsLeft +.unreq srcStep +.unreq tmp + +.end diff --git a/libraries/public/yuv/__uyvy_to_yuv444p_image.S b/libraries/public/yuv/__uyvy_to_yuv444p_image.S new file mode 100644 index 0000000..eef2d15 --- /dev/null +++ b/libraries/public/yuv/__uyvy_to_yuv444p_image.S @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.text +.arch armv7-a +.fpu neon + +.global __uyvy_to_yuv444p_image + +.include "yuv.inc" + +__uyvy_to_yuv444p_image: +width .req r0 +height .req r1 +linesLeft .req r1 +pYUV .req r2 +srcStride .req r3 +srcStep .req r3 +pY .req r4 +pU .req r5 +pV .req r6 +dstStride .req r7 +dstStep .req r7 +pixelsLeft .req r8 +tmp .req r9 + PROLOG r0, r12 + ldr pY, [sp, #(14 * 4)] + ldr pU, [sp, #(15 * 4)] + ldr pV, [sp, #(16 * 4)] + ldr dstStride, [sp, #(17 * 4)] + add tmp, width, width + sub dstStep, dstStride, width + sub srcStep, srcStride, tmp +__uyvy_to_yuv444p_image_lines: + mov pixelsLeft, width +__uyvy_to_yuv444p_image_pixels: + pld [pYUV, #L2_LINE_SIZE] + vld4.8 {d0,d1,d2,d3}, [pYUV]! + vst2.8 {d1,d3}, [pY]! + vmov d1, d0 + vst2.8 {d0,d1}, [pU]! + vmov d3, d2 + vst2.8 {d2,d3}, [pV]! + subs pixelsLeft, pixelsLeft, #16 + bgt __uyvy_to_yuv444p_image_pixels + add pYUV, pYUV, srcStep + add pY, pY, dstStep + add pU, pU, dstStep + add pV, pV, dstStep + subs linesLeft, linesLeft, #1 + bgt __uyvy_to_yuv444p_image_lines + EPILOG r0, r12 +.unreq width +.unreq height +.unreq pYUV +.unreq srcStride +.unreq srcStep +.unreq pY +.unreq pU +.unreq pV +.unreq dstStride +.unreq dstStep +.unreq linesLeft +.unreq pixelsLeft +.unreq tmp + +.end diff --git a/libraries/public/yuv/concerto.mak b/libraries/public/yuv/concerto.mak new file mode 100644 index 0000000..834a2f3 --- /dev/null +++ b/libraries/public/yuv/concerto.mak @@ -0,0 +1,53 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_CPU),ARM) + +ifneq ($(HOST_COMPILER),TMS470) + +include $(PRELUDE) + +VISION_LIBRARIES+=yuv +DVP_INC+=$(_MODPATH)/include +DVP_FEATURES+=DVP_USE_YUV + +ifdef DVP_LOCAL_BUILD +TARGET=yuv +TARGETTYPE=library +ASSEMBLY:=$(all-S-files) +CSOURCES:= +endif # LOCAL + +include $(FINALE) + +endif # COMPILER + +else # ARM + +include $(PRELUDE) + +# Don't expose this yet. +#VISION_LIBRARIES+=yuv +#DVP_INC+=$(_MODPATH)/include +#DVP_FEATURES+=DVP_USE_YUV + +ifdef DVP_LOCAL_BUILD +TARGET=yuv +TARGETTYPE=library +CSOURCES:=$(all-c-files) +endif # LOCAL + +include $(FINALE) + +endif # ARM diff --git a/libraries/public/yuv/include/yuv/dvp_kl_yuv.h b/libraries/public/yuv/include/yuv/dvp_kl_yuv.h new file mode 100644 index 0000000..ef7b198 --- /dev/null +++ b/libraries/public/yuv/include/yuv/dvp_kl_yuv.h @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! + * \file + * \brief This file decribes the exact set of kernels supported by the YUV + * algorithm library as exported through DVP. + * \note When using these enums, only the YUV kernels will be used! + */ + +#ifndef _DVP_KL_YUV_H_ +#define _DVP_KL_YUV_H_ + +#ifdef DVP_USE_YUV + +#include + +/*! The explicit list of kernels supported by the YUV algorithm library */ +enum { + DVP_KN_YUV_BASE = DVP_KN_LIBRARY_BASE(DVP_KL_YUV), + + /*! + * Converts FOURCC_UYVY format to FOURCC_IYUV or FOURCC_YV12 format. Chroma planes are downsampled vertically. (VLIB-API.Sec 55.0)\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_IYUV or FOURCC_YV12 + */ + DVP_KN_YUV_UYVY_TO_IYUV, + + /*! + * Converts FOURCC_UYVY format to 8 bits per pixels planar RGB using BT.601. (VLIB-API.Sec 58.0)\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_RGBP + */ + DVP_KN_YUV_UYVY_TO_RGBp, + + /*! + * Converts FOURCC_UYVY or FOURCC_VYUY to FOURCC_Y800 image\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY or FOURCC_VYUY + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_YUV_XYXY_TO_Y800, + + /*! + * Converts FOURCC_YVYU or FOURCC_YUY2 format to FOURCC_Y800 image.\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_YVYU or FOURCC_YUY2 + * \param [output] Image color type supported: FOURCC_Y800 + */ + DVP_KN_YUV_YXYX_TO_Y800, + + /*! + * Converts 1 plane 8 bit per pixel luma to FOURCC_UYVY\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_Y800 + * \param [output] Image color type supported: FOURCC_UYVY + */ + DVP_KN_YUV_Y800_TO_XYXY, + + /*! + * Converts FOURCC_UYVY format to 1 plane 8 bit pixel packed BGR byte ordered 24 bit per pixel format (FOURCC_BGR) using BT.601\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_BGR + */ + DVP_KN_YUV_UYVY_TO_BGR, + + /*! + * Converts FOURCC_UYVY format to 1 plane 565 bit pixel packed BGR ordered format (FOURCC_RGB565) using BT.601 \n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_RGB565 + */ + DVP_KN_YUV_IYUV_TO_RGB565, + + /*! + * Converts FOURCC_IYUV format to 1 plane 8 bit pixel packed BGR byte ordered 24 bit per pixel format (FOURCC_BGR) using BT.601\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_IYUV + * \param [output] Image color type supported: FOURCC_BGR + */ + DVP_KN_YUV_IYUV_TO_BGR, + + /*! + * Converts FOURCC_IYUV format to 1 plane 8 bits per pixels planar RGB using BT.601 format (FOURCC_BGR) using BT.601\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_IYUV + * \param [output] Image color type supported: FOURCC_RGBP + */ + DVP_KN_YUV_IYUV_TO_RGBp, + + /*! + * Converts 1 plane RGB 888 FOURCC_BGR to FOURCC_UYVY\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_RGB888 or FOURCC_BGR + * \param [output] Image color type supported: FOURCC_UYVY + */ + DVP_KN_YUV_BGR_TO_UYVY, + + /*! + * Converts 1 plane RGB 888 FOURCC_BGR to FOURCC_IYUV\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_RGB888 or FOURCC_BGR + * \param [output] Image color type supported: FOURCC_IYUV + */ + DVP_KN_YUV_BGR_TO_IYUV, + + /*! + * Horizontally mirrors the FOURCC_UYVY data\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_UYVY + */ + DVP_KN_YUV_UYVY_MIRROR, + + /*! + * Half-scale downsamples the FOURCC_UYVY data\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_UYVY + */ + DVP_KN_YUV_UYVY_HALF_SCALE, + + /*! + * Quarter-scale downsamples the FOURCC_UYVY data\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_UYVY + */ + DVP_KN_YUV_UYVY_QTR_SCALE, + + /*! + * Rotates any N plane (8 bit per plane) image by 90 Degrees Clockwise\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_IYUV + * \param [output] Image color type supported: FOURCC_IYUV + */ + DVP_KN_YUV_Y800_ROTATE_CW_90, + + /*! + * Rotates any N plane (8 bit per plane) image by 90 Degrees Counter-Clockwise\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_IYUV + * \param [output] Image color type supported: FOURCC_IYUV + */ + DVP_KN_YUV_Y800_ROTATE_CCW_90, + + /*! + * Rotates FOURCC_UYVY data by 90 Degrees Clockwise, resamples Chroma\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_UYVY + */ + DVP_KN_YUV_UYVY_ROTATE_CW_90, + + /*! + * Rotates FOURCC_UYVY data by 90 Degrees Counter-Clockwise, resamples Chroma\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_UYVY + */ + DVP_KN_YUV_UYVY_ROTATE_CCW_90, + + /*! + * Converts FOURCC_UYVY format to FOURCC_YU24 or FOURCC_YV24 format. Chroma planes are doubled.\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [output] Image color type supported: FOURCC_YV24 or FOURCC_YU24 + */ + DVP_KN_YUV_UYVY_TO_YU24, + + /*! + * Converts FOURCC_UYVY format to FOURCC_NV12 or FOURCC_YV24 format. Luma plane is halved in each direction.\n + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_NV12 + * \param [output] Image color type supported: FOURCC_YV24 or FOURCC_YU24 + */ + DVP_KN_YUV_NV12_TO_YU24_HALF_SCALE, + + /*! + * Converts FOURCC_UYVY format to FOURCC_RGBP, FOURCC_Y800, & FOURCC_YU24. \n + * Configuration Structure: DVP_YUV_TripleTransform_t + * \param [input] Image color type supported: FOURCC_UYVY + * \param [out1] Image color type supported: FOURCC_RGBP + * \param [out2] Image color type supported: FOURCC_Y800 + * \param [out3] Image color type supported: FOURCC_YV24 or FOURCC_YU24 + */ + DVP_KN_YUV_UYVY_TO_RGBp_Y800_YU24, + + /*! + * Converts FOURCC_ARGB format to FOURCC_UYVY\n. + * Configuration Structure: DVP_Transform_t + * \param [input] Image color type supported: FOURCC_ARGB + * \param [output] Image color type supported: FOURCC_UYVY + */ + DVP_KN_YUV_ARGB_TO_UYVY, +}; + +/*! \brief Use this struct with the YUV kernels which support one input and three outputs. + * \see DVP_KN_YUV_UYVY_TO_RGBp_Y800_YU24 + */ +typedef struct _dvp_yuv_triple_transform_t { + DVP_Image_t input; + DVP_Image_t out1; + DVP_Image_t out2; + DVP_Image_t out3; +} DVP_YUV_TripleTransform_t; + +#endif // DVP_USE_YUV + +#endif // _DVP_KL_YUV_H_ + diff --git a/libraries/public/yuv/include/yuv/yuv_armv7.h b/libraries/public/yuv/include/yuv/yuv_armv7.h new file mode 100644 index 0000000..5bdac50 --- /dev/null +++ b/libraries/public/yuv/include/yuv/yuv_armv7.h @@ -0,0 +1,481 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief The YUV NEON Library + * \author Erik Rainey + * \defgroup group_yuv Algos: YUV (NEON) + * \brief This only works on ARMv7 NEON enabled cores. + */ + +/*! +\page page_yuv YUV NEON Algorithm Library +This file implements YUV and RGB conversion and various other transforms using +the ARMv7 NEON SIMD instruction set. + +Here's the BT601 equation of for YCbCr (Computer) conversion to RGB (Computer). +Taken from "Video Demystified, Fourth Edition" by Keith Jack (p.18-19) + +Where R,G,B are [0,255] +Where Y is [16,235] +Where Cb,Cr is [0,255] + + \code + R = 1.164*(Y - 16) + 1.596(Cr - 128) + G = 1.164*(Y - 16) - 0.813(Cr - 128) - 0.391(Cb - 128) + B = 1.164*(Y - 16) + 2.018(Cb - 128) + \endcode + +This can be rewritten in a more integer (thus SIMD) friendly form as: + + \code + Y' = Y - 16 + Cb' = Cb - 128 + Cr' = Cr - 128 + + R = (74*Y' + 102*Cr') >> 6 + G = (74*Y' - 52*Cr' - 25*Cb') >> 6 + B = (74*Y' + 129*Cb') >> 6 + \endcode + +The inverse is: + + \code + Y = 0.257*R + 0.504*G + 0.098*B + 16 + Cb = -0.148*R - 0.291*G + 0.439*B + 128 + Cr = 0.439*R - 0.368*G - 0.071*B + 128 + \endcode + +Where R,G,B is [0,255] + +This is also rewritable in an integer format as: + + \code + Y = ( 16*R + 32*G + 6*B )>>6 + 16 + Cb = ( -9*R - 19*G + 28*B )>>6 + 128 + Cr = ( 28*R - 24*G + 5*B )>>6 + 128 + \endcode + +Converting to integer has a disadvantage that there is a necessary loss of +precision but it has the upside of a significant gain in performance. + +*/ + +#ifndef _YUV_ARMV7_H_ +#define _YUV_ARMV7_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief Converts a UYVY formatted image to a YUV420 formatted image. + * \param [in] width The width in pixels + * \param [in] height The height in pixels + * \param [in] pUYVY The UYVY image pointer. + * \param [in] srcStride The stride in bytes of the UYVY image. + * \param [out] pY The pointer to the LUMA plane. + * \param [out] pU The pointer to the U/Cb plane + * \param [out] pV The pointer to the V/Cr plane + * \param [in] y_stride The stride in bytes of the LUMA plane + * \param [in] uv_stride The stride in bytes of the U/V planes. + * \ingroup group_yuv + */ +void __uyvy_to_yuv420_image(uint32_t width, + uint32_t height, + uint8_t *pUYVY, + int32_t srcStride, + uint8_t *pY, + uint8_t *pU, + uint8_t *pV, + int32_t y_stride, + int32_t uv_stride); + + +/*! \brief This function extracts LUMA (Y) data from a UYVY image. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pYUV The UYVY data pointer. + * \param [in] srcStride The stride in bytes of the pYUV image. + * \param [out] pY The LUMA data pointer. + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __uyvy_luma_extract(uint32_t width, + uint32_t height, + uint8_t *pYUV, + int32_t srcStride, + uint8_t *pY, + int32_t dstStride); + +/*! \brief Converts luma data back to UYVY format data. Inserts "zero" (not + * actually zero) data into U/V channels. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pY The pointer to the LUMA image. + * \param [in] srcStride The stride in bytes of the source image. + * \param [out] pUYVY The poitner to the UYVY image. + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __luma_to_uyvy_image(uint32_t width, + uint32_t height, + uint8_t *pY, + int32_t srcStride, + uint8_t *pUYVY, + int32_t dstStride); + +/*! \brief This function converts a UYVY image to a RGBp image via the BT601 constants. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pSrc The pointer to the source image. + * \param [in] srcStride The stride in bytes of the source image. + * \param [out] pR The pointer to the red plane. + * \param [out] pG The poitner to the green plane. + * \param [out] pB The poitner to the blue plane. + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __uyvy_to_rgbp_image_bt601(uint32_t width, + uint32_t height, + uint8_t *pSrc, + int32_t srcStride, + uint8_t *pR, + uint8_t *pG, + uint8_t *pB, + int32_t dstStride); + +/*! \brief This function converts a UYVY image to a BGR (24 bit) image via the BT601 constants. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pSrc The pointer to the source image. + * \param [in] srcStride The stride in bytes of the source image. + * \param [out] pDst The pointer to the destintation image. + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __uyvy_to_bgr_image_bt601(uint32_t width, + uint32_t height, + uint8_t *pSrc, + int32_t srcStride, + uint8_t *pDst, + int32_t dstStride); + +/*! \brief + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pY The pointer the luma plane. + * \param [in] pU The pointer to the Cb/U plane. + * \param [in] pV The pointer to the Cr/V plane. + * \param [out] pDst The pointer to the destintation image + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __iyuv_to_rgb565_image_bt601(uint32_t width, + uint32_t height, + uint8_t *pY, + uint8_t *pU, + uint8_t *pV, + uint32_t *pDst, + int32_t dstStride); + +/*! \brief + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pY The pointer to the Luma plane. + * \param [in] pU The pointer to the U/Cb plane. + * \param [in] pV The pointer to the V/Cr plane. + * \param [out] pDst The pointer the destination image. + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __iyuv_to_bgr_image_bt601(uint32_t width, + uint32_t height, + uint8_t *pY, + uint8_t *pU, + uint8_t *pV, + uint8_t *pDst, + int32_t dstStride); + +/*! \brief Converts IYUV byte ordered data to RGBp over an image. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pY The pointer to the Luma plane. + * \param [in] pU The pointer to the U/Cb plane. + * \param [in] pV The pointer to the V/Cr plane. + * \param [in] srcStride The stride in bytes of the source image. + * \param [out] pR The pointer to the red plane. + * \param [out] pG The pointer to the green plane. + * \param [out] pB The pointer to the blue plane. + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __iyuv_to_rgbp_image_bt601(uint32_t width, + uint32_t height, + uint8_t *pY, + uint8_t *pU, + uint8_t *pV, + int32_t srcStride, + uint8_t *pR, + uint8_t *pG, + uint8_t *pB, + int32_t dstStride); + +/*! \brief Converts ARGB byte ordered data to UYVY over an image. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pSrc The pointer to the source image. + * \param [in] srcStride The stride in bytes of the source image. + * \param [out] pDst The pointer to the destination image. + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __argb_to_uyvy_image_bt601(uint32_t width, + uint32_t height, + uint8_t *pSrc, + int32_t srcStride, + uint8_t *pDst, + int32_t dstStride); + +/*! \brief Converts BGR byte ordered data to UYVY byte ordered data in an image. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pSrc The pointer to the source image. + * \param [in] srcStride The stride in bytes of the source image. + * \param [out] pDst The pointer to the destination image. + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __bgr_to_uyvy_image_bt601(uint32_t width, + uint32_t height, + uint8_t *pSrc, + int32_t srcStride, + uint8_t *pDst, + int32_t dstStride); + +/*! \brief Converts a BGR byte ordered data to IYUV formated image. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pSrc The pointer to the source image. + * \param [in] srcStride The stride in bytes of the source image. + * \param [out] pY The pointer to the Luma plane. + * \param [out] pU The pointer to the U/Cb plane. + * \param [out] pV The pointer to the V/Cr plane. + * \ingroup group_yuv + */ +void __bgr_to_iyuv_image_bt601(uint32_t width, + uint32_t height, + uint8_t *pSrc, + int32_t srcStride, + uint8_t *pY, + uint8_t *pU, + uint8_t *pV); + +/*! \brief Rotates a single plane of byte sized data clockwise 90 degrees. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pSrc The pointer to the source image. + * \param [out] pDst The pointer to the destination image. + * \ingroup group_yuv + */ +void __planar_rotate_cw90(uint32_t width, + uint32_t height, + uint8_t *pSrc, + uint8_t *pDst); + +/*! \brief Rotates a single plane of byte sized data counter-clockwise 90 degrees. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pSrc The pointer to the source image. + * \param [out] pDst The pointer to the destination image. + * \ingroup group_yuv + */ +void __planar_rotate_ccw90(uint32_t width, + uint32_t height, + uint8_t *pSrc, + uint8_t *pDst); + +/*! \brief A subroutine to scale down a UYVY image by 2. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pSrc The pointer to the source image. + * \param [in] srcStride The stride in bytes of the source image. + * \param [out] pDst The pointer to the destination image. + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __uyvy_half_scale_image(uint32_t width, + uint32_t height, + uint8_t *pSrc, + int32_t srcStride, + uint8_t *pDst, + int32_t dstStride); + +/*! \brief A subroutine to scale down a UYVY Image by 4. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pSrc The pointer to the source image. + * \param [in] srcStride The stride in bytes of the source image. + * \param [out] pDst The pointer to the destination image. + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __uyvy_qtr_scale_image(uint32_t width, + uint32_t height, + uint8_t *pSrc, + int32_t srcStride, + uint8_t *pDst, + int32_t dstStride); + +/*! \brief Horizontally mirrors a UYVY image (swaps Y channel only). + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pSrc The pointer to the source image. + * \param [in] srcStride The stride in bytes of the source image. + * \param [out] pDst The pointer to the destination image. + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __uyvy_horizontal_mirror_image(uint32_t width, + uint32_t height, + uint8_t *pSrc, + int32_t srcStride, + uint8_t *pDst, + int32_t dstStride); + +/*! \brief Rotates a UYVY formated image counter-clockwise 90 degrees. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pSrc The pointer to the source image. + * \param [out] pDst The pointer to the destination image. + * \param [in] srcStride The stride in bytes of the source image. + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __uyvy_rotate_ccw90(uint32_t width, + uint32_t height, + uint8_t *pSrc, + uint8_t *pDst, + int32_t srcStride, + int32_t dstStride); + +/*! \brief Rotates a UYVY formated image clockwise 90 degrees. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pSrc The pointer to the source image. + * \param [out] pDst The pointer to the destination image. + * \param [in] srcStride The stride in bytes of the source image. + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __uyvy_rotate_cw90(uint32_t width, + uint32_t height, + uint8_t *pSrc, + uint8_t *pDst, + int32_t srcStride, + int32_t dstStride); + +/*! \brief Converts a UYVY formated image to a YUV444 planar image. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pSrc The pointer to the source image. + * \param [in] srcStride The stride in bytes of the source image. + * \param [out] pY The pointer to the Luma plane. + * \param [out] pU The pointer to the U/Cb plane. + * \param [out] pV The pointer to the V/Cr plane. + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __uyvy_to_yuv444p_image(uint32_t width, + uint32_t height, + uint8_t *pSrc, + int32_t srcStride, + uint8_t *pY, + uint8_t *pU, + uint8_t *pV, + int32_t dstStride); + +/*! \brief Converts an NV12 image to a half-scaled YUV444 planar image. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pY0 The pointer to the Luma plane. + * \param [in] pUV The pointer to the interleaved U/V (Cb/Cr) plane. + * \param [in] srcStride The stride in bytes of the source image. + * \param [out] pY1 The pointer to the half scaled Luma plane. + * \param [out] pU The pointer to the U/Cb plane. + * \param [out] pV The pointer to the V/Cr plane. + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __nv12_to_half_yuv444_image(uint32_t width, + uint32_t height, + uint8_t *pY0, + uint8_t *pUV, + int32_t srcStride, + uint8_t *pY1, + uint8_t *pU, + uint8_t *pV, + int32_t dstStride); + +/*! \brief Converts a UYVY formatted image to 3 formats; RGBp, Luma, and YUV444p. + * \param [in] width The width in pixels. + * \param [in] height The height in pixels. + * \param [in] pUYVY The pointer to the source image. + * \param [in] srcStride The stride in bytes of the source image. + * \param [out] pR The pointer to the red plane. + * \param [out] pG The pointer to the green plane. + * \param [out] pB The pointer to the blue plane. + * \param [out] pL The pointer to the Luma plane. + * \param [out] pY The pointer to the YUV444 luma plane. + * \param [out] pU The pointer to the U/Cb plane. + * \param [out] pV The pointer to the V/Cr plane. + * \ingroup group_yuv + */ +void __uyvy_to_rgbp_luma_yuv444p_image(uint32_t width, + uint32_t height, + uint8_t *pUYVY, + uint32_t srcStride, + uint8_t *pR, + uint8_t *pG, + uint8_t *pB, + uint8_t *pL, + uint8_t *pY, + uint8_t *pU, + uint8_t *pV); + +/*! \brief Converts a pair of lines from YUV420 data to into YUV422. + * \param [in] pY The pointer to the Luma plane. + * \param [in] pU The pointer to the U/Cb plane. + * \param [in] pV The pointer to the V/Cr plane. + * \param [out] pDst The pointer to the UYVY plane. + * \param [in] width The width in pixels. + * \param [in] y_stride The stride in bytes of the source Luma plane. This will + * also apply to the pU/pV plane. + * \param [in] dstStride The stride in bytes of the destination image. + * \ingroup group_yuv + */ +void __yuv420_to_yuv422_line(uint8_t *pY, + uint8_t *pU, + uint8_t *pV, + uint8_t *pDst, + uint32_t width, + int32_t y_stride, + int32_t dstStride); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libraries/public/yuv/yuv.inc b/libraries/public/yuv/yuv.inc new file mode 100644 index 0000000..5f54733 --- /dev/null +++ b/libraries/public/yuv/yuv.inc @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \brief PROLOG is a macro which saves your context on the stack. To reference the + * next stack variable, add (sN-s0+2)*4, ie PROLOG r0,r12 will move the sp - (14*4) + */ +.macro PROLOG, s0, sN + stmfd sp!, {\s0-\sN, lr} +.endm + +/*! \brief EPILOG is a macro which restores your context on the stack. This will + * also modify the PC. + */ +.macro EPILOG, s0, sN + ldmfd sp!, {\s0-\sN, pc} +.endm + +/** + * This macro changes RGB888 pixels into RGB565 pixles in NEON + */ +.macro RGB888_TO_RGB565 db, dg, dr, qb, qg, qr, qp + vshr.u8 \db, \db, #3 + vshr.u8 \dg, \dg, #2 + vshr.u8 \dr, \dr, #3 + vmovl.u8 \qb, \db + vmovl.u8 \qg, \dg + vmovl.u8 \qr, \dr + vshl.u16 \qg, \qg, #5 + vshl.u16 \qr, \qr, #11 + vorr.u16 \qp, \qb, \qg + vorr.u16 \qp, \qp, \qr +.endm + +/* These are the 64x Constants for Y,Cb,Cr to R,G,B in BT601 Space. */ +.macro FILL_YCBCR_TO_RGB_BT601 yk, gk2, gk1, rk, bk, coff, yoff + vmov.i16 \yk, #74 /* 1.614 * 64 */ + vmov.i16 \gk2, #25 /* 0.391 * 64 */ + vmov.i16 \gk1, #52 /* 0.813 * 64 */ + vmov.i16 \rk, #102 /* 1.596 * 64 */ + vmov.i16 \bk, #129 /* 2.018 * 64 */ + vmov.u8 \coff, #128 /* 128 */ + vmov.u8 \yoff, #16 /* 16 */ +.endm + +/* These are the 64x constants for R,G,B to Y,Cb,Cr in BT601 Space. */ +.macro FILL_RGB_TO_YCBCR_BT601 r0, r1, r2, g0, g1, g2, b1, b2 + vmov.i16 \r0, #16 /* R Coef */ + vmov.i16 \r1, #32 + vmov.i16 \r2, #6 + vmov.i16 \g0, #9 /* (G Coef) */ + vmov.i16 \g1, #19 + vmov.i16 \g2, #28 /* (G & B Coef) */ + vmov.i16 \b1, #24 /* (B Coef) */ + vmov.i16 \b2, #5 +.endm + +/* This takes a dN register and duplicates the bottom bytes */ +/* d0 = [1,2,3,4,0,0,0,0] */ +/* d0 = [1,1,2,2,3,3,4,4] */ +.macro DUPLICATE_EACH_BYTE reg, tmp + vmov.i8 \tmp,\reg + vzip.i8 \reg,\tmp +.endm + +/*! \brief This loads 16 macropixels (32 total pixels) by 2 rows and creates a 16x1 average. + * \d0-\d7 row 1 + * \d8-\d15 row 2 + * The loads should be done in an interleaved order. + * ie: d0 = u0, d1 = y0, d2 = v0, d3 = y1 + * Stores must be done in 2.16 order over \d0, \d1 + * Stores must be done in 2.16 order over \d4, \d5 + */ +.macro uyvy_32x2_average d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15 + vhadd.u8 \d0, \d0, \d8 /* Average U's */ + vhadd.u8 \d1, \d1, \d9 /* Average Y0's */ + vhadd.u8 \d2, \d2, \d10 /* Average V's */ + vhadd.u8 \d3, \d3, \d11 /* Average Y1's */ + vhadd.u8 \d4, \d4, \d12 /* Average U's */ + vhadd.u8 \d5, \d5, \d13 /* Average Y0's */ + vhadd.u8 \d6, \d6, \d14 /* Average V's */ + vhadd.u8 \d7, \d7, \d15 /* Average Y1's */ + /* Now the two lines are averaged. */ + + /* Average the adjacent pixels. */ + vtrn.8 \d0, \d2 /* \d0 = [u0, v0, u2, v2, u4, v4, u6, v6] */ + /* \d2 = [u1, v1, u3, v3, u5, v5, u7, v7] */ + vhadd.u8 \d0, \d0, \d2 /* Average U/V's */ + vhadd.u8 \d1, \d1, \d3 /* Average Y's */ + vtrn.8 \d0, \d1 + + vtrn.8 \d4, \d6 /* same for other half */ + vhadd.u8 \d4, \d4, \d6 /* Average U/V's */ + vhadd.u8 \d5, \d5, \d7 /* Average Y's */ + vtrn.8 \d4, \d5 +.endm + +/*.equ L1_LINE_SIZE, 64*/ +/*.equ L2_LINE_SIZE, 64*/ + +.equ L1_LINE_SIZE, 32 +.equ L2_LINE_SIZE, 32 + +/* Preloads 256 bytes of contigous data addresses into the L2 cache */ +.macro preload_L2_1x256bytes address + pld [\address, #(L2_LINE_SIZE * 0)] + pld [\address, #(L2_LINE_SIZE * 1)] + pld [\address, #(L2_LINE_SIZE * 2)] + pld [\address, #(L2_LINE_SIZE * 3)] +.endm + + +/* Preloads 4 lines of 64 bytes of data into the L2 cache */ +.macro preload_L2_4x64bytes address, offset, tmp + pld [\address] + pld [\address, \offset] + mov \tmp, \offset, lsl #1 + pld [\address, \tmp] + add \tmp, \tmp, \offset + pld [\address, \tmp] +.endm + + +/* Preloads 4 lines of 64 bytes of data into the L2 cache, aligned to 64 bytes */ +/* @note address will be modified */ +.macro preload_L2_4x64bytes_aligned address, offset, tmp + mvn \tmp, #0x2F + and \address, \address, \tmp + pld [\address] + pld [\address, \offset] + mov \tmp, \offset, lsl #1 + pld [\address, \tmp] + add \tmp, \tmp, \offset + pld [\address, \tmp] +.endm + + +/* VREV64 Reverses all bytes in a 64 bit value (dN) */ +.macro REVERSE s0, s1 + vrev64.32 \s0, \s1 + vrev32.16 \s0, \s1 + vrev16.8 \s0, \s1 +.endm diff --git a/libraries/public/yuv/yuv_c.h b/libraries/public/yuv/yuv_c.h new file mode 100644 index 0000000..f00bbe9 --- /dev/null +++ b/libraries/public/yuv/yuv_c.h @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _YUV_C_H_ +#define _YUV_C_H_ + +/*! \file + * \brief Defines the "C" model macros and defintions for YUV. + * \author Erik Rainey + */ + +#include + +#define SIZEOF_PIXEL_YUV420 (1) // this is for each individual plane +#define SIZEOF_IMAGE_YUV420(w,h) (((w)*(h)*3)/2) + +typedef union _yuv4444 { + struct { + uint8_t V; + uint8_t U; + uint8_t Y; + uint8_t A; + } VUYA; // FOURCC_VUYA + struct { + uint8_t A; + uint8_t Y; + uint8_t U; + uint8_t V; + } AYUV; // FOURCC_AYUV + uint32_t packed; +} YUV4444; + +#define SIZEOF_PIXEL_YUV4444 (4) +#define SIZEOF_IMAGE_YUV4444(w,h) ((w)*(h)*SIZEOF_PIXEL_YUV4444) + +typedef union _yuv422 { + struct { + uint8_t U0; + uint8_t Y0; + uint8_t V0; + uint8_t Y1; + } UYVY; // and Y422, UYNV and HDYC + struct { + uint8_t V0; + uint8_t Y0; + uint8_t U0; + uint8_t Y1; + } VYUY; + struct { + uint8_t Y0; + uint8_t U0; + uint8_t Y1; + uint8_t V0; + } YUYV; // and YUNV, V422, YUY2 + struct { + uint8_t Y0; + uint8_t V0; + uint8_t Y1; + uint8_t U0; + } YVYU; + uint32_t packed; +} YUV422; + +#define SIZEOF_PIXEL_YUV422 (2) // since this is a macropixel format, we just want the pixel itself. +#define SIZEOF_IMAGE_YUV422(w,h) ((w)*(h)*SIZEOF_PIXEL_YUV422) + +/** + * This structure defines the variations in LSB to MSB order. + * BGRA is B as LSB and A as MSB (which is considered ARGB by most). + */ +typedef union _rgb8888 { + struct { + uint8_t B; + uint8_t G; + uint8_t R; + uint8_t A; + } BGRA; // FOURCC_RGBA + struct { + uint8_t A; + uint8_t R; + uint8_t G; + uint8_t B; + } ARGB; // FOURCC_BGRA + struct { + uint8_t A; + uint8_t B; + uint8_t G; + uint8_t R; + } ABGR; // FOURCC_ABGR + struct { + uint8_t R; + uint8_t G; + uint8_t B; + uint8_t A; + } RGBA; // FOURCC_ABGR + uint32_t packed; +} RGB8888; + +#define SIZEOF_PIXEL_RGB8888 (4) +#define SIZEOF_IMAGE_RGB8888(w,h) ((w)*(h)*sizeof(RGB8888)) + +/*! \brief This is the RGB888 (24bit) structure. + * \note This should be a sizeof(x) == 3 (due to "packed") union member + */ +typedef union _rgb888 { + struct { + uint8_t B; + uint8_t G; + uint8_t R; + } BGR; + struct { + uint8_t R; + uint8_t G; + uint8_t B; + } RGB; + uint8_t packed[3]; +} RGB888; + +#define CAST_uint32_t_TO_RGB888(x,rgb) {rgb.packed[0] = (x & 0x000000FF) >> 0;\ + rgb.packed[1] = (x & 0x0000FF00) >> 8;\ + rgb.packed[2] = (x & 0x00FF0000) >> 16;} +#define SIZEOF_PIXEL_RGB888 (3) +#define SIZEOF_IMAGE_RGB888(w,h) ((w)*(h)*sizeof(RGB888)) + +/*! \brief This is the RGB565 (16 bit) structure.s + * \note Check with your compiler to see if this actually becomes a sizeof 2 + */ +typedef union _rgb565 { +#ifdef COMPILER_SUPPORTS_BITFIELDS + struct { + uint8_t B : 5; + uint8_t G : 6; + uint8_t R : 5; + } BGR; + struct { + uint8_t R : 5; + uint8_t G : 6; + uint8_t B : 5; + } RGB; +#endif + uint16_t packed; // use the macros with this field +} RGB565; + +#define SIZEOF_PIXEL_RGB565 (2) +#define SIZEOF_IMAGE_RGB565(w,h) ((w)*(h)*sizeof(RGB565)) + + +// If you use the "packed" variable above to get values out, use these macros +#define RGB565_GET_R(pixel) ((pixel & 0xF800) >> 11) +#define RGB565_GET_G(pixel) ((pixel & 0x07E0) >> 5) +#define RGB565_GET_B(pixel) ((pixel & 0x001F) >> 0) + +#define RGB565_SET_R(r) ((((r) >> 3) & 0x1F) << 11) +#define RGB565_SET_G(g) ((((g) >> 2) & 0x3F) << 5) +#define RGB565_SET_B(b) ((((b) >> 3) & 0x1F) << 0) + +/*! \brief The packed pair of RGB565 pixels.s + * \note This should be sizeof(x) == 4 + */ +typedef union _rgb565pair { + struct { + RGB565 lower; + RGB565 upper; + } halves; + uint32_t packed; +} RGB565_PAIR; + +/*! \brief Converts a YUV pixel to RGB using the BT601 variables in 14 bit precision. + */ +#define CONVERT_YUV_TO_RGB_BT601_Q14(y,u,v,r,g,b) { \ + y -= 16;\ + u -= 128;\ + v -= 128;\ + r = ((19070 * y) >> 14) + ((26148 * v) >> 14); \ + g = ((19070 * y) >> 14) - ((13320 * v) >> 14) - ((6406 * u) >> 14); \ + b = ((19070 * y) >> 14) + ((33062 * u) >> 14); \ +} + +/*! \brief Converts a RGB pixel to YUV using the BT601 variables in 14 bit precision. + */ +#define CONVERT_RGB_TO_YUV_BT601_Q14(r,g,b,y,u,v) { \ + y = (((3489 * r) >> 14) + ((8257 * g) >> 14) + ((1605 * b) >> 14) + 16); \ + if (y < 16) y = 16; if (y > 235) y = 235; \ + u = (((7192 * b) >> 14) - ((2424 * r) >> 14) - ((4767 * g) >> 14) + 128); \ + if (u < 128) u = 128; if (u > 240) u = 240; \ + v = (((7192 * r) >> 14) - ((6029 * g) >> 14) - ((1163 * b) >> 14) + 128); \ + if (v < 128) v = 128; if (v > 240) v = 240; \ +} +#endif diff --git a/raw/.gitignore b/raw/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/scripts/benchmark.sh b/scripts/benchmark.sh new file mode 100755 index 0000000..2d81779 --- /dev/null +++ b/scripts/benchmark.sh @@ -0,0 +1,203 @@ +#!/bin/bash + +# Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if [ "${MYDROID}" == "" ]; then + echo You must set your path to the Android Build in MYDROID. + exit +fi +if [ -z "${TI_HW_ROOT}" ]; then + export TI_HW_ROOT=hardware/ti +fi +if [ -z "${VISION_ROOT}" ]; then + export VISION_ROOT=hardware/ti/vision + echo "VISION_ROOT not defined, using $VISION_ROOT" +fi +if [ $# == 0 ]; then + echo "Usage: benchmark.sh [name setup|simcop|dsp|cpu|all|custom |report]" + echo "Example: benchmark.sh name 120418_ICS setup all report " + exit +fi + +export DVP_ROOT=${MYDROID}/${TI_HW_ROOT}/dvp +export HDR_FILE=${DVP_ROOT}/include/dvp/dvp_types.h +export PUBLIC_LIB_HEADER_LIST=" ${DVP_ROOT}/libraries/public/yuv/include/yuv/dvp_kl_yuv.h + ${DVP_ROOT}/libraries/public/imgfilter/include/imgfilter/dvp_kl_imgfilter.h + ${DVP_ROOT}/libraries/public/ocl/include/ocl/dvp_kl_ocl.h" +export PRIVATE_LIB_HEADER_LIST="${MYDROID}/${VISION_ROOT}/libraries/protected/imglib/include/imglib/dvp_kl_imglib.h + ${MYDROID}/${VISION_ROOT}/libraries/protected/vlib/include/vlib/dvp_kl_vlib.h + ${MYDROID}/${VISION_ROOT}/libraries/protected/vrun/include/vrun/dvp_kl_vrun.h + ${MYDROID}/${VISION_ROOT}/libraries/protected/rvm/include/rvm/dvp_kl_rvm.h + ${MYDROID}/${VISION_ROOT}/libraries/protected/tismo/include/tismo/dvp_kl_tismo.h" +export LIBHEADERS= + +export REPORT_DEBUG= #set to something to debug the report generation without running the test +export FRAMES=2 #set to number of frames to run +export OMX= #set to something to run the camera as the input, otherwise it will use file based input + +if [ ${OMX} ]; then + export QQVGA_FILE=OMX + export QVGA_FILE=OMX + export VGA_FILE=OMX + export x4VGA_FILE=OMX +else + export QQVGA_FILE=handqqvga + export QVGA_FILE=handqvga + export VGA_FILE=handvga + export x4VGA_FILE=hand4Xvga +fi + +while [ $# -gt 0 ]; +do + if [ "${1}" == "name" ]; then + shift + export DVP_BENCH_ROOT=${MYDROID}/${TI_HW_ROOT}/dvp/benchmarking/$1 + if [ ! -d "${MYDROID}/${TI_HW_ROOT}/dvp/benchmarking" ]; then + mkdir ${MYDROID}/${TI_HW_ROOT}/dvp/benchmarking + fi + if [ ! -d "${DVP_BENCH_ROOT}" ]; then + echo "Creating directories for results at /dvp/benchmarking" + mkdir ${DVP_BENCH_ROOT} + mkdir ${DVP_BENCH_ROOT}/simcop + mkdir ${DVP_BENCH_ROOT}/simcop/qqvga + mkdir ${DVP_BENCH_ROOT}/simcop/qvga + mkdir ${DVP_BENCH_ROOT}/simcop/vga + #mkdir ${DVP_BENCH_ROOT}/simcop/4xvga + mkdir ${DVP_BENCH_ROOT}/dsp + mkdir ${DVP_BENCH_ROOT}/dsp/qqvga + mkdir ${DVP_BENCH_ROOT}/dsp/qvga + mkdir ${DVP_BENCH_ROOT}/dsp/vga + #mkdir ${DVP_BENCH_ROOT}/dsp/4xvga + mkdir ${DVP_BENCH_ROOT}/cpu + mkdir ${DVP_BENCH_ROOT}/cpu/qqvga + mkdir ${DVP_BENCH_ROOT}/cpu/qvga + mkdir ${DVP_BENCH_ROOT}/cpu/vga + #mkdir ${DVP_BENCH_ROOT}/cpu/4xvga + else + echo "Directory /dvp/benchmarking exists, will overwrite previous data" + fi + fi + if [ "${1}" == "custom" ]; then + shift + export DVP_CUSTOM_DIR=$1 + shift + export DVP_CUSTOM_GRAPH=$1 + if [ "${DVP_CUSTOM_GRAPH}" != "x" ]; then + export DVP_CUSTOM_FLAG=1 + fi + if [ ! -d "${DVP_BENCH_ROOT}/${DVP_CUSTOM_DIR}" ]; then + echo "Creating directory for /dvp/benchmarking/${DVP_CUSTOM_DIR}" + mkdir ${DVP_BENCH_ROOT}/${DVP_CUSTOM_DIR} + mkdir ${DVP_BENCH_ROOT}/${DVP_CUSTOM_DIR}/qqvga + mkdir ${DVP_BENCH_ROOT}/${DVP_CUSTOM_DIR}/qvga + mkdir ${DVP_BENCH_ROOT}/${DVP_CUSTOM_DIR}/vga + #mkdir ${DVP_BENCH_ROOT}/${DVP_CUSTOM_DIR}/4xvga + else + echo "Directory /dvp/benchmarking/${DVP_CUSTOM_DIR} exists, will overwrite previous data" + fi + fi + if [ "${1}" == "setup" ]; then + # Connect ADB, Compile, install + $DVP_ROOT/scripts/dvp.sh setup zone dvpbenchmark clean mm install test + + #Load input videos + adb push $DVP_ROOT/raw/input/handqqvga_160x120_30Hz_UYVY.yuv /sdcard/raw/. + adb push $DVP_ROOT/raw/input/handqvga_320x240_30Hz_UYVY.yuv /sdcard/raw/. + adb push $DVP_ROOT/raw/input/handvga_640x480_30Hz_UYVY.yuv /sdcard/raw/. + adb push $DVP_ROOT/raw/input/hand4Xvga_1280x960_30Hz_UYVY.yuv /sdcard/raw/. + + adb shell "echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor" + export A9FREQ=`adb shell "cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq"` + echo "Set the A9 Frequency to $A9FREQ" + fi + if [ "${1}" == "simcop" ] || [ "${1}" == "all" ]; then + export SIMCOP_FLAG=1 + echo Running SIMCOP QQVGA from ${QQVGA_FILE} + adb shell "cd /sdcard && dvp_test ${QQVGA_FILE} 160 120 30 UYVY ${FRAMES} 7" > ${DVP_BENCH_ROOT}/simcop/qqvga/log + echo Running SIMCOP QVGA from ${QVGA_FILE} + adb shell "cd /sdcard && dvp_test ${QVGA_FILE} 320 240 30 UYVY ${FRAMES} 7" > ${DVP_BENCH_ROOT}/simcop/qvga/log + echo Running SIMCOP VGA from ${VGA_FILE} + adb shell "cd /sdcard && dvp_test ${VGA_FILE} 640 480 30 UYVY ${FRAMES} 7" > ${DVP_BENCH_ROOT}/simcop/vga/log + #echo Running SIMCOP 4XVGA from ${x4VGA_FILE} + #adb shell "cd /sdcard && dvp_test ${x4VGA_FILE} 1280 960 30 UYVY ${FRAMES} 7" > ${DVP_BENCH_ROOT}/simcop/4xvga/log + fi + if [ "${1}" == "dsp" ] || [ "${1}" == "all" ]; then + export DSP_FLAG=1 + echo Running DSP QQVGA from ${QQVGA_FILE} + adb shell "cd /sdcard && dvp_test ${QQVGA_FILE} 160 120 30 UYVY ${FRAMES} 8" > ${DVP_BENCH_ROOT}/dsp/qqvga/log + echo Running DSP QVGA from ${QVGA_FILE} + adb shell "cd /sdcard && dvp_test ${QVGA_FILE} 320 240 30 UYVY ${FRAMES} 8" > ${DVP_BENCH_ROOT}/dsp/qvga/log + echo Running DSP VGA from ${VGA_FILE} + adb shell "cd /sdcard && dvp_test ${VGA_FILE} 640 480 30 UYVY ${FRAMES} 8" > ${DVP_BENCH_ROOT}/dsp/vga/log + #echo Running DSP 4XVGA from ${x4VGA_FILE} + #adb shell "cd /sdcard && dvp_test ${x4VGA_FILE} 1280 960 30 UYVY ${FRAMES} 8" > ${DVP_BENCH_ROOT}/dsp/4xvga/log + fi + if [ "${1}" == "cpu" ] || [ "${1}" == "all" ]; then + export CPU_FLAG=1 + echo Running CPU QQVGA from ${QQVGA_FILE} + adb shell "cd /sdcard && dvp_test ${QQVGA_FILE} 160 120 30 UYVY ${FRAMES} 9" > ${DVP_BENCH_ROOT}/cpu/qqvga/log + echo Running CPU QVGA from ${QVGA_FILE} + adb shell "cd /sdcard && dvp_test ${QVGA_FILE} 320 240 30 UYVY ${FRAMES} 9" > ${DVP_BENCH_ROOT}/cpu/qvga/log + echo Running CPU VGA from ${VGA_FILE} + adb shell "cd /sdcard && dvp_test ${VGA_FILE} 640 480 30 UYVY ${FRAMES} 9" > ${DVP_BENCH_ROOT}/cpu/vga/log + #echo Running CPU 4XVGA from ${x4VGA_FILE} + #adb shell "cd /sdcard && dvp_test ${x4VGA_FILE} 1280 960 30 UYVY ${FRAMES} 9" > ${DVP_BENCH_ROOT}/cpu/4xvga/log + fi + if [ ${DVP_CUSTOM_DIR} ] && [ ${DVP_CUSTOM_FLAG} ]; then + unset DVP_CUSTOM_FLAG + echo Running ${DVP_CUSTOM_DIR} QQVGA from ${QQVGA_FILE} + adb shell "cd /sdcard && dvp_test ${QQVGA_FILE} 160 120 30 UYVY ${FRAMES} ${DVP_CUSTOM_GRAPH}" > ${DVP_BENCH_ROOT}/${DVP_CUSTOM_DIR}/qqvga/log + echo Running ${DVP_CUSTOM_DIR} QVGA from ${QVGA_FILE} + adb shell "cd /sdcard && dvp_test ${QVGA_FILE} 320 240 30 UYVY ${FRAMES} ${DVP_CUSTOM_GRAPH}" > ${DVP_BENCH_ROOT}/${DVP_CUSTOM_DIR}/qvga/log + echo Running ${DVP_CUSTOM_DIR} VGA from ${VGA_FILE} + adb shell "cd /sdcard && dvp_test ${VGA_FILE} 640 480 30 UYVY ${FRAMES} ${DVP_CUSTOM_GRAPH}" > ${DVP_BENCH_ROOT}/${DVP_CUSTOM_DIR}/vga/log + #echo Running ${DVP_CUSTOM_DIR} 4XVGA from ${x4VGA_FILE} + #adb shell "cd /sdcard && dvp_test ${x4VGA_FILE} 1280 960 30 UYVY ${FRAMES} ${DVP_CUSTOM_GRAPH}" > ${DVP_BENCH_ROOT}/${DVP_CUSTOM_DIR}/4xvga/log + fi + if [ "${1}" == "report" ]; then + # Only include the headers that exist from vision_prebuilt + for i in ${PRIVATE_LIB_HEADER_LIST}; do + if [ -f ${i} ]; then + LIBHEADERS+="${i} "; + echo "Library Header File Found: ${i}"; + fi + done + if [ ${REPORT_DEBUG} ]; then + export SIMCOP_FLAG=1 + export DSP_FLAG=1 + export CPU_FLAG=1 + fi + if [ -f "${DVP_BENCH_ROOT}/simcop/qqvga/log" ] && [ ${SIMCOP_FLAG} ]; then + unset SIMCOP_FLAG + echo "Generating SIMCOP report" + report.pl ${HDR_FILE} ${DVP_BENCH_ROOT}/simcop 1 ${FRAMES} ${LIBHEADERS} ${PUBLIC_LIB_HEADER_LIST} + fi + if [ -f "${DVP_BENCH_ROOT}/dsp/qqvga/log" ] && [ ${DSP_FLAG} ]; then + unset DSP_FLAG + echo "Generating DSP report" + report.pl ${HDR_FILE} ${DVP_BENCH_ROOT}/dsp 1 ${FRAMES} ${LIBHEADERS} ${PUBLIC_LIB_HEADER_LIST} + fi + if [ -f "${DVP_BENCH_ROOT}/cpu/qqvga/log" ] && [ ${CPU_FLAG} ]; then + unset CPU_FLAG + echo "Generating CPU report" + report.pl ${HDR_FILE} ${DVP_BENCH_ROOT}/cpu 1 ${FRAMES} ${LIBHEADERS} ${PUBLIC_LIB_HEADER_LIST} + fi + if [ -f "${DVP_BENCH_ROOT}/${DVP_CUSTOM_DIR}/qqvga/log" ]; then + echo "Generating ${DVP_CUSTOM_DIR} report" + report.pl ${HDR_FILE} ${DVP_BENCH_ROOT}/${DVP_CUSTOM_DIR} 0 ${FRAMES} ${LIBHEADERS} ${PUBLIC_LIB_HEADER_LIST} + fi + fi + shift +done diff --git a/scripts/dvp.bat b/scripts/dvp.bat new file mode 100755 index 0000000..e719420 --- /dev/null +++ b/scripts/dvp.bat @@ -0,0 +1,164 @@ +@ECHO OFF + +@REM Copyright (C) 2011 Texas Insruments, Inc. +@REM +@REM Licensed under the Apache License, Version 2.0 (the "License"); +@REM you may not use this file except in compliance with the License. +@REM You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. + + +@IF "%MYDROID%" == "" @( + @ECHO "You must set the MYDROID variable! + @GOTO END +) + +@IF "%_PRODUCT_%" == "" @( + SET _PRODUCT_=blaze +) + +@IF "%TI_HW_ROOT%" == "" @( + SET TI_HW_ROOT=hardware\ti +) + +@SET OUT_DIR=%MYDROID%\out\target\product\%_PRODUCT_% +@SET DVP_ROOT=%MYDROID%\%TI_HW_ROOT%\dvp +@SET TARGET_LIBS=dvp dvp_kgm_cpu dvp_kgm_imx dvp_kgm_dsp +@SET TARGET_BINS=shm_service +@SET TARGET_APPS= +@SET TARGET_PACKAGES= +@SET TARGET_TEST=vcam_simple vcam_test vcam_server dvp_simple dvp_demo sosal_test uinput_test +@SET TARGET_SRVC= +@SET TARGET_SPKG= +@SET TARGET_DOMX=camera OMX_Core omx_rpc omx_proxy_common OMX.TI.DUCATI1.VIDEO.CAMERA OMX.TI.DUCATI1.IMAGE.JPEGD + +:LOOP + @IF "%1" == "setup" @( + adb kill-server + adb start-server + adb get-state + adb devices + ) + @IF "%1" == "logcat" @( + start /min adb logcat + ) + @IF "%1" == "omx" @( + adb remount + @FOR %%A IN (%TARGET_DOMX%) DO @( + adb shell "rm /system/lib/lib%%A.so" + adb push %OUT_DIR%\system\lib\lib%%A.so /system/lib + ) + ) + @IF "%1" == "test" @( + adb remount + @FOR %%A IN (%TARGET_TEST%) DO @( + @ECHO Reinstalling %%A + adb shell "rm /system/bin/%%A" + adb push %OUT_DIR%\system\bin\%%A /system/bin + adb shell "chmod 755 /system/bin/%%A" + adb shell "chown root /system/bin/%%A" + @REM adb shell "chgrp shell /system/bin/%%A" + ) + ) + @IF "%1" == "export" @( + @FOR %%A IN (%TARGET_LIBS%) DO @( + @echo Copying lib%%A.so + copy %OUT_DIR%\system\lib\lib%%A.so %2 + ) + @FOR %%A IN (%TARGET_BINS%) DO @( + @echo Copying %%A + copy %OUT_DIR%\system\bin\%%A %2 + ) + @FOR %%A IN (%TARGET_APPS%) DO @( + @echo Copying %%A.apk + copy %OUT_DIR%\system\app\%%A.apk %2 + ) + @FOR %%A IN (%TARGET_SRVC%) DO @( + @echo Copying %%A.apk + copy %OUT_DIR%\system\app\%%A.apk %2 + ) + ) + @IF "%1" == "install" @( + adb remount + @FOR %%A IN (%TARGET_LIBS%) DO @( + @ECHO Installing %%A + adb push %OUT_DIR%\system\lib\lib%%A.so /system/lib + ) + @FOR %%A IN (%TARGET_BINS%) DO @( + @ECHO Installing %%A + adb push %OUT_DIR%\system\bin\%%A /system/bin + adb shell "chmod 755 /system/bin/%%A" + adb shell "chown root /system/bin/%%A" + @REM adb shell "chgrp shell /system/bin/%%A" + ) + ) + @IF "%1" == "remoteclean" @( + adb remount + @FOR %%A IN (%TARGET_LIBS%) DO @( + @ECHO Uninstalling %%A + adb shell "rm /system/lib/lib%%A.so" + ) + @FOR %%A IN (%TARGET_BINS%) DO @( + @ECHO Uninstalling %%A + adb shell "rm /system/bin/%%A" + ) + @FOR %%A IN (%TARGET_PACKAGES%) DO @( + @ECHO Uninstalling %%A + adb shell "rm -rf /data/data/%%A" + adb uninstall %%A + ) + @FOR %%A IN (%TARGET_SPKG%) DO @( + @ECHO Uninstalling %%A + adb shell "rm -rf /data/data/%%A" + adb uninstall %%A + ) + ) + @IF "%1" == "qdisp" @( + adb push %DVP_ROOT%\scripts\qdisp.sh /data + adb shell "chmod 755 /data/qdisp.sh" + adb shell "/data/qdisp.sh" + ) + @IF "%1" == "v4l2" @( + adb shell "echo \"2lcd\" > /sys/devices/platform/omapdss/overlay2/manager" + adb shell "echo 2 > /sys/devices/platform/omapdss/overlay0/zorder" + adb shell "echo 1 > /sys/devices/platform/omapdss/overlay1/zorder" + adb shell "echo 3 > /sys/devices/platform/omapdss/overlay2/zorder" + adb shell "echo 1 > /sys/devices/platform/omapdss/overlay2/enabled" + adb shell "echo 0 > /sys/devices/platform/omapdss/manager2/trans_key_value" + adb shell "echo \"video-source\" > /sys/devices/platform/omapdss/manager2/trans_key_type" + ) + @IF "%1" == "perf" @( + adb shell "echo \"ondemand\" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor" + adb shell "echo 1 > /sys/devices/system/cpu/cpu1/online + adb shell "echo \"performance\" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor" + adb shell "cat /sys/devices/system/cpu/cpu0/online" + adb shell "cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor" + adb shell "cat /sys/devices/system/cpu/cpu1/online" + adb shell "cat /sys/devices/system/cpu/cpu1/cpufreq/scaling_governor" + ) + @IF "%1" == "service" ( + start /b adb shell "shm_service" + adb shell "ps" | find "shm_service" + ) + @IF "%1" == "tombstones" @( + adb pull /data/tombstones/ . + adb shell "rm -rf /data/tombstones/*" + ) + @IF "%1" == "vcam_server" @( + adb forward tcp:8501 tcp:8501 + adb forward tcp:8502 tcp:8502 + adb shell vcam_server + ) + @SHIFT + @IF "%1" == "" GOTO END +@GOTO LOOP + +:END + diff --git a/scripts/dvp.sh b/scripts/dvp.sh new file mode 100755 index 0000000..8de88e0 --- /dev/null +++ b/scripts/dvp.sh @@ -0,0 +1,135 @@ +#!/bin/bash + +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# The definitions must be matched to the dvp_debug.h and sosal/debug.h +function zone_mask() { + if [ "$1" == "print" ]; then + echo DVP_DEBUG=${DVP_DEBUG} + echo DVP_ZONE_MASK=${DVP_ZONE_MASK} + echo SOSAL_DEBUG=${SOSAL_DEBUG} + echo SOSAL_ZONE_MASK=${SOSAL_ZONE_MASK} + echo OMAPRPC_DEBUG=${OMAPRPC_DEBUG} + echo OMAPRPC_ZONE_MASK=${OMAPRPC_ZONE_MASK} + fi + if [ "$1" == "undef" ]; then # Refer to Android.mk for defaults in this case + unset DVP_DEBUG + unset DVP_ZONE_MASK + unset SOSAL_DEBUG + unset SOSAL_ZONE_MASK + unset OMAPRPC_DEBUG + unset OMAPRPC_ZONE_MASK + fi + if [ "$1" == "runtime" ]; then + export DVP_DEBUG=2 + unset DVP_ZONE_MASK + export SOSAL_DEBUG=2 + unset SOSAL_ZONE_MASK + export OMAPRPC_DEBUG=2 + unset OMAPRPC_ZONE_MASK + fi + if [ "$1" == "clear" ] || [ "$1" == "none" ] || [ "$1" == "release" ]; then # All debugging turned off + export DVP_DEBUG=0 + export DVP_ZONE_MASK=0 + export SOSAL_DEBUG=0 + export SOSAL_ZONE_MASK=0 + export OMAPRPC_DEBUG=0 + export OMAPRPC_ZONE_MASK=0 + fi + if [ "$1" == "full" ]; then + export DVP_DEBUG=2 + export DVP_ZONE_MASK=0xFFFFFFFF + export SOSAL_DEBUG=2 + export SOSAL_ZONE_MASK=0xFFFFFFFF + export OMAPRPC_DEBUG=2 + export OMAPRPC_ZONE_MASK=0xFFFF + fi + if [ "$1" == "min" ]; then + export DVP_DEBUG=2 + export DVP_ZONE_MASK=0x0003 + export SOSAL_DEBUG=2 + export SOSAL_ZONE_MASK=0x0003 + export OMAPRPC_DEBUG=2 + export OMAPRPC_ZONE_MASK=0x3 + fi + if [ "$1" == "errors" ]; then + export DVP_DEBUG=2 + export DVP_ZONE_MASK=0x0001 + export SOSAL_DEBUG=2 + export SOSAL_ZONE_MASK=0x0001 + export OMAPRPC_DEBUG=2 + export OMAPRPC_ZONE_MASK=0x1 + fi + if [ "$1" == "perf" ]; then + export DVP_DEBUG=2 + export DVP_ZONE_MASK=0x8203 + export SOSAL_DEBUG=2 + export SOSAL_ZONE_MASK=0x0003 + export OMAPRPC_DEBUG=2 + export OMAPRPC_ZONE_MASK=0x21 + fi + if [ "$1" == "rpc" ]; then + export DVP_DEBUG=2 + export DVP_ZONE_MASK=0x0233 + export SOSAL_DEBUG=2 + export SOSAL_ZONE_MASK=0x0001 + export OMAPRPC_DEBUG=2 + export OMAPRPC_ZONE_MASK=0x1 + fi + if [ "$1" == "debug" ]; then + export DVP_DEBUG=2 + export DVP_ZONE_MASK=0xFFFF + export SOSAL_DEBUG=2 + export SOSAL_ZONE_MASK=0x1 + export OMAPRPC_DEBUG=2 + export OMAPRPC_ZONE_MASK=0x1 + fi + if [ "$1" == "dvpbenchmark" ]; then # For use by benchmark.pl scripts + export DVP_DEBUG=1 + export DVP_ZONE_MASK=0x0203 + export SOSAL_DEBUG=1 + export SOSAL_ZONE_MASK=0x1 + export OMAPRPC_DEBUG=1 + export OMAPRPC_ZONE_MASK=0x1 + fi + if [ "$1" == "dvptest" ]; then + export DVP_DEBUG=2 + export DVP_ZONE_MASK=0x0273 + export SOSAL_DEBUG=2 + export SOSAL_ZONE_MASK=0x3 + export OMAPRPC_DEBUG=2 + export OMAPRPC_ZONE_MASK=0x1 + fi + if [ "$1" == "fullprint" ]; then + export DVP_DEBUG=1 + export DVP_ZONE_MASK=0xFFFFFFFF + export SOSAL_DEBUG=1 + export SOSAL_ZONE_MASK=0xFFFFFFFF + export OMAPRPC_DEBUG=1 + export OMAPRPC_ZONE_MASK=0xFFFFFFFF + fi +} + +if [ -n "${MYDROID}" ]; then + . dvp_android.sh $* +fi + +if [ -n "${QNX_TARGET}" ]; then + . dvp_qnx.sh $* +fi + +if [ -z "${QNX_TARGET}" ] && [ -z "${MYDROID}" ]; then + . dvp_linux.sh $* +fi diff --git a/scripts/dvp_android.sh b/scripts/dvp_android.sh new file mode 100755 index 0000000..1102a0c --- /dev/null +++ b/scripts/dvp_android.sh @@ -0,0 +1,889 @@ +#!/bin/bash + +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +function make_install_deplibs() { + DEPS=$* + for i in ${DEPS}; do + echo Making ${i} + done + make -j${CPUS} ${DEPS} + for i in ${DEPS}; do + if [ "${i}" == "camera.omap4" ]; then + adb -s ${TARGET_DEVICE} push ${ANDROID_PRODUCT_OUT}/system/lib/hw/${i}.so /system/lib/hw + else + adb -s ${TARGET_DEVICE} push ${ANDROID_PRODUCT_OUT}/system/lib/${i}.so /system/lib + fi + + done + adb -s ${TARGET_DEVICE} shell "sync" +} + +function get_symbols() { + FILENAME=${1} + FILETYPE=${2} + OBJOPT="-C -d -g -f -l -S --include=${TARGET_ROOT}" + echo "Processing $filename" + if [ "${FILETYPE}" == "lib" ] && [ -e ${ANDROID_PRODUCT_OUT}/symbols/system/lib/${FILENAME} ]; then + arm-eabi-objdump ${OBJOPT} ${ANDROID_PRODUCT_OUT}/symbols/system/lib/${FILENAME} > ${TARGET_ROOT}/out/${FILENAME}.txt + fi + if [ "${FILETYPE}" == "bin" ] && [ -e ${ANDROID_PRODUCT_OUT}/symbols/system/bin/${FILENAME} ]; then + arm-eabi-objdump ${OBJOPT} ${ANDROID_PRODUCT_OUT}/symbols/system/bin/${FILENAME} > ${TARGET_ROOT}/out/${FILENAME}.txt + fi +} + +function get_devices() { + if [ -z "${TARGET_DEVICE}" ]; then + NUM_DEV=`adb devices | grep -E "^[0-9A-Fa-f]+" | awk '{print $1}' | wc -l` + if [ "${NUM_DEV}" == "1" ]; then + export TARGET_DEVICE=`adb devices | grep -E "^[0-9A-Fa-f]+" | awk '{print $1}'` + elif [ "${NUM_DEV}" -gt "1" ]; then + echo "You must set your TARGET_DEVICE to the serial number of the device to program. You have ${NUM_DEV} devices connected now!" + exit + else + echo "You must have a device plugged in to use ADB" + exit + fi + fi +} + +if [ "${MYDROID}" == "" ]; then + echo You must set your path to the Android Build in MYDROID. + exit +fi + +if [ $# == 0 ]; then + echo "Usage: $0 [clean|build|vars|setup|install|videos|convert|test|rvm|vlib|baseimage|music|apps]" + echo "" + echo " options: " + echo " clean - Deletes previously built libraries & intermediate files on the host machine" + echo " remoteclean - Deletes previously libraries & intermediate files on the target device." + echo " build - Builds entire DVP project" + echo " vars - Checks for your currently defined environment build variables relating to DVP." + echo " install - Installs successfully-built libraries and applications. Requires active adb connection!" + echo " -- You might want to run the 'DVP.sh setup' option first --" + echo " setup - Configures your adb connection. Requires 'ADB_HOST' variable to be defined! (e.g. ADB_HOST=125.247.xx.yy)" + echo " videos - Downloads processed video files from target device to DVP's root folder/raw on host machine" + echo " convert - " + echo " test - Runs the DVP framework in various standalone test modes." + echo " baseimage - Installs the Ducati / Tesla binaries & the Syslink on the target device and reboot the target device." + echo "" + exit +fi +################################################################################ +if [ -z "${_PRODUCT_}" ]; then + export _PRODUCT_=blaze_tablet +fi +echo "Target product is ${_PRODUCT_}" + +if [ -z "${TI_HW_ROOT}" ]; then + export TI_HW_ROOT=hardware/ti +fi +if [ -z "${TARGET_ANDROID}" ]; then + export TARGET_ANDROID=GB + if [ "${_PRODUCT_}" == "blaze_tablet" ]; then + export TARGET_ANDROID=ICS + fi +fi +if [ "${_PRODUCT_}" == "maguro" ] || [ "${_PRODUCT_}" == "tuna" ]; then + export TARGET_ANDROID=ICS +fi +if [ "${_PRODUCT_}" == "p2" ]; then + export TARGET_ANDROID=ICS +fi +################################################################################ +echo "DVP Configured for ${TARGET_ANDROID}" +################################################################################ +export ANDROID_PRODUCT_OUT=${MYDROID}/out/target/product/${_PRODUCT_} +export DVP_ROOT=${MYDROID}/${TI_HW_ROOT}/dvp +export CPUS=`cat /proc/cpuinfo | grep processor | wc -l` + +export TARGET_PROJ=dvp +export TARGET_ROOT="${MYDROID}/${TI_HW_ROOT}/${TARGET_PROJ}" +export TARGET_LIBS="dvp dvp_kgm_cpu dvp_kgm_simcop dvp_kgm_dsp" +if [ "${TARGET_ANDROID}" == "ICS" ] || [ "${TARGET_ANDROID}" == "JB" ]; then +export TARGET_SLIB="cthreaded VisionEngine pyuv sosal vcam v4l2 imgdbg sosal_shm omaprpc gfxdisp anw sf" +export TARGET_TEST="dvp_demo dvp_dsplib dvp_simple dvp_test dvp_share dvp_crash_test dvp_info v4l2_test vcam_test vcam_simple vcam_server sosal_test imgfilter_test uinput_test gfxd_test modload_test dvp_unittest" +else +export TARGET_SLIB="cthreaded VisionEngine pyuv sosal vcam v4l2 imgdbg sosal_shm" +export TARGET_TEST="dvp_demo dvp_dsplib dvp_simple dvp_test dvp_share dvp_crash_test dvp_info v4l2_test vcam_test vcam_simple vcam_server sosal_test imgfilter_test uinput_test modload_test dvp_unittest" +fi +export TARGET_BINS="shm_service" +export TARGET_APPS="" +export TARGET_PKGS="" +export TARGET_SRVC="" +export TARGET_SPKG="" + +while [ $# -gt 0 ]; +do + if [ "${1}" == "usbsetup" ]; then + sudo mkdir -p /root/.android + sudo echo "0x0451" > /root/.android/adb_usb.ini + echo Be sure to enable USB Debugging on the Device and to enable usbfs + echo if you are running versions of Ubuntu previous to 10.10. + fi + if [ "${1}" == "setup" ]; then + adb kill-server + killall adb + adb start-server + adb get-state + adb devices + get_devices + echo "TARGET_DEVICE=${TARGET_DEVICE}" + if [ -n "${TARGET_DEVICE}" ] && [ "${TARGET_ANDROID}" == "ICS" ] || [ "${TARGET_ANDROID}" == "JB" ]; then + adb -s ${TARGET_DEVICE} root + sleep 2 + adb -s ${TARGET_DEVICE} remount + fi + fi + if [ "${1}" == "perms" ]; then + cd ${TARGET_ROOT} + # mark all directories as drwxr-xr-x + find . -type d -exec chmod 755 {} \; + # mark all files as rw-r--r-- + find . -type f -exec chmod 644 {} \; + # mark all executable files (on PC) as rwxr-xr-x + chmod 755 bin/* + find . -type f -name "*\.bat" -exec chmod 755 {} \; + find . -type f -name "*\.pl" -exec chmod 755 {} \; + find . -type f -name "*\.x*" -exec chmod 755 {} \; + find . -type f -name "*\.sh" -exec chmod 755 {} \; + find . -type f -name "*\.out" -exec chmod 755 {} \; + find . -type f -name "*\.rc" -exec chmod 644 {} \; + find . -type f -name "*\.so" -exec chmod 755 {} \; + cd ${MYDROID} + fi + if [ "${1}" == "unix" ]; then + cd ${TARGET_ROOT} + FILES=`find . -type f \( -name *.c -o -name *.cpp -o -name *.h -o -name *.java -o -name *.aidl -o -name *.xml \) -print` + for f in ${FILES}; do + fromdos -v -p -o $f + done + cd ${MYDROID} + fi + if [ "${1}" == "clean" ]; then + for i in ${TARGET_SLIB}; do + echo Removing Static Library $i in ${_PRODUCT_} + rm -rf ${ANDROID_PRODUCT_OUT}/obj/STATIC_LIBRARIES/lib${i}_intermediates/ + done + for i in ${TARGET_LIBS}; do + echo Removing Shared Library $i in ${_PRODUCT_} + rm -rf ${ANDROID_PRODUCT_OUT}/obj/SHARED_LIBRARIES/lib${i}_intermediates/ + rm -rf ${ANDROID_PRODUCT_OUT}/symbols/system/lib/lib${i}.so + rm -rf ${ANDROID_PRODUCT_OUT}/system/lib/lib${i}.so + done + for i in ${TARGET_BINS}; do + echo Removing Binary $i in ${_PRODUCT_} + rm -rf ${ANDROID_PRODUCT_OUT}/obj/EXECUTABLES/${i}_intermediates/ + rm -rf ${ANDROID_PRODUCT_OUT}/symbols/system/bin/${i} + rm -rf ${ANDROID_PRODUCT_OUT}/system/bin/${i} + done + for i in ${TARGET_TEST}; do + echo Removing Binary $i in ${_PRODUCT_} + rm -rf ${ANDROID_PRODUCT_OUT}/obj/EXECUTABLES/${i}_intermediates/ + rm -rf ${ANDROID_PRODUCT_OUT}/symbols/system/bin/${i} + rm -rf ${ANDROID_PRODUCT_OUT}/system/bin/${i} + done + for i in ${TARGET_APPS}; do + echo Removing Android App $i in ${_PRODUCT_} + rm -rf out/target/common/obj/APPS/${i}_intermediates/ + rm -rf ${ANDROID_PRODUCT_OUT}/obj/APPS/${i}_intermediates/ + done + for i in ${TARGET_SPKG}; do + echo Removing Android Package $i in ${_PRODUCT_} + rm -rf out/target/common/obj/JAVA_LIBRARIES/${i}_intermediates/ + rm -rf ${ANDROID_PRODUCT_OUT}/obj/JAVA_LIBRARIES/${i}_intermediates/ + done + for i in ${TARGET_SRVC}; do + echo Removing Android Service $i in ${_PRODUCT_} + rm -rf out/target/common/obj/APPS/${i}_intermediates/ + rm -rf ${ANDROID_PRODUCT_OUT}/obj/APPS/${i}_intermediates/ + done + fi + if [ "${1}" == "remoteclean" ]; then + cd ${MYDROID} + get_devices + for i in ${TARGET_BINS}; do + adb -s ${TARGET_DEVICE} shell "rm /system/bin/${i}" + done + for i in ${TARGET_TEST}; do + adb -s ${TARGET_DEVICE} shell "rm /system/bin/${i}" + done + for i in ${TARGET_LIBS}; do + adb -s ${TARGET_DEVICE} shell "rm /system/lib/lib${i}.so" + done + for i in ${TARGET_PKGS}; do + adb -s ${TARGET_DEVICE} uninstall $i + adb -s ${TARGET_DEVICE} shell "rm -rf /data/data/${i}" + done + for i in ${TARGET_APPS}; do + adb -s ${TARGET_DEVICE} shell "rm -rf /system/apps/${i}.apk" + done + for i in ${TARGET_SRVC}; do + adb -s ${TARGET_DEVICE} uninstall $i + done + for i in ${TARGET_SPKG}; do + adb -s ${TARGET_DEVICE} uninstall $i + done + adb -s ${TARGET_DEVICE} shell "rm /data/raw/*" + adb -s ${TARGET_DEVICE} shell "sync" + fi + if [ "${1}" == "install" ]; then + get_devices + adb -s ${TARGET_DEVICE} remount + for i in ${TARGET_BINS}; do + echo Installing ${i} + adb -s ${TARGET_DEVICE} push ${ANDROID_PRODUCT_OUT}/system/bin/${i} /system/bin/ + #adb -s ${TARGET_DEVICE} shell "chmod 755 /system/bin/${i}" + #adb -s ${TARGET_DEVICE} shell "chown root /system/bin/${i}" + done + for i in ${TARGET_LIBS}; do + echo Installing lib${i}.so + adb -s ${TARGET_DEVICE} push ${ANDROID_PRODUCT_OUT}/system/lib/lib${i}.so /system/lib/ + done + adb -s ${TARGET_DEVICE} shell "mkdir -p /sdcard/raw" + adb -s ${TARGET_DEVICE} shell "sync" + fi + if [ "${1}" == "package" ]; then + export TARGET_OUT=${TARGET_ROOT}/out/ANDROID/ARM/ + mkdir -p ${TARGET_OUT} + for i in ${TARGET_BINS}; do + mkdir -p ${TARGET_OUT}/system/bin/ + cp -Rfp ${ANDROID_PRODUCT_OUT}/system/bin/${i} ${TARGET_OUT}/system/bin + done + for i in ${TARGET_TEST}; do + mkdir -p ${TARGET_OUT}/system/bin/ + cp -Rfp ${ANDROID_PRODUCT_OUT}/system/bin/${i} ${TARGET_OUT}/system/bin + done + for i in ${TARGET_LIBS}; do + mkdir -p ${TARGET_OUT}/system/lib/ + cp -Rfp ${ANDROID_PRODUCT_OUT}/system/lib/lib${i}.so ${TARGET_OUT}/system/lib + done + cd ${TARGET_OUT} + tar zcvf ${TARGET_PROJ}.tar.gz system/ + cd ${MYDROID} + fi + if [ "${1}" == "test" ]; then + get_devices + adb -s ${TARGET_DEVICE} remount + for i in ${TARGET_TEST}; do + echo Installing ${i} + adb -s ${TARGET_DEVICE} push ${ANDROID_PRODUCT_OUT}/system/bin/${i} /system/bin/ + done + adb -s ${TARGET_DEVICE} shell "sync" + fi + if [ "${1}" == "mm" ]; then + cd ${MYDROID} + source build/envsetup.sh + cd ${TARGET_ROOT} + if [ "${_PRODUCT_}" == "GT-I9100G" ]; then + mm -j$CPUS PRODUCT-${_PRODUCT_}-eng + else + mm -j$CPUS + fi + cd ${MYDROID} + fi + if [ "${1}" == "apps" ]; then + get_devices + for i in ${TARGET_PKGS}; do + echo Uninstalling ${i} + adb -s ${TARGET_DEVICE} uninstall ${i} + adb -s ${TARGET_DEVICE} shell "rm -rf /data/data/${i}" + done + for i in ${TARGET_APPS}; do + echo Installing ${i} + adb -s ${TARGET_DEVICE} shell "rm /system/app/${i}.apk" + adb -s ${TARGET_DEVICE} install ${ANDROID_PRODUCT_OUT}/system/app/${i}.apk + done + fi + if [ "${1}" == "omxdeps" ]; then + if [ "${TARGET_ANDROID}" == "GB" ]; then + cd ${MYDROID} + get_devices + adb -s ${TARGET_DEVICE} remount + make_install_deplibs libOMX_Core \ + libcamera \ + libomx_rpc \ + libomx_proxy_common \ + libOMX.TI.DUCATI1.VIDEO.CAMERA \ + libOMX.TI.DUCATI1.IMAGE.JPEGD + fi + fi + if [ "${1}" == "syslinkdeps" ]; then + if [ "${TARGET_ANDROID}" == "GB" ]; then + cd ${MYDROID} + get_devices + adb -s ${TARGET_DEVICE} remount + make_install_deplibs libipc libipcutils libsysmgr librcm libnotify + fi + fi + if [ "${1}" == "alldeps" ]; then + if [ "${TARGET_ANDROID}" == "GB" ]; then + cd ${MYDROID} + get_devices + adb -s ${TARGET_DEVICE} remount + make_install_deplibs libipc \ + libipcutils \ + libsysmgr \ + libmemmgr \ + librcm \ + libOMX_Core \ + libcamera \ + libOMX.TI.DUCATI1.VIDEO.CAMERA \ + libOMX.TI.DUCATI1.IMAGE.JPEGD \ + libVendor_ti_omx + fi + fi + if [ "${1}" == "vars" ]; then + env | grep DVP + env | grep VLIB + env | grep RVM + env | grep OMX + env | grep VCAM + env | grep TARGET + fi + if [ "${1}" == "patches" ]; then + if [ "${TARGET_ANDROID}" == "GB" ]; then + cd ${MYDROID}/${TI_HW_ROOT}/omx + git checkout -b DB482 + git checkout -b DB482-NUI + git am < ${TARGET_ROOT}/patches/GB/domx/0001-Added-single-preview-mode-type.patch + git am < ${TARGET_ROOT}/patches/GB/domx/0002-Added-Gesture-related-OMX-interface-changes.patch + git am < ${TARGET_ROOT}/patches/GB/domx/0003-OMX-OMX-Cap-structure-extended-with-the-3D-capabilit.patch + git am < ${TARGET_ROOT}/patches/GB/domx/0004-Malloc-Fix.patch + git am < ${TARGET_ROOT}/patches/GB/domx/0005-ZSL-OMX-Interface.patch + git am < ${TARGET_ROOT}/patches/GB/domx/0006-core-ti-Restore-OMX_TI_CONFIG_SHAREDBUFFER.patch + git am < ${TARGET_ROOT}/patches/GB/domx/0007-OMX-OMX-changes-for-stereo-gesture-usecase.patch + cd ${MYDROID} + fi + if [ "${TARGET_ANDROID}" == "ICS" ] || [ "${TARGET_ANDROID}" == "JB" ]; then + # TUNA and MAGURO don't need to be patched for eCameraView + if [ "${_PRODUCT_}" == "maguro" ] || [ "${_PRODUCT_}" == "tuna" ]; then + cd ${MYDROID}/${TI_HW_ROOT}/omap4xxx/domx/omx_core + else + cd ${MYDROID}/${TI_HW_ROOT}/domx + fi + git am ${TARGET_ROOT}/patches/ICS/android/domx/*.patch + cd ${MYDROID}/device/ti/blaze_tablet + git am ${TARGET_ROOT}/patches/ICS/android/0001-Tablet-Add-startup-of-shm-and-ARX-services-in-init.patch + cd ${MYDROID}/device/ti/blaze + git am ${TARGET_ROOT}/patches/ICS/android/0001-Blaze-Add-startup-of-shm-and-ARX-services-in-init.patch + cd ${MYDROID} + fi + fi + + if [ "${1}" == "kill" ]; then + adb -s ${TARGET_DEVICE} kill-server + fi + if [ "${1}" == "logcat" ]; then + adb -s ${TARGET_DEVICE} logcat *:D >> ${MYDROID}/logcat.log & + echo "To see the logcat data, do a $ tail -f logcat.log" + fi + if [ "${1}" == "trace" ]; then + adb -s ${TARGET_DEVICE} shell "syslink_trace_daemon.out" >> ${MYDROID}/syslink_trace.log & + echo "To see the SYSLINK trace, do a $ tail -f syslink_trace.log" + fi + if [ "${1}" == "shell" ]; then + get_devices + if [ -z "${2}" ]; then + adb -s ${TARGET_DEVICE} shell + else + shift # eat the $1 + echo "Executing ${*}" + adb -s ${TARGET_DEVICE} shell "${*}" & + fi + fi + if [ "${1}" == "baseimage" ]; then + cd ${MYDROID} + get_devices + adb -s ${TARGET_DEVICE} root + sleep 2 + adb -s ${TARGET_DEVICE} remount + SUFFIX="" + if [ "${TARGET_ANDROID}" == "JB" ]; then + SUFFIX="-jb" + fi + if [ "${TARGET_ANDROID}" == "GB" ]; then + echo "Loading Ducati Base Image" + adb -s ${TARGET_DEVICE} push ${TARGET_ROOT}/prebuilt/base_image_app_m3.xem3 /system/vendor/firmware/. + adb -s ${TARGET_DEVICE} push ${TARGET_ROOT}/prebuilt/base_image_sys_m3.xem3 /system/vendor/firmware/. + echo "Loading Tesla Base Image" + adb -s ${TARGET_DEVICE} push ${TARGET_ROOT}/prebuilt/base_image_dsp.xe64T /system/vendor/firmware/. + echo "Loading syslink_daemon.out" + adb -s ${TARGET_DEVICE} push ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/syslink_daemon.out /system/bin/. + adb -s ${TARGET_DEVICE} shell chmod 755 /system/bin/syslink_daemon.out + echo "Loading libsysmgr.so" + adb -s ${TARGET_DEVICE} push ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/libsysmgr.so /system/lib/. + elif [ "${TARGET_ANDROID}" == "ICS" ] || [ "${TARGET_ANDROID}" == "JB" ] ; then + echo "Loading Ducati Base Image" + if [ "${_PRODUCT_}" == "omap5sevm" ]; then + adb -s ${TARGET_DEVICE} push ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/ducati-m3-core0.xem3 /vendor/firmware/. + else + adb -s ${TARGET_DEVICE} push ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/ducati-m3${SUFFIX}.bin /vendor/firmware/ducati-m3.bin + fi + echo "Loading Tesla Base Image" + adb -s ${TARGET_DEVICE} push ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/tesla-dsp${SUFFIX}.bin /vendor/firmware/tesla-dsp.bin + fi + adb -s ${TARGET_DEVICE} shell "sync" + fi + if [ "${1}" == "dcc" ]; then + cd ${MYDROID} + get_devices + adb -s ${TARGET_DEVICE} root + sleep 2 + adb -s ${TARGET_DEVICE} remount + echo "Using Ducati Default DCC Files" + if [ "${TARGET_ANDROID}" == "GB" ]; then + adb -s ${TARGET_DEVICE} shell "mv /etc/omapcam /etc/omapcam.bak" + elif [ "${TARGET_ANDROID}" == "ICS" ] || [ "${TARGET_ANDROID}" == "JB" ]; then + adb -s ${TARGET_DEVICE} shell "mv /data/misc/camera /data/misc/camera.bak" + fi + adb -s ${TARGET_DEVICE} shell "sync" + fi + if [ "${1}" == "docs" ]; then + export PUBLIC_LIB_HEADER_LIST=" ${TARGET_ROOT}/libraries/public/yuv/include/yuv/dvp_kl_yuv.h + ${TARGET_ROOT}/libraries/public/imgfilter/include/imgfilter/dvp_kl_imgfilter.h + ${TARGET_ROOT}/libraries/public/ocl/include/ocl/dvp_kl_ocl.h + ${TARGET_ROOT}/libraries/public/vrun/include/vrun/dvp_kl_vrun.h" + export PRIVATE_LIB_HEADER_LIST="${MYDROID}/${VISION_ROOT}/libraries/protected/imglib/include/imglib/dvp_kl_imglib.h + ${MYDROID}/${VISION_ROOT}/libraries/protected/vlib/include/vlib/dvp_kl_vlib.h + ${MYDROID}/${VISION_ROOT}/libraries/protected/rvm/include/rvm/dvp_kl_rvm.h + ${MYDROID}/${VISION_ROOT}/libraries/protected/tismo/include/tismo/dvp_kl_tismo.h" + export LIBHEADERS= + export doxygen_status=`dpkg-query -W -f='${Status}\n' doxygen` + export graphviz_status=`dpkg-query -W -f='${Status}\n' graphviz` + export mscgen_status=`dpkg-query -W -f='${Status}\n' mscgen` + if [ "$doxygen_status" == "install ok installed" ] && + [ "$graphviz_status" == "install ok installed" ] && + [ "$mscgen_status" == "install ok installed" ]; then + pushd ${TARGET_ROOT} + export COMMIT=`git describe --tags --dirty` + cp docs/dvp_sdk.txt docs/dvp_sdk.bak + sed -i "s/VERSION/${COMMIT}/" docs/dvp_sdk.txt + sed -i "s/DATE/`date`/" docs/dvp_sdk.txt + if [ "${TARGET_ANDROID}" == "GB" ]; then + export PREDEF="PREDEFINED += ANDROID GINGERBREAD DVP_USE_RCM" + elif [ "${TARGET_ANDROID}" == "ICS" ]; then + export PREDEF="PREDEFINED += ANDROID ICS DVP_USE_OMAPRPC" + elif [ "${TARGET_ANDROID}" == "JB" ]; then + export PREDEF="PREDEFINED += ANDROID JELLYBEAN DVP_USE_OMAPRPC" + else + export PREDEF="PREDEFINED += LINUX" + fi + + # Only include the headers that exist from vision_prebuilt + for i in ${PRIVATE_LIB_HEADER_LIST}; do + if [ -f ${i} ]; then + LIBHEADERS+="${i} "; + echo "Library Header File Found: ${i}"; + PREDEF+=" `echo ${i} | sed 's/.*dvp_kl_\([a-z]*\).h/DVP_USE_\U\1/'` "; + fi + done + scripts/kernel_doc.pl docs/dvp_kernel_autogen.txt ${TARGET_ROOT}/include/dvp/dvp_types.h ${LIBHEADERS} ${PUBLIC_LIB_HEADER_LIST} + (cat docs/full/Doxyfile ; echo "PROJECT_NUMBER = \"DVP project git tag: \" $COMMIT" ; echo $PREDEF; \ + echo "INPUT+= ${LIBHEADERS}") | doxygen - + mv docs/dvp_sdk.bak docs/dvp_sdk.txt + popd + echo "Look in ${TARGET_ROOT}/docs/ for the generated documentation" + else + echo "A required package is not installed on your machine!" + echo "To generate ${TARGET_PROJ} docs, install the package (sudo apt-get install ) and re-run this option." + fi + fi + if [ "${1}" == "ramdisk" ]; then + if [ "${EMMC_DIR}" == "" ]; then + echo "You must set EMMC_DIR variable first." + else + if [ -d "${EMMC_DIR}" ]; then + cd ${EMMC_DIR} + + mkdir root + cd root/ + gunzip -c ../ramdisk.img | cpio -i + cd ../ + + SUFFIX="" + if [ "${TARGET_ANDROID}" == "JB" ]; then + SUFFIX="-jb" + fi + echo "Replacing the original init.rc script with our modified one." + if [ "${TARGET_ANDROID}" == "ICS" ] || [ "${TARGET_ANDROID}" == "JB" ] ; then + if [ "${_PRODUCT_}" == "maguro" ] || [ "${_PRODUCT_}" == "tuna" ]; then + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/init.tuna.rc ${EMMC_DIR}/root/. + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/init.rc ${EMMC_DIR}/root/. + elif [ "${_PRODUCT_}" == "omap5sevm" ]; then + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/ueventd.omap5sevmboard.rc ${EMMC_DIR}/root/. + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/init.omap5sevmboard.rc ${EMMC_DIR}/root/. + else + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/init.omap4blazeboard${SUFFIX}.rc ${EMMC_DIR}/root/init.omap4blazeboard.rc + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/ueventd.omap4blazeboard.rc ${EMMC_DIR}/root/. + fi + else + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/init.omap4430.rc ${EMMC_DIR}/root/. + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/kos/* ${EMMC_DIR}/root/. + fi + ${MYDROID}/out/host/linux-x86/bin/mkbootfs root/ | ${MYDROID}/out/host/linux-x86/bin/minigzip >ramdisk.img + if [ "${TARGET_ANDROID}" == "ICS" ] || [ "${TARGET_ANDROID}" == "JB" ] ; then + echo "Replacing our zImage to enable OMAPRPC." + cp -fv ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/zImage${SUFFIX} ${EMMC_DIR}/zImage + #./umulti2.sh + ./mkbootimg --kernel zImage --ramdisk ramdisk.img --base 0x80000000 --cmdline "" --board omap4 -o boot.img + else + echo "Replacing our zImage to enable Tesla." + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/zImage_sl2_ducati_debug_gadget ${EMMC_DIR}/zImage + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/umulti.sh ${EMMC_DIR}/umulti.sh + ./umulti.sh + fi + + rm -R root + + if [ "${_PRODUCT_}" != "omap5sevm" ]; then + echo "Reboot the device into fastboot mode" + sudo ./fastboot flash boot ./boot.img + echo "Rebooting Fastboot" + sudo ./fastboot reboot + fi + else + echo "EMMC_DIR variable does not point to a valid directory." + fi + fi + fi + if [ "${1}" == "emmc" ]; then + if [ "${EMMC_DIR}" == "" ]; then + echo "You must set EMMC_DIR variable first." + else + if [ -d "${EMMC_DIR}" ]; then + + # Modifying boot.img + echo "Modifying ${EMMC_DIR}" + cd ${EMMC_DIR} + mkdir root + cd root/ + gunzip -c ../ramdisk.img | cpio -i + cd ../ + + SUFFIX="" + if [ "${TARGET_ANDROID}" == "JB" ]; then + SUFFIX="-jb" + fi + + echo "Replacing the original init.rc script with our modified one." + if [ "${TARGET_ANDROID}" == "ICS" ] || [ "${TARGET_ANDROID}" == "JB" ]; then + if [ "${_PRODUCT_}" == "maguro" ] || [ "${_PRODUCT_}" == "tuna" ]; then + echo "target product is maguro (tuna)" + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/init.tuna.rc ${EMMC_DIR}/root/. + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/init.rc ${EMMC_DIR}/root/. + else + if [ "${_PRODUCT_}" == "omap5sevm" ]; then + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/ueventd.omap5sevmboard.rc ${EMMC_DIR}/root/. + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/init.omap5sevmboard.rc ${EMMC_DIR}/root/. + else + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/init.omap4blazeboard.rc ${EMMC_DIR}/root/. + fi + fi + else + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/kos/* ${EMMC_DIR}/root/. + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/init.omap4430.rc ${EMMC_DIR}/root/. + fi + ${MYDROID}/out/host/linux-x86/bin/mkbootfs root/ | ${MYDROID}/out/host/linux-x86/bin/minigzip >ramdisk.img + if [ "${TARGET_ANDROID}" == "ICS" ] || [ "${TARGET_ANDROID}" == "JB" ] ; then + echo "Replacing our zImage to enable OMAPRPC." + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/zImage${SUFFIX} ${EMMC_DIR}/zImage + #./umulti2.sh + ./mkbootimg --kernel zImage --ramdisk ramdisk.img --base 0x80000000 --cmdline "" --board omap4 -o boot.img + else + echo "Replacing our zImage to enable Tesla." + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/zImage_sl2_ducati_debug_gadget ${EMMC_DIR}/zImage + cp -f ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/umulti.sh ${EMMC_DIR}/umulti.sh + ./umulti.sh + fi + rm -R root + + # Extracting system partitions + ./simg2img system.img system.img.raw + mkdir tmp + sudo mount -t ext4 -o loop system.img.raw tmp/ + sudo chmod -R a+w tmp + + # From "install" + for i in $TARGET_BINS; do + echo Copying ${i} + cp ${ANDROID_PRODUCT_OUT}/system/bin/${i} tmp/bin/ + done + for i in $TARGET_LIBS; do + echo Copying lib${i}.so + cp ${ANDROID_PRODUCT_OUT}/system/lib/lib${i}.so tmp/lib/ + done + + # From "test" + for i in $TARGET_TEST; do + echo Copying ${i} + cp ${ANDROID_PRODUCT_OUT}/system/bin/${i} tmp/bin/ + done + # From "baseimage" + + if [ "${TARGET_ANDROID}" == "ICS" ] || [ "${TARGET_ANDROID}" == "JB" ] ; then + echo "Copying Ducati and Tesla images" + cp ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/ducati-m3${SUFFIX}.bin tmp/vendor/firmware/ducati-m3.bin + cp ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/tesla-dsp${SUFFIX}.bin tmp/vendor/firmware/tesla-dsp.bin + else + echo "Loading Ducati Base Image" + cp ${TARGET_ROOT}/prebuilt/base_image_app_m3.xem3 tmp/vendor/firmware/ + cp ${TARGET_ROOT}/prebuilt/base_image_sys_m3.xem3 tmp/vendor/firmware/ + echo "Loading Tesla Base Image" + cp ${TARGET_ROOT}/prebuilt/base_image_dsp.xe64T tmp/vendor/firmware/ + echo "Loading syslink_daemon.out" + cp ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/syslink_daemon.out tmp/bin/ + sudo chmod 755 tmp/bin/syslink_daemon.out + echo "Loading libsysmgr.so" + cp ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/libsysmgr.so tmp/lib/ + fi + sudo ./make_ext4fs -s -l 512M -a system system.img tmp/ + sudo umount tmp + rm -rf tmp + rm -rf system.img.raw + + # Extracting data partition for DCC file change + ./simg2img userdata.img userdata.img.raw + mkdir tmpData + sudo mount -t ext4 -o loop userdata.img.raw tmpData/ + sudo chmod -R a+w tmpData + + if [ "${TARGET_ANDROID}" == "GB" ]; then + echo Gingerbread DCC file not needed to be changed. + #mv /etc/omapcam /etc/omapcam.bak + elif [ "${TARGET_ANDROID}" == "ICS" ] || [ "${TARGET_ANDROID}" == "JB" ]; then + mv tmpData/misc/camera tmpData/misc/camera.bak + fi + + sudo ./make_ext4fs -s -l 512M -a userdata userdata.img tmpData/ + ${MYDROID}/out/host/linux-x86/bin/mkuserimg.sh -s tmpData userdata.img ext4 data 512M + sudo umount tmpData + rm -rf tmpData + rm -rf userdata.img.raw + if [ "${TARGET_ANDROID}" == "ICS" ] || [ "${TARGET_ANDROID}" == "JB" ]; then + echo "Copying xloader" + cp ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/*MLO ./ + fi + else + echo EMMC_DIR variable does not point to a valid directory. + fi + fi + fi + if [ "${1}" == "debug" ]; then + cd ${MYDROID} + OBJOPT="-C -d -g -f -l -S --include=${TARGET_ROOT}" + echo Outputing Obj-Dump info on ${TARGET_PROJ} Objects + source build/envsetup.sh + setpaths + mkdir ${TARGET_ROOT}/out + # System Objects + #arm-eabi-objdump ${OBJOPT} ${ANDROID_PRODUCT_OUT}/symbols/system/bin/gdbserver > ${TARGET_ROOT}/out/gdbserver.txt + arm-eabi-objdump ${OBJOPT} ${ANDROID_PRODUCT_OUT}/symbols/system/lib/libc.so > ${TARGET_ROOT}/out/libc.txt + arm-eabi-objdump ${OBJOPT} ${ANDROID_PRODUCT_OUT}/symbols/system/lib/libOMX.TI.DUCATI1.VIDEO.CAMERA.so > ${TARGET_ROOT}/out/libOMX.TI.DUCATI1.VIDEO.CAMERA.txt + #arm-eabi-objdump ${OBJOPT} ${ANDROID_PRODUCT_OUT}/symbols/system/lib/libopencore_common.so > ${TARGET_ROOT}/out/libopencore_common.txt + # Unit Tests + for i in ${TARGET_BINS}; do + arm-eabi-objdump ${OBJOPT} ${ANDROID_PRODUCT_OUT}/symbols/system/bin/${i} > ${TARGET_ROOT}/out/${i}.txt + done + for i in ${TARGET_TEST}; do + arm-eabi-objdump ${OBJOPT} ${ANDROID_PRODUCT_OUT}/symbols/system/bin/${i} > ${TARGET_ROOT}/out/${i}.txt + done + for i in ${TARGET_LIBS}; do + arm-eabi-objdump ${OBJOPT} ${ANDROID_PRODUCT_OUT}/symbols/system/lib/lib${i}.so > ${TARGET_ROOT}/out/lib${i}.txt + done + fi + if [ "${1}" == "tombstones" ]; then + get_devices + rm ${TARGET_ROOT}/out/tombstone_* + TOMBSTONES=`adb -s ${TARGET_DEVICE} shell "ls /data/tombstones" | tr '\r' ' ' | tr '\n' ' '` + echo ${TOMBSTONES} + for file in ${TOMBSTONES} + do + echo "Copying file ${file} to PC" + adb -s ${TARGET_DEVICE} pull /data/tombstones/${file} ${TARGET_ROOT}/out/ + done + adb -s ${TARGET_DEVICE} shell "rm /data/tombstones/*" + fi + if [ "${1}" == "perf" ]; then + get_devices + adb -s ${TARGET_DEVICE} shell "echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor" + fi + if [ "${1}" == "videos" ]; then + get_devices + LISTING=`adb -s ${TARGET_DEVICE} shell "ls /sdcard/raw/" | grep "^[0-9][0-9]" | tr '\r' ' ' | tr '\n' ' '` + mkdir -p ${TARGET_ROOT}/raw/output/ + for file in ${LISTING} + do + echo "Copying ${file} from device to ${TARGET_ROOT}/raw/output/" + adb -s ${TARGET_DEVICE} pull /sdcard/raw/${file} ${TARGET_ROOT}/raw/output/ + #adb -s ${TARGET_DEVICE} shell rm -rf /sdcard/raw/${file} + done + fi + if [ "${1}" == "convert" ]; then + LISTING=`ls ${TARGET_ROOT}/raw/output | grep "^[0-9][0-9]_bitimg" | tr '\r' ' ' | tr '\n' ' '` + for file in ${LISTING} + do + echo "Converting ${file}" + modfile=`echo ${file} | sed "s/bitimg/img/"` + ${TARGET_ROOT}/bin/bitimg2img ${TARGET_ROOT}/raw/output/${file} ${TARGET_ROOT}/raw/output/$modfile + done + fi + if [ "${1}" == "unitest" ]; then + adb -s ${TARGET_DEVICE} shell "sosal_test" + adb -s ${TARGET_DEVICE} shell "dvp_test" + fi + if [ "${1}" == "gdb" ] || [ "${1}" == "ddd" ]; then + get_devices + TYPE=${1} + if [ "${TARGET_ANDROID}" == "GB" ]; then + adb -s ${TARGET_DEVICE} push ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/gdbserver /system/bin/ + adb -s ${TARGET_DEVICE} shell "chmod 777 /system/bin/gdbserver" + fi + PROCESS=${2} + shift # Remove "gdb" + shift # Remove "process" + adb -s ${TARGET_DEVICE} forward tcp:5039 tcp:5039 + adb -s ${TARGET_DEVICE} shell "cd /sdcard && gdbserver :5039 /system/bin/${PROCESS} $*" & + cat > gdb_cmds.txt << EOF +set solib-absolute-prefix ${ANDROID_PRODUCT_OUT}/symbols +set solib-search-path ${ANDROID_PRODUCT_OUT}/symbols/system/lib +target remote ${ADBHOST}:5039 +EOF + if [ "${TYPE}" == "gdb" ]; then + arm-eabi-gdb ${ANDROID_PRODUCT_OUT}/symbols/system/bin/${PROCESS} --command=gdb_cmds.txt + fi + if [ "${TYPE}" == "ddd" ]; then + ddd --debugger arm-eabi-gdb -x gdb_cmds.txt ${ANDROID_PRODUCT_OUT}/symbols/system/bin/${PROCESS} & + fi + #rm gdb_cmds.txt + exit + fi + if [ "${1}" == "attach" ]; then + if [ "${TARGET_ANDROID}" == "GB" ]; then + adb -s ${TARGET_DEVICE} push ${TARGET_ROOT}/prebuilt/ANDROID/${TARGET_PLATFORM}/gdbserver /system/bin/ + adb -s ${TARGET_DEVICE} shell "chmod 777 /system/bin/gdbserver" + fi + PROCESS=${2} + adb -s ${TARGET_DEVICE} forward tcp:5039 tcp:5039 + PID=`adb -s ${TARGET_DEVICE} shell "ps" | grep ${PROCESS} | awk '{print $2}'` + echo "Connecting to ${PROCESS} PID ${PID}" + adb -s ${TARGET_DEVICE} shell "gdbserver --attach :5039 ${PID}" & + cat > gdb_cmds.txt << EOF +set solib-absolute-prefix ${ANDROID_PRODUCT_OUT}/symbols +set solib-search-path ${ANDROID_PRODUCT_OUT}/symbols/system/lib +target remote ${ADBHOST}:5039 +EOF + ddd --debugger arm-eabi-gdb -x gdb_cmds.txt ${ANDROID_PRODUCT_OUT}/symbols/system/bin/${PROCESS} & + fi + if [ "${1}" == "todo" ]; then + cd ${MYDROID} + source build/envsetup.sh + cd ${TARGET_ROOT} + cgrep TODO + cd ${MYDROID} + fi + if [ "${1}" == "qdisp" ]; then + adb -s ${TARGET_DEVICE} push ${TARGET_ROOT}/qdisp.sh /bin && adb -s ${TARGET_DEVICE} shell "chmod 755 /bin/qdisp.sh && qdisp.sh" + fi + if [ "${1}" == "vcam_server" ]; then + if [ "${2}" == "local" ]; then + adb -s ${TARGET_DEVICE} shell vcam_server & + adb -s ${TARGET_DEVICE} shell "vcam_simple -t 3 -w 320 -h 240 -# 300 -s 1" + else + adb -s ${TARGET_DEVICE} forward tcp:8501 tcp:8501 + adb -s ${TARGET_DEVICE} forward tcp:8502 tcp:8502 + adb -s ${TARGET_DEVICE} shell vcam_server & + fi + fi + if [ "${1}" == "zones" ] || [ "${1}" == "zone" ]; then + if [ -n "${2}" ]; then + zone_mask ${2} + shift + fi + zone_mask print + fi + if [ "${1}" == "init" ]; then + if [ "${TARGET_ANDROID}" == "ICS" ] || [ "${TARGET_ANDROID}" == "JB" ]; then + if ["${_PRODUCT_}" == "omap5sevm"]; then + INIT_SCRIPT=${MYDROID}/device/ti/${_PRODUCT_}/init.omap5sevmboard.rc + else + INIT_SCRIPT=${MYDROID}/device/ti/${_PRODUCT_}/init.omap4blazeboard.rc + fi + else + INIT_SCRIPT=${MYDROID}/device/ti/${_PRODUCT_}/init.omap4430.rc + fi + TEXT=`cat $INIT_SCRIPT | grep shm_service` + if [ -z "$TEXT" ]; then + cat >> $INIT_SCRIPT << EOF +# Texas Instruments Shared Memory Service +service shm_service /system/bin/shm_service --no-fork + class core + user root + group root +EOF + fi + if [ -n "$TEXT" ]; then + echo "$INIT_SCRIPT already has entry for shm_service" + fi + fi + if [ "${1}" == "fastboot" ]; then + echo "Rebooting ${TARGET_DEVICE} into fastboot" + adb -s ${TARGET_DEVICE} reboot bootloader + fi + if [ "${1}" == "reboot" ]; then + echo "Rebooting ${TARGET_DEVICE}" + adb -s ${TARGET_DEVICE} reboot + fi + if [ "${1}" == "wait" ]; then + echo "Waiting for ${TARGET_DEVICE} to connect to ADB" + adb -s ${TARGET_DEVICE} wait-for-device + fi + if [ "${1}" == "ndk" ]; then + OUTDIR=${2} + if [ -z "${OUTDIR}" ]; then + OUTDIR=$MYDROID/../dvp_ndk/ + fi + if [ ! -d "${OUTDIR}" ]; then + mkdir -p ${OUTDIR} + fi + echo "Exporting DVP to NDK format in ${OUTDIR}" + export INCDIRS="dvp sosal" + for inc in ${INCDIRS}; do + echo "Exporting Include Folder ${inc}" + mkdir -p ${OUTDIR}/include/$inc + cp -Rf ${DVP_ROOT}/include/$inc ${OUTDIR}/include/ + done + # remove some files: + rm -f ${OUTDIR}/include/dvp/Vision*.h + rm -f ${OUTDIR}/include/dvp/Image*.h + # Copy the outputs + mkdir -p ${OUTDIR}/libs/armeabi/ + for lib in ${TARGET_LIBS}; do + cp -f ${ANDROID_PRODUCT_OUT}/system/lib/lib$lib.so ${OUTDIR}/libs/armeabi/ + done + #for lib in ${TARGET_SLIB}; do + #cp -f ${ANDROID_PRODUCT_OUT}/system/lib/lib$lib.a ${OUTDIR}/libs/armeabi/ + #done + # Copy the docs + pushd ${DVP_ROOT} + doxygen ${DVP_ROOT}/docs/ndk/Doxyfile + mkdir -p ${OUTDIR}/docs/ + cp -Rf ${TARGET_ROOT}/docs/ndk/html/ ${OUTDIR}/docs/ + popd + fi + shift +done diff --git a/scripts/dvp_avsdk.bat b/scripts/dvp_avsdk.bat new file mode 100755 index 0000000..b568803 --- /dev/null +++ b/scripts/dvp_avsdk.bat @@ -0,0 +1,19 @@ +@ECHO ON + +@IF "%ROOTDIR%" == "" @GOTO EXIT +@IF "%DVP_ROOT%" == "" @GOTO EXIT + +@SET INC_DIRS=include\sosal include\dvp +@SET SRC_DIRS=source\sosal source\dvp\dvp_kgraph source\dvp\dvp_kgm_cpu +@SET TARGET=C:\sdks\av_bios_sdk_00_06_00_00\avsdk_00_06_00_00\demos\avsk_app\a8 + +@SET XCOPY_OPTS=/I /Y +xcopy %DVP_ROOT%\include\sosal\*.h %TARGET%\inc\sosal\ %XCOPY_OPTS% +xcopy %DVP_ROOT%\include\dvp\*.h %TARGET%\inc\dvp\ %XCOPY_OPTS% +xcopy %DVP_ROOT%\source\dvp\dvp_kgraph\include\*.h %TARGET%\inc\dvp\ %XCOPY_OPTS% +xcopy %DVP_ROOT%\source\dvp\dvp_kgm_cpu\*.h %TARGET%\inc\dvp\ %XCOPY_OPTS% +xcopy %DVP_ROOT%\source\sosal\*.c %TARGET%\src\sosal\ %XCOPY_OPTS% +xcopy %DVP_ROOT%\source\dvp\dvp_kgraph\*.c %TARGET%\src\dvp\ %XCOPY_OPTS% +xcopy %DVP_ROOT%\source\dvp\dvp_kgm_cpu\*.c %TARGET%\src\dvp\ %XCOPY_OPTS% + +:EXIT \ No newline at end of file diff --git a/scripts/dvp_linux.sh b/scripts/dvp_linux.sh new file mode 100755 index 0000000..f8a40f5 --- /dev/null +++ b/scripts/dvp_linux.sh @@ -0,0 +1,470 @@ +#!/bin/bash + +# Copyright (C) 2009-2012 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +function get_symbols() { + FILENAME=$1 + FILETYPE=$2 + OBJOPT="-C -d -g -f -l -S --include=${TARGET_ROOT}" + echo "Processing filename" + objdump ${OBJOPT} ${OUT_DIR}/${FILENAME} > ${OUT_DIR}/${FILENAME}.txt +} + + +if [ -z "${DVP_ROOT}" ]; then + echo "You must set DVP_ROOT manually!" + die 1 +fi + +# Make the TARGET_ env variables +cd ${DVP_ROOT} +LINES=$(make targets | grep TARGET_) +for line in ${LINES}; do + echo ${line} + export ${line} +done +cd - + +export OUT_DIR=${DVP_ROOT}/out/${TARGET_OS}/${TARGET_CPU} +export CPUS=`cat /proc/cpuinfo | grep processor | wc -l` + +export TARGET_PROJ=dvp +export TARGET_ROOT="${DVP_ROOT}" +export TARGET_LIBS="dvp dvp_kgm_cpu" +if [ "${TARGET_CPU}" == "ARM" ]; then + export TARGET_LIBS="dvp dvp_kgm_cpu dvp_kgm_simcop dvp_kgm_dsp dvp_kgm_ocl omaprpc" +fi +export TARGET_SLIB="cthreaded VisionEngine pyuv sosal vcam v4l2 imgdbg vlib_${TARGET_CPU} rvm_${TARGET_CPU} yuv imglib_${TARGET_CPU} c6xsim" +export TARGET_BINS="" +export TARGET_TEST="dvp_demo dvp_simple dvp_test v4l2_test vcam_simple vcam_server sosal_test uinput_test" +export TARGET_APPS="" +export TARGET_PKGS="" +export TARGET_SRVC="" +export TARGET_SPKG="" +export OMX_INC=${OMX_ROOT}/omx_core/inc + +if [ $# == 0 ]; then + echo "Usage: $0 [clean|remoteclean|mm|vars|setup|install|test|images|videos|convert|baseimage|docs|gdb|ddd|run|]" + echo "" + echo " options: " + echo " clean - Deletes previously built libraries & intermediate files on the host machine" + echo " remoteclean - Deletes previously built libraries & intermediate files on the target device" + echo " mm - Builds entire DVP project on the host machine" + echo " vars - Checks for your currently defined environment build variables relating to DVP." + echo " install - Installs successfully-built libraries and applications. Requires active network connection or SD card if on remote target!" + echo " test - Installs successfully-built test binaries. Requires active network connection or SD card if on remote target!" + echo " -- You might want to run the 'DVP.sh setup' option first --" + echo " setup - Adds ssh public key to device. Requires 'TARGET_IP' variable to be defined! (e.g. TARGET_IP=125.247.xx.yy)" + echo " images - Uploads input video files from host machine to root/raw/ on device" + echo " videos - Downloads processed video files from target device to DVP's root folder/raw/output on host machine" + echo " convert - Converts the downloaded video files that are binary images to images that can be viewed on pyuv player" + echo " run - Runs the DVP framework in various standalone test modes." + echo " baseimage - Installs the Ducati / Tesla binaries on the target device and reboot the target device." + echo "" + exit +fi + +echo "Target platform is ${TARGET_PLATFORM}" + +if [ "${TARGET_PLATFORM}" != "PANDA" ]; then + export SUDO=sudo +else + export SUDO= +fi +echo "SUDO is : ${SUDO}" + +while [ $# -gt 0 ]; +do + if [ "${1}" == "vars" ]; then + env | grep DVP + env | grep VISION + env | grep TARGET_IP + env | grep ROOTFS_DIR + fi + if [ "${1}" == "setup" ]; then + if [ "${TARGET_CPU}" == "ARM" ]; then + if [ ! -f "${HOME}/.ssh/id_rsa.pub" ]; then + echo "ERROR: SSH public key NOT found" + exit 0 + fi + echo "Copying local SSH RSA public key to Panda" + ssh root@${TARGET_IP} "mkdir -p /root/.ssh" + ssh root@${TARGET_IP} "chmod 644 /root/.ssh" + scp ${HOME}/.ssh/id_rsa.pub root@${TARGET_IP}:/root/.ssh/authorized_keys + exit 0 + fi + fi + if [ "${1}" == "perms" ]; then + cd ${TARGET_ROOT} + # mark all directories as drwxr-xr-x + find . -type d -exec chmod 755 {} \; + # mark all files as rw-r--r-- + find . -type f -exec chmod 644 {} \; + # mark all executable files (on PC) as rwxr-xr-x + chmod 755 bin/* + chmod 755 scripts/*.sh + chmod 755 scripts/*.bat + chmod 755 prebuilt/*.x* + fi + if [ "${1}" == "unix" ]; then + cd ${TARGET_ROOT} + FILES=`find . -type f \( -name *.c -o -name *.cpp -o -name *.h -o -name *.java -o -name *.aidl -o -name *.xml -o -name *.mak \) -print` + for f in ${FILES}; do + fromdos -v -p -o $f + done + cd ${MYDROID} + fi + if [ "${1}" == "clean" ]; then + rm -rf ${OUT_DIR} + fi + if [ "${1}" == "mm" ]; then + cd ${TARGET_ROOT} + make + fi + if [ "${1}" == "remoteclean" ]; then + cd ${TARGET_ROOT} + if [ "${TARGET_CPU}" == "ARM" ]; then + if [ "${TARGET_IP}" != "" ]; then # Network case + for i in ${TARGET_BINS}; do + ssh root@${TARGET_IP} "rm /usr/bin/${i}" + done + for i in ${TARGET_TEST}; do + ssh root@${TARGET_IP} "rm /usr/bin/${i}" + done + for i in ${TARGET_LIBS}; do + ssh root@${TARGET_IP} "rm /usr/lib/lib${i}.so" + done + ssh root@${TARGET_IP} "rm /root/raw/*" + elif [ "${ROOTFS_DIR}" != "" ]; then # SD Card case + for i in ${TARGET_BINS}; do + ${SUDO} rm ${ROOTFS_DIR}/usr/bin/${i} + done + for i in ${TARGET_TEST}; do + ${SUDO} rm ${ROOTFS_DIR}/usr/bin/${i} + done + for i in ${TARGET_LIBS}; do + ${SUDO} rm ${ROOTFS_DIR}/usr/lib/lib${i}.so + done + ${SUDO} rm ${ROOTFS_DIR}/root/raw/* + else + echo "For network install: set TARGET_IP variable." + echo "For SD card install: set ROOTFS_DIR variable." + exit 0 + fi + else # PC Case + # For running on PC, we MUST put the .so files in the /usr/lib folder because DVP is explicitly looking for + # dvp_kgm_* files to know what kgm's are available for loading. Bins can safely remain in the OUT_DIR + # if called directly (or calling the dvp.sh run ). + for i in ${TARGET_LIBS}; do + ${SUDO} rm /usr/lib/lib${i}.so + done + fi + fi + if [ "${1}" == "install" ]; then + if [ "${TARGET_CPU}" == "ARM" ]; then + if [ "${TARGET_IP}" != "" ]; then # Network case + cd ${TARGET_ROOT} + for i in ${TARGET_BINS}; do + echo Installing ${i} + scp ${OUT_DIR}/${i} root@${TARGET_IP}:/usr/bin/ + done + for i in ${TARGET_LIBS}; do + echo Installing lib${i}.so + scp ${OUT_DIR}/lib${i}.so root@${TARGET_IP}:/usr/lib/ + done + elif [ "${ROOTFS_DIR}" != "" ]; then # SD Card case + for i in ${TARGET_BINS}; do + echo Installing ${i} + ${SUDO} cp ${OUT_DIR}/${i} ${ROOTFS_DIR}/usr/bin/. + done + for i in ${TARGET_LIBS}; do + echo Installing lib${i}.so + ${SUDO} cp ${OUT_DIR}/lib${i}.so ${ROOTFS_DIR}/usr/lib/. + done + sync + else + echo "For network install: set TARGET_IP variable." + echo "For SD card install: set ROOTFS_DIR variable." + exit 0 + fi + else # PC Case + # For running on PC, we MUST put the .so files in the /usr/lib folder because DVP is explicitly looking for + # dvp_kgm_* files to know what kgm's are available for loading. Bins can safely remain in the OUT_DIR + # if called directly (or calling the dvp.sh run ). + for i in ${TARGET_LIBS}; do + echo Installing lib${i}.so + ${SUDO} cp ${OUT_DIR}/lib${i}.so /usr/lib/. + done + fi + fi + if [ "${1}" == "test" ]; then + if [ "${TARGET_CPU}" == "ARM" ]; then + if [ "${TARGET_IP}" != "" ]; then # Network case + ssh root@${TARGET_IP} mkdir -p /root/ + ssh root@${TARGET_IP} mkdir -p /root/raw + cd ${TARGET_ROOT} + for i in ${TARGET_TEST}; do + echo Installing ${i} + scp ${OUT_DIR}/${i} root@${TARGET_IP}:/usr/bin/ + done + elif [ "${ROOTFS_DIR}" != "" ]; then # SD Card case + ${SUDO} mkdir -p ${ROOTFS_DIR}/root + ${SUDO} mkdir -p ${ROOTFS_DIR}/root/raw + for i in ${TARGET_TEST}; do + echo Installing ${i} + ${SUDO} cp ${OUT_DIR}/${i} ${ROOTFS_DIR}/usr/bin/. + done + sync + else + echo "For network install: set TARGET_IP variable." + echo "For SD card install: set ROOTFS_DIR variable." + exit 0 + fi + fi + fi + if [ "${1}" == "domxinstall" ]; then + if [ "${TARGET_CPU}" == "ARM" ] && [ "${OMX_ROOT}" != "" ]; then + if [ "${TARGET_IP}" != "" ]; then # Network case + echo Installing DOMX Libs + scp ${OMX_ROOT}/domx/libdomx.so root@${TARGET_IP}:/usr/lib/ + scp ${OMX_ROOT}/omx_proxy_component/omx_camera/libOMX.TI.DUCATI1.VIDEO.CAMERA.so root@${TARGET_IP}:/usr/lib/ + scp ${OMX_ROOT}/omx_core/libomx_core.so root@${TARGET_IP}:/usr/lib/ + scp ${OMX_ROOT}/mm_osal/libmm_osal.so root@${TARGET_IP}:/usr/lib/ + elif [ "${ROOTFS_DIR}" != "" ]; then # SD Card case + echo Installing DOMX Libs + ${SUDO} cp ${OMX_ROOT}/domx/libdomx.so ${ROOTFS_DIR}/usr/lib/ + ${SUDO} cp ${OMX_ROOT}/omx_proxy_component/omx_camera/libOMX.TI.DUCATI1.VIDEO.CAMERA.so ${ROOTFS_DIR}/usr/lib/ + ${SUDO} cp ${OMX_ROOT}/omx_core/libomx_core.so ${ROOTFS_DIR}/usr/lib/ + ${SUDO} cp ${OMX_ROOT}/mm_osal/libmm_osal.so ${ROOTFS_DIR}/usr/lib/ + sync + else + echo "For network install: set TARGET_IP variable." + echo "For SD card install: set ROOTFS_DIR variable." + exit 0 + fi + fi + fi + if [ "${1}" == "images" ]; then + if [ "${TARGET_CPU}" == "ARM" ]; then + if [ "${TARGET_IP}" != "" ]; then # Network case + ssh root@${TARGET_IP} mkdir -p /root/ + ssh root@${TARGET_IP} mkdir -p /root/raw + echo Installing Input Test Videos + scp ${TARGET_ROOT}/raw/input/hand* root@${TARGET_IP}:/root/raw/. + elif [ "${ROOTFS_DIR}" != "" ]; then # SD Card case + ${SUDO} mkdir -p ${ROOTFS_DIR}/root + ${SUDO} mkdir -p ${ROOTFS_DIR}/root/raw + echo Installing Input Test Videos + ${SUDO} cp ${TARGET_ROOT}/raw/input/hand* ${ROOTFS_DIR}/root/raw/. + sync + else + echo "For network install: set TARGET_IP variable." + echo "For SD card install: set ROOTFS_DIR variable." + exit 0 + fi + fi + fi + if [ "${1}" == "baseimage" ]; then + if [ "${TARGET_CPU}" == "ARM" ]; then + if [ "${TARGET_IP}" != "" ]; then # Network case + ssh root@${TARGET_IP} mkdir -p /lib/firmware + echo "Loading Ducati Base Image" + scp ${TARGET_ROOT}/prebuilt/ANDROID/BLAZE/ducati-m3.bin root@${TARGET_IP}:/lib/firmware/. + echo "Loading Tesla Base Image" + scp ${TARGET_ROOT}/prebuilt/ANDROID/BLAZE/tesla-dsp.bin root@${TARGET_IP}:/lib/firmware/. + elif [ "${ROOTFS_DIR}" != "" ]; then # SD Card case + ${SUDO} mkdir ${ROOTFS_DIR}/lib/firmware + echo "Loading Ducati Base Image" + ${SUDO} cp ${TARGET_ROOT}/prebuilt/ANDROID/BLAZE/ducati-m3.bin ${ROOTFS_DIR}/lib/firmware/. + echo "Loading Tesla Base Image" + ${SUDO} cp ${TARGET_ROOT}/prebuilt/ANDROID/BLAZE/tesla-dsp.bin ${ROOTFS_DIR}/lib/firmware/. + sync + else + echo "For network install: set TARGET_IP variable." + echo "For SD card install: set ROOTFS_DIR variable." + exit 0 + fi + fi + fi + if [ "${1}" == "videos" ]; then + if [ "${TARGET_CPU}" == "ARM" ]; then + mkdir -p ${TARGET_ROOT}/raw/output/ + if [ "${TARGET_IP}" != "" ]; then # Network case + LISTING=`ssh root@${TARGET_IP} "ls /root/raw/" | grep "^[0-9][0-9]" | tr '\r' ' ' | tr '\n' ' '` + for file in ${LISTING} + do + echo "Copying ${file} from device to ${TARGET_ROOT}/raw/output/" + scp root@${TARGET_IP}:raw/${file} ${TARGET_ROOT}/raw/output/ + done + elif [ "${ROOTFS_DIR}" != "" ]; then # SD Card case + LISTING=`ls ${ROOTFS_DIR}/root/raw/ | grep "^[0-9][0-9]" | tr '\r' ' ' | tr '\n' ' '` + for file in ${LISTING} + do + echo "Copying ${file} from device to ${TARGET_ROOT}/raw/output/" + ${SUDO} cp ${ROOTFS_DIR}/raw/${file} ${TARGET_ROOT}/raw/output/ + done + else + echo "For network pull: set TARGET_IP variable." + echo "For SD card pull: set ROOTFS_DIR variable." + exit 0 + fi + fi + fi + if [ "${1}" == "convert" ]; then + LISTING=`ls ${TARGET_ROOT}/raw/output | grep "^[0-9][0-9]_bitimg" | tr '\r' ' ' | tr '\n' ' '` + for file in ${LISTING} + do + echo "Converting ${file}" + modfile=`echo ${file} | sed "s/bitimg/img/"` + ${TARGET_ROOT}/out/LINUX/ARM/bitimg2img ${TARGET_ROOT}/raw/output/${file} ${TARGET_ROOT}/raw/output/${modfile} + done + fi + if [ "${1}" == "docs" ]; then + export PUBLIC_LIB_HEADER_LIST=" ${TARGET_ROOT}/libraries/public/yuv/include/yuv/dvp_kl_yuv.h + ${TARGET_ROOT}/libraries/public/imgfilter/include/imgfilter/dvp_kl_imgfilter.h + ${TARGET_ROOT}/libraries/public/ocl/include/ocl/dvp_kl_ocl.h + ${TARGET_ROOT}/libraries/public/vrun/include/vrun/dvp_kl_vrun.h" + export PRIVATE_LIB_HEADER_LIST="${VISION_ROOT}/libraries/protected/imglib/include/imglib/dvp_kl_imglib.h + ${VISION_ROOT}/libraries/protected/vlib/include/vlib/dvp_kl_vlib.h + ${VISION_ROOT}/libraries/protected/rvm/include/rvm/dvp_kl_rvm.h + ${VISION_ROOT}/libraries/protected/tismo/include/tismo/dvp_kl_tismo.h" + export LIBHEADERS= + export doxygen_status=`dpkg-query -W -f='${Status}\n' doxygen` + export graphviz_status=`dpkg-query -W -f='${Status}\n' graphviz` + export mscgen_status=`dpkg-query -W -f='${Status}\n' mscgen` + if [ "$doxygen_status" == "install ok installed" ] && + [ "$graphviz_status" == "install ok installed" ] && + [ "$mscgen_status" == "install ok installed" ]; then + pushd ${TARGET_ROOT} + export COMMIT=`git describe --tags --dirty` + cp docs/dvp_sdk.txt docs/dvp_sdk.bak + sed -i "s/VERSION/${COMMIT}/" docs/dvp_sdk.txt + sed -i "s/DATE/`date`/" docs/dvp_sdk.txt + export PREDEF="PREDEFINED += LINUX DVP_USE_BO" + + # Only include the headers that exist from vision_prebuilt + for i in ${PRIVATE_LIB_HEADER_LIST}; do + if [ -f ${i} ]; then + LIBHEADERS+="${i} "; + echo "Library Header File Found: ${i}"; + PREDEF+=" `echo ${i} | sed 's/.*dvp_kl_\([a-z]*\).h/DVP_USE_\U\1/'` "; + fi + done + scripts/kernel_doc.pl docs/dvp_kernel_autogen.txt ${TARGET_ROOT}/include/dvp/dvp_types.h ${LIBHEADERS} ${PUBLIC_LIB_HEADER_LIST} + (cat docs/full/Doxyfile ; echo "PROJECT_NUMBER = \"DVP project git tag: \" $COMMIT" ; echo $PREDEF; \ + echo "INPUT+= ${LIBHEADERS}") | doxygen - + #doxygen docs/DoxyRules + mv docs/dvp_sdk.bak docs/dvp_sdk.txt + popd + echo "Look in ${TARGET_ROOT}/docs/ for the generated documentation" + else + echo "A required package is not installed on your machine!" + echo "To generate ${TARGET_PROJ} docs, install the package (sudo apt-get install ) and re-run this option." + fi + fi + if [ "${1}" == "debug" ]; then + for i in $TARGET_TEST; do + get_symbols ${i} bin + done + for i in $TARGET_LIBS; do + get_symbols lib${i}.so lib + done + fi + if [ "${1}" == "gdb" ] || [ "${1}" == "ddd" ]; then + TYPE=${1} + PROCESS=${2} + shift # Remove "gdb" + shift # Remove "process" + if [ "${TARGET_IP}" != "" ]; then + if [ "${TARGET_CPU}" == "ARM" ]; then # Network case + ssh root@${TARGET_IP} "gdbserver :5039 ${PROCESS} $*" & + cat > gdb_cmds.txt << EOF +set solib-absolute-prefix ${OUT_DIR} +set solib-search-path ${OUT_DIR} +target remote ${TARGET_IP}:5039 +EOF + if [ "${TYPE}" == "gdb" ]; then + arm-none-linux-gnueabi-gdb ${OUT_DIR}/${PROCESS} --command=gdb_cmds.txt + fi + if [ "${TYPE}" == "ddd" ]; then + ddd --debugger arm-none-linux-gnueabi-gdb -command gdb_cmds.txt ${OUT_DIR}/${PROCESS} & + fi + #rm gdb_cmds.txt + exit + else + echo "Unknown target cpu!" + exit 0 + fi + else # Local CPU Case + export SRC_DIRS=${TARGET_ROOT} + for src in `find ${TARGET_ROOT}/source -type d | tr '\r' ' ' | tr '\n' ' '`; do + export SRC_DIRS="${SRC_DIRS}:${src}" + done + export OBJ_DIRS=${TARGET_ROOT} + for lib in `echo ${LD_LIBRARY_PATH} | tr ':' ' '`; do + for obj in `find ${lib} -type d | tr '\r' ' ' | tr '\n' ' '`; do + export OBJ_DIRS="${OBJ_DIRS}:${obj}" + done + done + cat > gdb_cmds.txt << EOF +set solib-absolute-prefix ${OUT_DIR} +set solib-search-path ${OUT_DIR} +directory ${SRC_DIRS} +path ${OBJ_DIRS} +EOF + if [ "${TYPE}" == "gdb" ]; then + gdb --command gdb_cmds.txt ${OUT_DIR}/$PROCESS + fi + if [ "${TYPE}" == "ddd" ]; then + ddd --gdb --command gdb_cmds.txt ${OUT_DIR}/$PROCESS & + fi + exit + fi + fi + if [ "${1}" == "zones" ] || [ "${1}" == "zone" ]; then + if [ -n "${2}" ]; then + zone_mask $2 + shift + fi + zone_mask print + fi + if [ "${1}" == "run" ]; then + if [ -n "${2}" ]; then + PROCESS=${2} + shift + shift + if [ "${TARGET_CPU}" == "ARM" ]; then + if [ "${TARGET_IP}" != "" ]; then # Network case + ssh root@${TARGET_IP} ${PROCESS} $* + else + echo "For network run: set TARGET_IP variable." + exit 0 + fi + else + ${OUT_DIR}/${PROCESS} $* + exit + fi + fi + fi + if [ "${1}" == "shell" ]; then + if [ "${TARGET_CPU}" == "ARM" ]; then + if [ "${TARGET_IP}" != "" ]; then # Network case + ssh root@${TARGET_IP} + fi + fi + fi + shift +done diff --git a/scripts/dvp_qnx.sh b/scripts/dvp_qnx.sh new file mode 100755 index 0000000..d30be3a --- /dev/null +++ b/scripts/dvp_qnx.sh @@ -0,0 +1,289 @@ +#!/bin/bash + +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +function target_ip() { + + if [ -z ${PB_TARGET_IP} ]; then + + if [ -z "`usb-devices | grep \"RIM Network Device\"`" ]; then + echo "ERROR: PlayBook not found!" + exit 0 + fi + PB_HOST_IP=`ifconfig usb0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'` + PB_TARGET_IP1=`echo ${PB_HOST_IP} | cut -d. -f1` + PB_TARGET_IP2=`echo ${PB_HOST_IP} | cut -d. -f2` + PB_TARGET_IP3=`echo ${PB_HOST_IP} | cut -d. -f3` + PB_TARGET_IP4=`echo ${PB_HOST_IP} | cut -d. -f4` + PB_TARGET_IP4=`echo ${PB_TARGET_IP4} - 1 | bc` + PB_TARGET_IP=`echo ${PB_TARGET_IP1}.${PB_TARGET_IP2}.${PB_TARGET_IP3}.${PB_TARGET_IP4}` + if [ -z ${PB_TARGET_IP1} ]; then + echo "ERROR: PlayBook link not giving any IP address!" + exit 0 + fi + echo PlayBook IP is: ${PB_TARGET_IP} + fi +} + +if [ $# == 0 ]; then + echo "Usage: ${0} [docs|clean|mm|build|setup|remoteclean|install|videos|convert|test|baseimage]" + echo "" + echo " options: " + echo " docs - Uses Doxygen to generate the documentation from the code." + echo " setup - Installs your SSH public key for further loginless ssh operations." + echo " clean - Deletes previously built libraries & intermediate files on the host machine" + echo " remoteclean - Deletes previously libraries & intermediate files on the target device." + echo " build|mm - Builds entire ${TARGET_PROJECT} project" + echo " install - Installs successfully-built libraries and applications." + echo " test - Runs the ${TARGET_PROJECT} framework in various standalone test modes." + echo " baseimage - Installs the Ducati / Tesla binaries & the Syslink on the target device and reboot the target device." + echo " videos - Downloads processed video files from target device to DVP's root folder/raw on host machine" + echo " convert - " + echo "" + exit +fi + +export TARGET_PROJECT=DVP +export TARGET_ROOT=${DVP_ROOT} +export TARGET_LIBS="dvp dvp_kgm_cpu dvp_kgm_simcop dvp_kgm_dsp" +export TARGET_SLIB= +export TARGET_BINS= +export TARGET_TEST="dvp_simple dvp_demo dvp_test uinput_test sosal_test qnxscreen_test vcam_simple vcam_server" +export CROSS_COMPILE=ntoarmv7- + +if [ -z "${TARGET_ROOT}" ]; then + echo You must set your ${TARGET_PROJECT}_ROOT to the ${TARGET_PROJECT} build for QNX. + exit +fi + +export TARGET_OUT="${TARGET_ROOT}/out/__QNX__/ARM" + +while [ $# -gt 0 ]; +do + if [ "${1}" == "setup" ]; then + target_ip + if [ ! -f "${HOME}/.ssh/id_rsa.pub" ]; then + echo "ERROR: SSH public key NOT found" + exit 0 + fi + echo "Copying local SSH RSA public key to PlayBook" + scp ${TARGET_ROOT}/prebuilt/__QNX__/etc/ssh/sshd_config root@${PB_TARGET_IP}:/etc/ssh/ + scp ${HOME}/.ssh/id_rsa.pub root@${PB_TARGET_IP}:/etc/ssh/authorized_keys + echo "Done. Please restart your PlayBook for the changes to take effect." + exit 0 + fi + if [ "${1}" == "clean" ]; then + cd ${TARGET_ROOT} + make DEBUG=1 TARGET_PLATFORM=PLAYBOOK clean + fi + if [ "${1}" == "mm" ] || [ "${1}" == "build" ]; then + cd ${TARGET_ROOT} + make DEBUG=1 TARGET_PLATFORM=PLAYBOOK + fi + if [ "${1}" == "remoteclean" ]; then + target_ip + cd ${TARGET_ROOT} + for i in ${TARGET_BINS}; do + ssh root@${PB_TARGET_IP} "rm /usr/bin/${i}" + done + for i in ${TARGET_TEST}; do + ssh root@${PB_TARGET_IP} "rm /usr/bin/${i}" + done + for i in ${TARGET_LIBS}; do + ssh root@${PB_TARGET_IP} "rm /usr/lib/lib${i}.so" + done + ssh root@${PB_TARGET_IP} "rm /root/raw/*" + fi + if [ "${1}" == "install" ]; then + target_ip + echo Changing PlayBook filesystem permissions to Read/Write... + ssh root@${PB_TARGET_IP} mount -uw /base + if [ -z ${TARGET_OUT} ]; then + echo "ERROR(${1}): There's no recognizable build output folders found" + exit 0 + fi + cd ${TARGET_ROOT} + for i in ${TARGET_BINS}; do + echo Installing ${i} + scp ${TARGET_OUT}/${i} root@${PB_TARGET_IP}:/usr/bin/ + done + for i in ${TARGET_LIBS}; do + echo Installing lib${i}.so + scp ${TARGET_OUT}/lib${i}.so root@${PB_TARGET_IP}:/usr/lib/ + done + ssh root@${PB_TARGET_IP} mkdir -p /root/raw + fi + if [ "${1}" == "test" ]; then + target_ip + echo Changing PlayBook filesystem permissions to Read/Write... + ssh root@${PB_TARGET_IP} mount -uw /base + if [ -z ${TARGET_OUT} ]; then + echo "ERROR(${1}): There's no recognizable build output folders found" + exit 0 + fi + cd ${TARGET_ROOT} + for i in ${TARGET_TEST}; do + echo Installing ${i} + scp ${TARGET_OUT}/${i} root@${PB_TARGET_IP}:/usr/bin/ + done + fi + if [ "${1}" == "docs" ]; then + export doxygen_status=`dpkg-query -W -f='${Status}\n' doxygen` + if [ "${doxygen_status}" == "install ok installed" ]; then + pushd ${TARGET_ROOT} + doxygen docs/DoxyRules + popd + echo "Look in ${TARGET_ROOT}/docs/ for the generated documentation" + else + echo "doxygen package is not installed on your machine!" + echo "To generate ${TARGET_PROJECT} docs, install the package (sudo apt-get install doxygen) and re-run this option." + fi + fi + if [ "${1}" == "videos" ]; then + target_ip + LISTING=`ssh root@${PB_TARGET_IP} "ls /root/raw/" | grep "^[0-9][0-9]" | tr '\r' ' ' | tr '\n' ' '` + mkdir -p ${TARGET_ROOT}/raw/output/ + for file in ${LISTING} + do + echo "Copying ${file} from device to ${TARGET_ROOT}/raw/output/" + scp root@${PB_TARGET_IP}:raw/${file} ${TARGET_ROOT}/raw/output/ + done + fi + if [ "${1}" == "convert" ]; then + target_ip + LISTING=`ls ${TARGET_ROOT}/raw/output | grep "^[0-9][0-9]_bitimg" | tr '\r' ' ' | tr '\n' ' '` + for file in ${LISTING} + do + echo "Converting ${file}" + modfile=`echo ${file} | sed "s/bitimg/img/"` + ${TARGET_ROOT}/bin/bitimg2img ${TARGET_ROOT}/raw/output/${file} ${TARGET_ROOT}/raw/output/${modfile} + done + fi + if [ "${1}" == "unitest" ]; then + target_ip + ssh root@${PB_TARGET_IP} "sosal_test" + ssh root@${PB_TARGET_IP} "dvp_test" + fi + if [ "${1}" == "ip" ]; then + target_ip + fi + if [ "${1}" == "ducati" ]; then + target_ip + echo Changing PlayBook filesystem permissions to Read/Write... + ssh root@${PB_TARGET_IP} mount -uw /base + echo "Replacing Ducati Base Image" + #scp root@${PB_TARGET_IP}:/lib/firmware/ducati/base_image_app_m3.xem3 ${TARGET_ROOT}/prebuilt/__QNX__/. + scp ${TARGET_ROOT}/prebuilt/__QNX__/lib/firmware/ducati/base_image_app_m3.xem3 root@${PB_TARGET_IP}:/lib/firmware/ducati/ + fi + if [ "${1}" == "baseimage" ]; then + target_ip + echo Changing PlayBook filesystem permissions to Read/Write... + ssh root@${PB_TARGET_IP} mount -uw /base + + if [ -z "${QCONF_OVERRIDE}" ]; then + INSTALL_DIR=${QNX_TARGET} + else + INSTALL_DIR=`cat ${QCONF_OVERRIDE} | grep INSTALL_ROOT_nto | cut -d= -f2` + fi + + echo "Killing services before library updates (tiler mmsynclite syslink camera-omap)" + ssh root@${PB_TARGET_IP} slay tiler mmsynclite syslink camera-omap + echo "Loading Ducati Base Image" + scp ${TARGET_ROOT}/prebuilt/__QNX__/lib/firmware/ducati/*.xem3 root@${PB_TARGET_IP}:/lib/firmware/ducati/ + echo "Loading Tesla Base Image (TODO)" + echo "Loading binaries" + scp ${INSTALL_DIR}/armle-v7/sbin/tiler* root@${PB_TARGET_IP}:/sbin/ + scp ${INSTALL_DIR}/armle-v7/bin/camera-omap root@${PB_TARGET_IP}:/bin/ + scp ${INSTALL_DIR}/armle-v7/bin/syslink* root@${PB_TARGET_IP}:/bin/ + echo "Loading libraries" + ssh root@${PB_TARGET_IP} rm /usr/lib/libmemmgr* /usr/lib/libtiler* /usr/lib/lib[Ss]yslink* /usr/lib/libdce.so* /usr/lib/libaoi.so* /usr/lib/librocket.so* /usr/lib/libcamdrv.so* + scp ${INSTALL_DIR}/armle-v7/usr/lib/libmmfomx.so* root@${PB_TARGET_IP}:/usr/lib/ + scp ${INSTALL_DIR}/armle-v7/usr/lib/libdce.so* root@${PB_TARGET_IP}:/usr/lib/ + scp ${INSTALL_DIR}/armle-v7/usr/lib/libOMX*.so* root@${PB_TARGET_IP}:/usr/lib/ + scp ${INSTALL_DIR}/armle-v7/usr/lib/libdomx.so* root@${PB_TARGET_IP}:/usr/lib/ + scp ${INSTALL_DIR}/armle-v7/usr/lib/libmmosal.so* root@${PB_TARGET_IP}:/usr/lib/ + scp ${INSTALL_DIR}/armle-v7/usr/lib/libaoi.so* root@${PB_TARGET_IP}:/usr/lib/ + scp ${INSTALL_DIR}/armle-v7/usr/lib/lib[Ss]yslink*.so* root@${PB_TARGET_IP}:/usr/lib/ + scp ${INSTALL_DIR}/armle-v7/usr/lib/libtilerusr.so* root@${PB_TARGET_IP}:/usr/lib/ + scp ${INSTALL_DIR}/armle-v7/usr/lib/libmemmgr*.so* root@${PB_TARGET_IP}:/usr/lib/ + scp ${INSTALL_DIR}/armle-v7/usr/lib/libcamdrv.so* root@${PB_TARGET_IP}:/usr/lib/ + scp ${INSTALL_DIR}/armle-v7/usr/lib/librocket.so* root@${PB_TARGET_IP}:/usr/lib/ + echo "Done. Please restart your PlayBook for the changes to take effect." + fi + if [ "${1}" == "cores" ]; then + target_ip + rm ${TARGET_ROOT}/out/*.core + export CORE_LOC="/root /var/log" + for loc in ${CORE_LOC}; do + CORES=`ssh root@${PB_TARGET_IP} "cd ${loc} && ls *.core" | tr '\r' ' ' | tr '\n' ' '` + echo ${CORES} + for file in ${CORES} + do + echo "Copying file ${file} to PC" + scp root@${PB_TARGET_IP}:${loc}/${file} ${TARGET_ROOT}/out/ + done + ssh root@${PB_TARGET_IP} "rm ${loc}/*.core" + done + fi + if [ "${1}" == "debug" ]; then + OBJOPT="-C -d -g -f -l -S --include=${TARGET_ROOT}" + echo Outputing Obj-Dump info on ${TARGET_PROJECT} objects + for i in ${TARGET_BINS}; do + ${CROSS_COMPILE}objdump ${OBJOPT} ${TARGET_OUT}/${i} > ${TARGET_ROOT}/out/${i}.txt + done + for i in ${TARGET_TEST}; do + ${CROSS_COMPILE}objdump ${OBJOPT} ${TARGET_OUT}/${i} > ${TARGET_ROOT}/out/${i}.txt + done + for i in ${TARGET_LIBS}; do + ${CROSS_COMPILE}objdump ${OBJOPT} ${TARGET_OUT}/lib${i}.so > ${TARGET_ROOT}/out/lib${i}.txt + done + fi + if [ "${1}" == "gdb" ]; then + target_ip + # The GDB already knows the ${QNX_TARGET}/armle-v7 path + cat > ${TARGET_OUT}/gdb_cmds.txt << EOF +set solib-search-path ${TARGET_OUT} +EOF + ntoarm-gdb -cd=${TARGET_OUT} -x gdb_cmds.txt --readnow --exec=${TARGET_OUT}/${2} --core=${TARGET_ROOT}/out/${2}.core + fi + if [ "${1}" == "shell" ]; then + target_ip + if [ -z "${2}" ]; then + ssh root@${PB_TARGET_IP} + else + shift # eat ${1} + echo "Executing ${*} as command" + ssh root@${PB_TARGET_IP} "$*" + fi + fi + if [ "${1}" == "vcam_server" ]; then + target_ip + ssh -N -f root@${PB_TARGET_IP} -L 8501:localhost:8501 -L 8502:localhost:8502 + ssh root@${PB_TARGET_IP} vcam_server & + fi + if [ "${1}" == "tunnel" ]; then + target_ip + ssh -N -f root@${PB_TARGET_IP} -L 8501:localhost:8501 -L 8502:localhost:8502 + fi + if [ "${1}" == "zones" ] || [ "${1}" == "zone" ]; then + if [ -n "${2}" ]; then + zone_mask ${2} + shift + fi + zone_mask print + fi + shift +done + diff --git a/scripts/dvp_test.sh b/scripts/dvp_test.sh new file mode 100755 index 0000000..891f91e --- /dev/null +++ b/scripts/dvp_test.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if [ -n "${MYDROID}" ]; then + . dvp_test_android.sh $* +fi + +if [ -n "${QNX_TARGET}" ]; then + . dvp_test_qnx.sh $* +fi + +if [ -z "${MYDROID}" ] && [ -z "${QNX_TARGET}" ]; then + . dvp_test_linux.sh $* +fi diff --git a/scripts/dvp_test_android.sh b/scripts/dvp_test_android.sh new file mode 100755 index 0000000..2a01c90 --- /dev/null +++ b/scripts/dvp_test_android.sh @@ -0,0 +1,159 @@ +#!/bin/bash + +# Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if [ "${MYDROID}" == "" ]; then + echo You must set your path to the Android Build in MYDROID. + exit +fi + +if [ $# == 0 ]; then + echo "Usage: dvp_test.sh [setup|clean|full|library graph|simcop|dsp|cpu|report]" + echo " setup: Compile and load the test and required input files." + echo " clean: Clean the previous run output files from the target and local pc" + echo " full: By default, only QQVGA resolution is run, with 'full' enabled," + echo " then QVGA and VGA resolutions are run as well" + echo " library graph: one of the following options: vrun|imglib|vlib|rvm|tismo" + echo " report: Report the results of the binary comparisons at the output." + exit +fi + +if [ -z "${TI_HW_ROOT}" ]; then + export TI_HW_ROOT=hardware/ti +fi + +export DVP_ROOT=${MYDROID}/${TI_HW_ROOT}/dvp + +function get_devices() { + if [ -z "${TARGET_DEVICE}" ]; then + NUM_DEV=`adb devices | grep -E "^[0-9A-Fa-f]+" | awk '{print $1}' | wc -l` + if [ "${NUM_DEV}" == "1" ]; then + export TARGET_DEVICE=`adb devices | grep -E "^[0-9A-Fa-f]+" | awk '{print $1}'` + elif [ "${NUM_DEV}" -gt "1" ]; then + echo "You must set your TARGET_DEVICE to the serial number of the device to program. You have ${NUM_DEV} devices connected now!" + exit + else + echo "You must have a device plugged in to use ADB" + exit + fi + fi +} + +function remote_clean() { + adb -s ${TARGET_DEVICE} shell "rm /sdcard/raw/0* /sdcard/raw/1* /sdcard/raw/2* /sdcard/raw/3* /sdcard/raw/4* /sdcard/raw/5* /sdcard/raw/6*" +} + +if [[ "$@" =~ "full" ]]; then + export DVP_TEST_FULL=1 +fi +if [[ "$@" =~ "vrun" ]]; then + export DVP_TEST_GRAPH_NUM=7 + export DVP_TEST_GRAPH_STR="vrun" +fi +if [[ "$@" =~ "imglib" ]]; then + export DVP_TEST_GRAPH_NUM=16 + export DVP_TEST_GRAPH_STR="imglib" +fi +if [[ "$@" =~ "vlib" ]]; then + export DVP_TEST_GRAPH_NUM=22 + export DVP_TEST_GRAPH_STR="vlib" +fi +if [[ "$@" =~ "rvm" ]]; then + export DVP_TEST_GRAPH_NUM=1 + export DVP_TEST_GRAPH_STR="rvm" +fi + +while [ $# -gt 0 ]; +do + get_devices + if [ "$1" == "setup" ]; then + # Connect ADB, Compile, install + . $DVP_ROOT/scripts/dvp.sh setup logcat zone dvptest clean mm install test + + #Load RVM binary + echo Installing rvm_generate_lut_ARM + adb -s ${TARGET_DEVICE} push ${ANDROID_PRODUCT_OUT}/system/bin/rvm_generate_lut_ARM /system/bin/rvm_generate_lut + + #Load input videos + adb -s ${TARGET_DEVICE} push $DVP_ROOT/raw/input/handqqvga_160x120_30Hz_UYVY.yuv /sdcard/raw/. + adb -s ${TARGET_DEVICE} push $DVP_ROOT/raw/input/handqvga_320x240_30Hz_UYVY.yuv /sdcard/raw/. + adb -s ${TARGET_DEVICE} push $DVP_ROOT/raw/input/handvga_640x480_30Hz_UYVY.yuv /sdcard/raw/. + adb -s ${TARGET_DEVICE} push $DVP_ROOT/raw/input/hand4Xvga_1280x960_30Hz_UYVY.yuv /sdcard/raw/. +# adb -s ${TARGET_DEVICE} push $DVP_ROOT/raw/input/rvm_lut_320x240_to_320x240_BL64.bin /sdcard/raw/. + adb -s ${TARGET_DEVICE} push $DVP_ROOT/raw/input/rvm_calib_160x120_to_160x120.txt /sdcard/raw/. + adb -s ${TARGET_DEVICE} push $DVP_ROOT/raw/input/rvm_calib_320x240_to_320x240.txt /sdcard/raw/. + adb -s ${TARGET_DEVICE} push $DVP_ROOT/raw/input/rvm_calib_640x480_to_640x480.txt /sdcard/raw/. +# adb -s ${TARGET_DEVICE} push $DVP_ROOT/raw/input/rvm_calib_1280x960_to_1280x960.txt /sdcard/raw/. + + #Prepare output directory + mkdir -p $DVP_ROOT/raw/output + + #Open the output log + echo "**********************************************************" > regression_results.txt + echo "******************** TEST RESULTS ************************" >> regression_results.txt + echo "**********************************************************" >> regression_results.txt + echo >> regression_results.txt + fi + + if [ "$1" == "simcop" ] || [ "$1" == "dsp" ] || [ "$1" == "cpu" ]; then + + #QQVGA Test + remote_clean + echo TESTING ${DVP_TEST_GRAPH_STR} on $1 at QQVGA + adb -s ${TARGET_DEVICE} shell "cd /sdcard && dvp_test handqqvga 160 120 30 UYVY 10 $DVP_TEST_GRAPH_NUM $1" + $DVP_ROOT/scripts/dvp.sh videos + + if [ $DVP_TEST_FULL ]; then + #QVGA Test + remote_clean + echo TESTING ${DVP_TEST_GRAPH_STR} on $1 at QVGA + adb -s ${TARGET_DEVICE} shell "cd /sdcard && dvp_test handqvga 320 240 30 UYVY 2 $DVP_TEST_GRAPH_NUM $1" + $DVP_ROOT/scripts/dvp.sh videos + + #VGA Test + remote_clean + echo TESTING ${DVP_TEST_GRAPH_STR} on $1 at VGA + adb -s ${TARGET_DEVICE} shell "cd /sdcard && dvp_test handvga 640 480 30 UYVY 2 $DVP_TEST_GRAPH_NUM $1" + $DVP_ROOT/scripts/dvp.sh videos + + #4xVGA Test + #remote_clean + #echo TESTING ${DVP_TEST_GRAPH_STR} on $1 at 4xVGA + #adb -s ${TARGET_DEVICE} shell "cd /sdcard && dvp_test hand4Xvga 1280 960 30 UYVY 2 $DVP_TEST_GRAPH_NUM $1" + #$DVP_ROOT/scripts/dvp.sh videos + fi + . $DVP_ROOT/scripts/dvp.sh convert + + echo RESULTS of ${DVP_TEST_GRAPH_STR} on $1 at QQVGA >> regression_results.txt + $DVP_ROOT/bin/imgDiff $DVP_ROOT/raw/ref/$DVP_TEST_GRAPH_STR/qqvga/ $DVP_ROOT/raw/output/ $DVP_ROOT/raw/ref/${DVP_TEST_GRAPH_STR}_reference_config.txt 10 0 >> regression_results.txt + if [ $DVP_TEST_FULL ]; then + echo RESULTS of ${DVP_TEST_GRAPH_STR} on $1 at QVGA >> regression_results.txt + $DVP_ROOT/bin/imgDiff $DVP_ROOT/raw/ref/$DVP_TEST_GRAPH_STR/qvga/ $DVP_ROOT/raw/output/ $DVP_ROOT/raw/ref/${DVP_TEST_GRAPH_STR}_reference_config.txt 2 0 >> regression_results.txt + echo RESULTS of ${DVP_TEST_GRAPH_STR} on $1 at VGA >> regression_results.txt + $DVP_ROOT/bin/imgDiff $DVP_ROOT/raw/ref/$DVP_TEST_GRAPH_STR/vga/ $DVP_ROOT/raw/output/ $DVP_ROOT/raw/ref/${DVP_TEST_GRAPH_STR}_reference_config.txt 2 0 >> regression_results.txt + #echo RESULTS of ${DVP_TEST_GRAPH_STR} on $1 at 4xVGA >> regression_results.txt + #$DVP_ROOT/bin/imgDiff $DVP_ROOT/raw/ref/$DVP_TEST_GRAPH_STR/4xvga/ $DVP_ROOT/raw/output/ $DVP_ROOT/raw/ref/${DVP_TEST_GRAPH_STR}_reference_config.txt 2 0 >> regression_results.txt + fi + echo >> regression_results.txt + fi + if [ "$1" == "report" ]; then + cat regression_results.txt + fi + if [ "$1" == "clean" ]; then + remote_clean + rm $DVP_ROOT/raw/output/0* $DVP_ROOT/raw/output/1* $DVP_ROOT/raw/output/2* $DVP_ROOT/raw/output/3* $DVP_ROOT/raw/output/4* $DVP_ROOT/raw/output/5* $DVP_ROOT/raw/output/6* + fi + shift +done diff --git a/scripts/dvp_test_linux.sh b/scripts/dvp_test_linux.sh new file mode 100755 index 0000000..1b76699 --- /dev/null +++ b/scripts/dvp_test_linux.sh @@ -0,0 +1,134 @@ +#!/bin/bash + +# Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +function move_videos { + LISTING=`ls raw/ | grep "^[0-9][0-9]" | tr '\r' ' ' | tr '\n' ' '` + for file in ${LISTING}; + do + mv raw/$file raw/output/ + done +} + +if [ $# == 0 ]; then + echo "Usage: dvp_test.sh [setup|clean|full|library graph|simcop|dsp|cpu|report]" + echo " setup: Compile and load the test and required input files." + echo " clean: Clean the previous run output files from the target and local pc" + echo " full: By default, only QQVGA resolution is run, with 'full' enabled," + echo " then QVGA and VGA resolutions are run as well" + echo " library graph: one of the following options: vrun|imglib|vlib|rvm|tismo" + echo " report: Report the results of the binary comparisons at the output." + exit +fi + +if [ -z "${DVP_ROOT}" ]; then + echo "DVP_ROOT must be set" + exit +fi + +if [[ "$@" =~ "full" ]]; then + export DVP_TEST_FULL=1 +fi +if [[ "$@" =~ "vrun" ]]; then + export DVP_TEST_GRAPH_NUM=7 + export DVP_TEST_GRAPH_STR="vrun" +fi +if [[ "$@" =~ "imglib" ]]; then + export DVP_TEST_GRAPH_NUM=16 + export DVP_TEST_GRAPH_STR="imglib" +fi +if [[ "$@" =~ "vlib" ]]; then + export DVP_TEST_GRAPH_NUM=22 + export DVP_TEST_GRAPH_STR="vlib" +fi +if [[ "$@" =~ "rvm" ]]; then + export DVP_TEST_GRAPH_NUM=1 + export DVP_TEST_GRAPH_STR="rvm" +fi + +pushd ${DVP_ROOT} + +while [ $# -gt 0 ]; +do + if [ "$1" == "setup" ]; then + make clean + make -j3 + make install + + #Prepare output directory + mkdir $DVP_ROOT/raw/output + + #Open the output log + echo "**********************************************************" > regression_results.txt + echo "******************** TEST RESULTS ************************" >> regression_results.txt + echo "**********************************************************" >> regression_results.txt + echo >> regression_results.txt + fi + + if [ "$1" == "simcop" ] || [ "$1" == "dsp" ] || [ "$1" == "cpu" ]; then + + #QQVGA Test + rm raw/0* raw/1* raw/2* raw/3* raw/4* raw/5* raw/6* + echo TESTING ${DVP_TEST_GRAPH_STR} on $1 at QQVGA + dvp_test handqqvga 160 120 30 UYVY 10 $DVP_TEST_GRAPH_NUM $1 + move_videos + + if [ $DVP_TEST_FULL ]; then + #QVGA Test + rm raw/0* raw/1* raw/2* raw/3* raw/4* raw/5* raw/6* + echo TESTING ${DVP_TEST_GRAPH_STR} on $1 at QVGA + dvp_test handqvga 320 240 30 UYVY 2 $DVP_TEST_GRAPH_NUM $1 + move_videos + + #VGA Test + rm raw/0* raw/1* raw/2* raw/3* raw/4* raw/5* raw/6* + echo TESTING ${DVP_TEST_GRAPH_STR} on $1 at VGA + dvp_test handvga 640 480 30 UYVY 2 $DVP_TEST_GRAPH_NUM $1 + move_videos + + #4xVGA Test + # rm raw/0* raw/1* raw/2* raw/3* raw/4* raw/5* raw/6* + #echo TESTING ${DVP_TEST_GRAPH_STR} on $1 at 4xVGA + # dvp_test hand4Xvga 1280 960 30 UYVY 2 $DVP_TEST_GRAPH_NUM $1 + # move_videos + fi + . $DVP_ROOT/scripts/dvp.sh convert + + echo RESULTS of ${DVP_TEST_GRAPH_STR} on $1 at QQVGA >> regression_results.txt + $DVP_ROOT/out/LINUX/ARM/imgDiff $DVP_ROOT/raw/ref/${DVP_TEST_GRAPH_STR}/qqvga/ $DVP_ROOT/raw/output/ $DVP_ROOT/raw/ref/${DVP_TEST_GRAPH_STR}_reference_config.txt 10 0 >> regression_results.txt + if [ $DVP_TEST_FULL ]; then + echo RESULTS of ${DVP_TEST_GRAPH_STR} on $1 at QVGA >> regression_results.txt + $DVP_ROOT/out/LINUX/ARM/imgDiff $DVP_ROOT/raw/ref/${DVP_TEST_GRAPH_STR}/qvga/ $DVP_ROOT/raw/output/ $DVP_ROOT/raw/ref/${DVP_TEST_GRAPH_STR}_reference_config.txt 2 0 >> regression_results.txt + echo RESULTS of ${DVP_TEST_GRAPH_STR} on $1 at VGA >> regression_results.txt + $DVP_ROOT/out/LINUX/ARM/imgDiff $DVP_ROOT/raw/ref/${DVP_TEST_GRAPH_STR}/vga/ $DVP_ROOT/raw/output/ $DVP_ROOT/raw/ref/${DVP_TEST_GRAPH_STR}_reference_config.txt 2 0 >> regression_results.txt + #echo RESULTS of ${DVP_TEST_GRAPH_STR} on $1 at 4xVGA >> regression_results.txt + #$DVP_ROOT/bin/imgDiff $DVP_ROOT/raw/ref/${DVP_TEST_GRAPH_STR}/4xvga/ $DVP_ROOT/raw/output/ $DVP_ROOT/raw/ref/${DVP_TEST_GRAPH_STR}_reference_config.txt 2 0 >> regression_results.txt + fi + echo >> regression_results.txt + fi + if [ "$1" == "report" ]; then + cat regression_results.txt + fi + if [ "$1" == "move" ]; then + move_videos + fi + if [ "$1" == "clean" ]; then + rm $DVP_ROOT/raw/0* $DVP_ROOT/raw/1* $DVP_ROOT/raw/2* $DVP_ROOT/raw/3* $DVP_ROOT/raw/4* $DVP_ROOT/raw/5* $DVP_ROOT/raw/6* + rm $DVP_ROOT/raw/output/0* $DVP_ROOT/raw/output/1* $DVP_ROOT/raw/output/2* $DVP_ROOT/raw/output/3* $DVP_ROOT/raw/output/4* $DVP_ROOT/raw/output/5* $DVP_ROOT/raw/output/6* + fi + shift +done + +popd diff --git a/scripts/dvp_test_qnx.sh b/scripts/dvp_test_qnx.sh new file mode 100755 index 0000000..67f2a46 --- /dev/null +++ b/scripts/dvp_test_qnx.sh @@ -0,0 +1,125 @@ +#!/bin/bash + +# Copyright (C) 2011 Texas Insruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if [ "$DVP_ROOT" == "" ]; then + echo You must DVP_ROOT environment variable. + exit +fi + +if [ $# == 0 ]; then + echo "Usage: dvp_test_qnx.sh [setup|clean|imx|dsp|cpu|full|check]" + exit +fi + +if [ -z "`usb-devices | grep \"RIM Network Device\"`" ]; then + echo "ERROR: PlayBook not found!" + exit 0 +fi + +PB_HOST_IP=`ifconfig usb0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'` + +PB_TARGET_IP1=`echo $PB_HOST_IP | cut -d. -f1` +PB_TARGET_IP2=`echo $PB_HOST_IP | cut -d. -f2` +PB_TARGET_IP3=`echo $PB_HOST_IP | cut -d. -f3` +PB_TARGET_IP4=`echo $PB_HOST_IP | cut -d. -f4` +PB_TARGET_IP4=`echo ${PB_TARGET_IP4} - 1 | bc` +PB_TARGET_IP=`echo ${PB_TARGET_IP1}.${PB_TARGET_IP2}.${PB_TARGET_IP3}.${PB_TARGET_IP4}` + +if [ -z $PB_TARGET_IP1 ]; then + echo "ERROR: PlayBook link not giving any IP address!" + exit 0 +fi + +export CPUS=`cat /proc/cpuinfo | grep processor | wc -l` + +while [ $# -gt 0 ]; +do + if [ "$1" == "setup" ]; then + # Compile, install + export DVP_DEBUG=1 + export DVP_ZONE_MASK=0x10203 + $DVP_ROOT/scripts/dvp_qnx.sh clean mm install test + + #Load input videos + scp $DVP_ROOT/raw/input/handqqvga_160x120_30Hz_UYVY.yuv root@${PB_TARGET_IP}:/root/raw/. + scp $DVP_ROOT/raw/input/handqvga_320x240_30Hz_UYVY.yuv root@${PB_TARGET_IP}:/root/raw/. + scp $DVP_ROOT/raw/input/handvga_640x480_30Hz_UYVY.yuv root@${PB_TARGET_IP}:/root/raw/. + scp $DVP_ROOT/raw/input/hand4Xvga_1280x960_30Hz_UYVY.yuv root@${PB_TARGET_IP}:/root/raw/. + + #Prepare output directory + mkdir $DVP_ROOT/raw/output + fi + + if [ "$1" == "imx" ] || [ "$1" == "dsp" ] || [ "$1" == "cpu" ]; then + + if [ "$1" == "imx" ]; then + export DVP_TEST_CORE=7 + fi + if [ "$1" == "dsp" ]; then + export DVP_TEST_CORE=8 + fi + if [ "$1" == "cpu" ]; then + export DVP_TEST_CORE=9 + fi + + #QQVGA Test + ssh root@${PB_TARGET_IP} "rm /root/raw/0* /root/raw/1* /root/raw/2* /root/raw/3*" + ssh root@${PB_TARGET_IP} "dvp_test handqqvga 160 120 30 UYVY 10 $DVP_TEST_CORE" + $DVP_ROOT/scripts/dvp_qnx.sh videos + + if [ "$2" == "full" ] || [ $DVP_TEST_FULL ]; then + #QVGA Test + ssh root@${PB_TARGET_IP} "rm /root/raw/0* /root/raw/1* /root/raw/2* /sdcard/raw/3*" + ssh root@${PB_TARGET_IP} "dvp_test handqvga 320 240 30 UYVY 2 $DVP_TEST_CORE" + $DVP_ROOT/scripts/dvp_qnx.sh videos + + #VGA Test + ssh root@${PB_TARGET_IP} "rm /root/raw/0* /root/raw/1* /root/raw/2* /sdcard/raw/3*" + ssh root@${PB_TARGET_IP} "dvp_test handvga 640 480 30 UYVY 2 $DVP_TEST_CORE" + $DVP_ROOT/scripts/dvp_qnx.sh videos + + #4xVGA Test + ssh root@${PB_TARGET_IP} "rm /root/raw/0* /root/raw/1* /root/raw/2* /sdcard/raw/3*" + #ssh root@${PB_TARGET_IP} "dvp_test hand4Xvga 1280 960 30 UYVY 2 $DVP_TEST_CORE" + #$DVP_ROOT/scripts/dvp_qnx.sh videos + fi + $DVP_ROOT/scripts/dvp_qnx.sh convert + fi + if [ "$1" == "full" ]; then + export DVP_TEST_FULL=1 + fi + if [ "$1" == "check" ]; then + echo "**********************************************************" + echo "******************** TEST RESULTS ************************" + echo "**********************************************************" + echo + echo QQVGA + $DVP_ROOT/bin/imgDiff $DVP_ROOT/raw/ref/qqvga/ $DVP_ROOT/raw/output/ $DVP_ROOT/raw/ref/reference_config.txt 10 + if [ "$2" == "full" ] || [ $DVP_TEST_FULL ]; then + echo QVGA + $DVP_ROOT/bin/imgDiff $DVP_ROOT/raw/ref/qvga/ $DVP_ROOT/raw/output/ $DVP_ROOT/raw/ref/reference_config.txt 2 + echo VGA + $DVP_ROOT/bin/imgDiff $DVP_ROOT/raw/ref/vga/ $DVP_ROOT/raw/output/ $DVP_ROOT/raw/ref/reference_config.txt 2 + #echo 4xVGA + #$DVP_ROOT/bin/imgDiff $DVP_ROOT/raw/ref/4xvga/ $DVP_ROOT/raw/output/ $DVP_ROOT/raw/ref/reference_config.txt 2 + fi + fi + if [ "$1" == "clean" ]; then + rm $DVP_ROOT/raw/output/0* $DVP_ROOT/raw/output/1* $DVP_ROOT/raw/output/2* $DVP_ROOT/raw/output/3* + fi + shift +done + diff --git a/scripts/env.bat b/scripts/env.bat new file mode 100755 index 0000000..d890de5 --- /dev/null +++ b/scripts/env.bat @@ -0,0 +1,21 @@ +@ECHO OFF + +@REM Copyright (C) 2011 Texas Insruments, Inc. +@REM +@REM Licensed under the Apache License, Version 2.0 (the "License"); +@REM you may not use this file except in compliance with the License. +@REM You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. + +SET DVP_DEBUG=1 +SET DVP_ZONE_MASK=0x00000003 +SET SOSAL_DEBUG=1 +SET SOSAL_ZONE_MASK=0x3 + diff --git a/scripts/env.sh b/scripts/env.sh new file mode 100755 index 0000000..7495ca9 --- /dev/null +++ b/scripts/env.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if [ -n "$QNX_TARGET" ]; then + if [ -z "$IPC_ROOT" ]; then + echo Must set IPC_ROOT + fi + if [ -z "$TILER_ROOT" ]; then + echo Must set TILER_ROOT + fi + env | grep QNX + echo Use TARGET_PLATFORM=PLAYBOOK on the make line to build for QNX. +fi +if [ -n "$MYDROID" ]; then + # Nothing... the Android Build has defaults + echo Android Build has default values already. +fi +if [ -z "$QNX_TARGET" ] && [ -z "$MYDROID" ]; then + # This is a PC build of some sort. + export TARGET_CPU=`uname -m` + export TARGET_PLATFORM=PC + export DVP_DEBUG=1 + export DVP_ZONE_MASK=0x0003 + export SOSAL_DEBUG=1 + export SOSAL_ZONE_MASK=0x3 +fi + + diff --git a/scripts/kernel_doc.pl b/scripts/kernel_doc.pl new file mode 100755 index 0000000..726786a --- /dev/null +++ b/scripts/kernel_doc.pl @@ -0,0 +1,321 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# v01 J.Villarreal - Initial Release +# v02 J.Villarreal - Changes to support dvp removal of union +# v03 J.Villarreal - Changes to remove dependency on xls file, extract +# all necessary info from the code. +# v04 J.Villarreal - Changes to leave the type blank if it doesn't +# exist in the comments. +# v05 J.Villarreal - Adding GPU core + +use Cwd; + +$argc = @ARGV; +if ($argc < 1) { + die "\nusage: perl kernel_doc.pl \nversion: v05\n\n"; +} + +my %hash_enums = (); +my %hash_types = (); +my @headers; + +my $outFile = shift; +my $summary = shift; +my $errorlog = "error.log"; + +my $k; +my $j; +my $i; +my $m; +my $type; +my $data; +my $cpu; +my $dsp; +my $imx; +my $core = "\\ref DVP_CORE_"; +my $cmma1; +my $cmma2; +my $parseOrder; +my $endOrder; +my $libName; +my $libNameTmp; + +for( $k=3; $k<=$argc; $k++ ) { + push (@headers, shift); +} + +open(DOC, ">$outFile") || die("can't open file"); + +$dir = cwd; # Assume this is running from the DVP root directory. + +&parseHeader($summary, "^typedef enum _dvp_knode_e", "^} DVP_KernelNode_e"); #parse dvp_types.h +push(@endOrder, scalar @parseOrder); +push(@libName, "DVP Common Kernels"); +foreach $k (@headers) { + &parseHeader($k, "^enum {", "^};"); + push(@endOrder, scalar @parseOrder); + push(@libName, "$libNameTmp Library"); +} +open(ERLOG, ">$errorlog") || die("can't open file"); + +&parseKgm("$dir/source/dvp/dvp_kgm_cpu/dvp_kgm_cpu.c"); +&parseKgm("$dir/source/dvp/dvp_kgm_dsp/dvp_kgm_dsp.c"); +&parseKgm("$dir/source/dvp/dvp_kgm_simcop/dvp_kgm_simcop.c"); +&parseKgm("$dir/source/dvp/dvp_kgm_ocl/dvp_kgm_ocl.c"); +#&parseSummary($summary); + +close(ERLOG); + +print DOC "/*! \\page kernel_page\n +\\section kernel_table Kernel Status Tables +The following tables contains a subset of the information found in the \\ref DVP_KernelNode_e reference, +including all the available kernel enumerations, their associated DVP_KernelNode_t::data types, and +what cores they are available to run on. +\\note 'x' means not available.\n +"; + +# Print Complete Kernel Tables +$i = 0; +$m = 0; +foreach $j (@endOrder) { + print DOC "\\subsection lib$m $libName[$m]\n +"; + print DOC "\n"; + print DOC " + + + + + + + + +"; + # Clear the tableSum + @tableSum = (0, 0, 0, 0); + + for($tbCnt=1 ; $i<$j; $i++) { + $k = $parseOrder[$i]; + print DOC " + + + + + + + + +"; + for($zzz=1 ; $zzz<=4; $zzz++) { + $tableSum[$zzz-1] += ($hash_enums{$k}[$zzz] ne "x") ? 1 : 0; + } + $tbCnt++; + } + + print DOC " + + + + + + + + +"; + + print DOC "
#\\ref DVP_KernelNode_eDVP_KernelNode_t::data Type\\ref DVP_CORE_CPU\\ref DVP_CORE_DSP\\ref DVP_CORE_SIMCOP\\ref DVP_CORE_GPU
$tbCnt\\ref $k$hash_enums{$k}[0]
$hash_enums{$k}[1]
$hash_enums{$k}[2]
$hash_enums{$k}[3]
$hash_enums{$k}[4]
$tableSum[0]
$tableSum[1]
$tableSum[2]
$tableSum[3]
\n"; + $m++; +} + + + +# Print comments for each enumeration, cross-referencing the required data types and available cores. +foreach $k (keys %hash_enums) { + $type = ($hash_enums{$k}[0] eq 'x') ? "N/A" : $hash_enums{$k}[0]; + $cpu = ($hash_enums{$k}[1] eq 'x') ? "" : + ($hash_enums{$k}[1] eq 'NEON') ? "$core"."CPU (NEON)" : "$core"."CPU"; + $dsp = ($hash_enums{$k}[2] eq 'x') ? "" : "$core"."$hash_enums{$k}[2]"; + $imx = ($hash_enums{$k}[3] eq 'x') ? "" : "$core"."$hash_enums{$k}[3]"; + $gpu = ($hash_enums{$k}[4] eq 'x') ? "" : "$core"."$hash_enums{$k}[4]"; + $cmma1 = ($cpu && $dsp) ? ", " : ""; + $cmma2 = (($cpu || $dsp) && $imx) ? ", " : ""; + $cmma3 = (($cpu || $dsp || $imx) && $gpu) ? ", " : ""; + print DOC " + \\var DVP_KernelNode_e::$k + Implemented on following cores: $cpu"."$cmma1"."$dsp"."$cmma2"."$imx"."$cmma3"."$gpu +"; +} + +# Print comments for each data types, cross-referncing the kernel enumerations that require each data type. +foreach $k (keys %hash_types) { + local $, = "\\n \n - \\ref "; + print DOC " + \\class $k + Used by the following kernels:\\n + - \\ref "; + print DOC @{$hash_types{$k}}; + print DOC "\n"; +} + +print DOC "*/"; + +sub parseHeader { + my $header = shift; + my $start = shift; + my $end = shift; + my $values; + my $configStruct; + + open(HEAD, $header) || die("can't open file"); + + $active = 0; + while ($line=) { + if($line =~ /$start/) { + $active = 1; + } + elsif ($line =~ /$end/) { + $active = 0; + } + + if($active) + { + if($line =~ /\s+Configuration Structure: (DVP_\w+)/) { + $configStruct = $1; + } + elsif($line =~ /\s+(DVP_KN_\w+),?/ && + $line !~ /\s+DVP_KN_\w+_BASE/ && + $line !~ /\s+DVP_KN_INVALID/ && + $line !~ /\s+DVP_KN_MAXIMUM/) { + $values = []; #creates a new anonymous array + push (@$values, $configStruct); + push (@$values, "x"); #placeholder for CPU + push (@$values, "x"); #placeholder for DSP + push (@$values, "x"); #placeholder for SIMCOP + push (@$values, "x"); #placeholder for GPU + $hash_enums{$1} = $values; + push @{ $hash_types{$configStruct} }, $1; + push (@parseOrder, $1); + $configStruct = ""; # Clearing variable for next enum + } + elsif($line =~ /DVP_KN_(\w+)_BASE =/) { + $libNameTmp = $1; + } + } + } + close(HEAD); +} + +sub parseKgm { + my $kgm = shift; + my $slot; + my $core; + my %case_enums = (); + + if($kgm =~ /cpu/) { + $slot = 1; + $core = "CPU"; + } + elsif($kgm =~ /dsp/) { + $slot = 2; + $core = "DSP"; + } + elsif($kgm =~ /simcop/) { + $slot = 3; + $core = "SIMCOP"; + } + elsif($kgm =~ /ocl/) { + $slot = 4; + $core = "GPU"; + } + + open(KGM, $kgm) || die("can't open file"); + + $active = 0; + while ($line=) { + if($line =~ /static DVP_CoreFunction_t/) { + $active = 1; + } + elsif ($line =~ /};/) { + $active = 0; + } + + if($active) + { + if($line =~ /(DVP_KN_\w+)/ && + $line !~ /\/\// && + exists $hash_enums{ $1 }) { + $hash_enums{$1}[$slot] = $core; + } + } + + # This portion is used for static code analysis + if($line =~ /case (DVP_KN_\w+)/ && + $line !~ /\@todo/ && + exists $hash_enums{ $1 }) { + $case_enums{$1} = $core; + } + } + close(KGM); + + # This portion is used for static code analysis + print ERLOG "\n+++++++++++++++++++++++++++++++++++++++++++\n"; + print ERLOG "$core \t Checking for missing cases\n"; + print ERLOG "+++++++++++++++++++++++++++++++++++++++++++\n"; + foreach $k (keys %hash_enums) { + if( ($hash_enums{$k}[$slot] ne "x") && + !(exists $case_enums{ $k }) ) + { + print ERLOG "$core \t missing case for $k\n"; + } + } + print ERLOG "\n+++++++++++++++++++++++++++++++++++++++++++\n"; + print ERLOG "$core \t Checking for missing table entries\n"; + print ERLOG "+++++++++++++++++++++++++++++++++++++++++++\n"; + foreach $k (keys %case_enums) { + if( !(exists $hash_enums{ $k }) || + ($hash_enums{$k}[$slot] eq "x") ) + { + print ERLOG "$core \t missing table entry for $k\n"; + } + } +} + +# Depreciated +sub parseSummary { + my $input = shift; + my $line; + my @words; + my $values; + my $i; + + open(IN, $input) || die("can't open file"); + + while ($line=) { + $line =~ s/\"//g; + chomp($line); + @words = split(/,/, $line); + $values = []; #creates a new anonymous array + for( $i=1; $i<@words; $i++ ) + { + push (@$values, $words[$i]); + } + $hash_enums{$words[0]} = $values; # add + push @{ $hash_types{$words[1]} }, $words[0]; + push (@parseOrder, $words[0]); + } + close(IN); +} diff --git a/scripts/qdisp.sh b/scripts/qdisp.sh new file mode 100755 index 0000000..3592d4b --- /dev/null +++ b/scripts/qdisp.sh @@ -0,0 +1,68 @@ +#!/system/bin/sh + +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +export PATH=$PATH:/data/busybox/bin +chmod 755 /data/busybox/bin/* + +OMAPDSS=/sys/devices/platform/omapdss + +DISPLAYS="0 1 2 3" +OVERLAYS="0 1 2 3" +MANAGERS="0 1 2" + +#function sysfs_read { +# cd $1 +# echo -n $1 +# for i in `ls`; do +# if [ -f $i ]; then +# VALUE=`cat $i` +# echo -n " $i=$VALUE" +# fi +# done +#} + +for i in $DISPLAYS ; +do + NAME=`cat $OMAPDSS/display$i/name` + ENABLED=`cat $OMAPDSS/display$i/enabled` + DRIVER=`cat $OMAPDSS/display$i/driver/name` + #if [ $ENABLED == "true" ]; then + echo "DISPLAY[$i]: is named $NAME uses driver $DRIVER enabled $ENABLED" + #fi +done + +for i in $MANAGERS ; +do + NAME=`cat $OMAPDSS/manager$i/name` + DISPLAY=`cat $OMAPDSS/manager$i/display` + TRANS=`cat $OMAPDSS/manager$i/trans_key_enabled` + TYPE=`cat $OMAPDSS/manager$i/trans_key_type` + echo "MANAGER[$i]: is named $NAME uses display $DISPLAY t:$TRANS $TYPE" +done + +for i in $OVERLAYS ; +do + NAME=`cat $OMAPDSS/overlay$i/name` + ENABLED=`cat $OMAPDSS/overlay$i/enabled` + MANAGER=`cat $OMAPDSS/overlay$i/manager` + ORDER=`cat $OMAPDSS/overlay$i/zorder` + #if [ $ENABLED == "true" ]; then + echo "OVERLAY[$i]: is named $NAME uses manager $MANAGER with zorder of $ORDER enabled $ENABLED" + #fi +done + +#sysfs_read $OMAPDSS/overlay2 + diff --git a/scripts/report.pl b/scripts/report.pl new file mode 100755 index 0000000..14c82fa --- /dev/null +++ b/scripts/report.pl @@ -0,0 +1,257 @@ +#!/usr/bin/perl -w + +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# v01 J.Villarreal - Initial Release +# v02 J.Villarreal - Migrating to latest DVP output structure. +# - Pruning out performance from cores that don't belong to the test core. +# - Dividing by 1000 to give performance in terms of ms. +# v03 J.Villarreal - Migrating to latest Performance printout structure. +# - Changing imx to simcop +# v04 J.Villarreal - Migrating to use new multiple header file configration +# from FOSS refactoring. + +$argc = @ARGV; +if ($argc < 1) { + die "\nusage: perl report.pl <0:debug/1:release> \nversion: v04\n\n"; +} + +my $header = shift; +my $top_dir = shift; +my $release = shift; +my $runs = shift; +my $report = "$top_dir/report.txt"; +my @stArray; +my %stHash; +my %libHash; +my %featHash; +my %tmpHash; +my @num; +my @core; +my @kernel; +my @first; +my @avg; +my @test; +my $cnt; +my @core_dir; +my $test_core; +my @headers; + +# Parse all the library specific header files from command line +for( $k=5; $k<=$argc; $k++ ) { + push (@headers, shift); +} + +if(-d $top_dir) { + open(REP, ">$report"); +} +else { + die "$top_dir does not exist.\n"; +} + +# When we only want to put the performances of the core whose directory this is in, +# we need to know the name of the core for screening later. +@core_dir = split(/\// ,$top_dir); +$test_core = $core_dir[@core_dir-1]; + +if($release) { + #@directories = ('qqvga', 'qvga', 'vga', '4xvga'); # OLD VERSION + @directories = ('qqvga', 'qvga', 'vga'); + foreach $dir (@directories) { + $dir = $top_dir . '/' . $dir; + } +} else { + @directories = <$top_dir/*>; +} + +# Parse dvp_types.h +%featHash = %{&parseHeader($header, "_KF_", "^typedef enum _dvp_kfeat_e", "^} DVP_KernelFeature_e")}; +%libHash = %{&parseHeader($header, "_KL_", "^typedef enum _dvp_klib_e", "^} DVP_KernelLibrary_e")}; +%stHash = %{&parseHeader($header, "_KN_", "^typedef enum _dvp_knode_e", "^} DVP_KernelNode_e")}; + +# Parse library specific DVP header files +foreach $k (@headers) { + %tmpHash = %{&parseHeader($k, "_KN_", "^enum {", "^};")}; + @stHash{ keys %tmpHash } = values %tmpHash; #concatenate hashes +} + +$dirCnt = 0; + +foreach $dir (@directories) { + if(-d $dir) { + + my $infile = "$dir/log"; + my $out = "$dir/log.txt"; + my $newAvg; + my $line; + my @words; + my @sub_dir; + + $cnt = 0; + $active = 0; + + open(IN, $infile) || die("can't open file"); + open(OUT, ">$out") || die("can't open file"); + + while ($line=) { + if($line =~ /Node Performance/) { + $active = 1; + } + elsif ($line =~ /Segmentation fault/) { + print " ERROR: $infile has a Segmentation Fault\n"; + } + + if($active) + { + chomp($line); +# $line =~ s/D\/DVP_ZONE_PERF\( \d+\)://; # OLD VERSION + $line =~ s/DVP_ZONE_PERF://; + $line =~ s/ //g; + @words = split(/,/, $line); + if (@words > 6 && $words[2] =~ /0x/) { + $words[2] =~ s/0x//; + $line =~ s/0x$words[2]/$stHash{hex($words[2])}/; + if($words[1] =~ /simcop/) { + $newAvg = &restrict_num_decimal_digits(($words[6]-$words[4])/($runs-1)/1000,3); + } + else { + $newAvg = &restrict_num_decimal_digits($words[5]/1000,3); + } + $num[$dirCnt][$cnt] = $words[0]; + $core[$dirCnt][$cnt] = $words[1]; + $kernel[$dirCnt][$cnt] = $stHash{hex($words[2])}; + $first[$dirCnt][$cnt] = $words[4]; + $avg[$dirCnt][$cnt] = $newAvg; +# if($core[$dirCnt][$cnt] !~ /m3/) { +# $avg[$dirCnt][$cnt] = 0; +# } + @sub_dir = split(/\// ,$dir); + #print "\n\n$sub_dir[1]\n"; + $test[$dirCnt] = $sub_dir[@sub_dir-1]; + $cnt++; + } + $line =~ s/,/\t/g; + $line = $line . "\n"; + print OUT $line; + } + } + + if($active == 0) + { + print " ERROR: $infile does not have performance data\n"; + } + + close(IN); + close(OUT); + $dirCnt++; + } +} + +print REP "Num\tKernel\tCore"; foreach $i (@test) {print REP "\t$i";} print REP "\n"; +for ($i=0; $i<$cnt; $i++) { + print REP "$num[0][$i]\t$kernel[0][$i]\t$core[0][$i]"; + for ($j=0; $j<$dirCnt; $j++) { + if ($avg[$j][$i] && + ($core[$j][$i] eq $core[0][$i]) && + ( ($core[$j][$i] =~ /$test_core/) || !($release) ) + ) { + print REP "\t$avg[$j][$i]" + } else { + print REP "\t" + } + } + print REP "\n"; +} + +close(REP); + + +# Parses a header file and returns a hash of enums/values +sub parseHeader { + my $header = shift; # Name of file to parse + my $searchStr = shift; # Search string + my $start = shift; # Starting delimeter in file + my $end = shift; # Ending delimeter in file + my %hash = (); # Start a new hash + + # Taken directly from dvp_types.h (easier than parsing, since it won't change) + my $DVP_KN_RANGE = hex(1000); + my $DVP_KN_FEATURE_START = hex(0); + my $DVP_KN_LIBRARY_START = hex(40000000); + + open(HEAD, $header) || die("can't open file"); + + $active = 0; + $value = 0; + while ($line=) { + if($line =~ /$start/) { + $active = 1; + } + elsif ($line =~ /$end/) { + $active = 0; + } + + if($active) + { + if($line =~ /=\s+(\d+),/) { # For when an enum is = a decimal value + $value = $1; + } + elsif($line =~ /=\s+0x([0-9A-F]+),/) { # For when an enum is = a hex value + $value = hex($1); + } + elsif($line =~ /=\s+DVP_KN_FEATURE_BASE\((DVP_KF_\w+)\),/) { + $value = $DVP_KN_FEATURE_START + ($featHash{$1} * $DVP_KN_RANGE); + } + elsif($line =~ /=\s+DVP_KN_LIBRARY_BASE\((DVP_KL_\w+)\),/) { + $value = $DVP_KN_LIBRARY_START + ($libHash{$1} * $DVP_KN_RANGE); + } + + if($line =~ /\s+(\w+$searchStr\w+),?/) { + if($searchStr eq "_KN_") { + $hash{$value} = $1; + } else { + $hash{$1} = $value; + } + $value++; + } + } + } + close(HEAD); + return \%hash; +} + +sub round { + my $number = shift || 0; + my $dec = 10 ** (shift || 0); + return int( $dec * $number + .5 * ($number <=> 0)) / $dec; +} + +# restrict the number of digits after the decimal point +sub restrict_num_decimal_digits +{ + my $num=shift;#the number to work on + my $digs_to_cut=shift;# the number of digits after + # the decimal point to cut + #(eg: $digs_to_cut=3 will leave + # two digits after the decimal point) + + if ($num=~/\d+\.(\d){$digs_to_cut,}/) + { + # there are $digs_to_cut or + # more digits after the decimal point + $num=sprintf("%.".($digs_to_cut-1)."f", $num); + } + return $num; +} diff --git a/source/Android.mk b/source/Android.mk new file mode 100644 index 0000000..b529487 --- /dev/null +++ b/source/Android.mk @@ -0,0 +1,15 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(call all-subdir-makefiles) diff --git a/source/dvp/Android.mk b/source/dvp/Android.mk new file mode 100644 index 0000000..b529487 --- /dev/null +++ b/source/dvp/Android.mk @@ -0,0 +1,15 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(call all-subdir-makefiles) diff --git a/source/dvp/ImageDebugging/Android.mk b/source/dvp/ImageDebugging/Android.mk new file mode 100644 index 0000000..0a5a38a --- /dev/null +++ b/source/dvp/ImageDebugging/Android.mk @@ -0,0 +1,25 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CPPFLAGS := $(DVP_DEBUGGING) $(DVP_CPPFLAGS) +LOCAL_SRC_FILES := ImageDebugging.cpp +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_MODULE := libimgdbg +include $(BUILD_STATIC_LIBRARY) + diff --git a/source/dvp/ImageDebugging/ImageDebugging.cpp b/source/dvp/ImageDebugging/ImageDebugging.cpp new file mode 100644 index 0000000..af5bb71 --- /dev/null +++ b/source/dvp/ImageDebugging/ImageDebugging.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#ifdef DVP_USE_TILER +#undef PAGE_SIZE // this is remove a warning +#include +#endif + +void ImageDebug_Init(ImageDebug_t *pImgd, DVP_Image_t *pImage, const char *path, const char *name) +{ + if (pImgd && pImage) + { + PYUV_GetFilename(pImgd->filename, (char *)path, (char *)name, pImage->width, pImage->height, 30, (fourcc_t)pImage->color); +#if defined(DVP_USE_FS) + pImgd->debug = NULL; +#endif + pImgd->pImg = pImage; + pImgd->pBuf = NULL; + DVP_PRINT(DVP_ZONE_IMGDBG, "Filename = %s\n", pImgd->filename); + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: ImageDgb = %p, pImage = %p\n", pImgd, pImage); + } +} + +void BufferDebug_Init(ImageDebug_t *pImgd, DVP_Buffer_t *pBuffer, const char *path, const char *name, const char *ext) +{ + if (pImgd && pBuffer) + { + strcpy(pImgd->filename,(char *)path); + strcat(pImgd->filename,(char *)name); + strcat(pImgd->filename,(char *)ext); +#if defined(DVP_USE_FS) + pImgd->debug = NULL; +#endif + pImgd->pImg = NULL; + pImgd->pBuf = pBuffer; + DVP_PRINT(DVP_ZONE_IMGDBG, "Filename = %s\n", pImgd->filename); + } +} + +void ImageDebug_Open(ImageDebug_t *pImgd, DVP_U32 numImg) +{ +#if defined(DVP_USE_FS) + DVP_U32 i = 0; + // open all the files for writing + for (i = 0; i < numImg; i++) + { + pImgd[i].debug = fopen(pImgd[i].filename, "w+"); + if (pImgd[i].debug == NULL) { + DVP_PRINT(DVP_ZONE_ERROR, "Error opening file [%u]%s for writing\n",i,pImgd[i].filename); + } else { + DVP_PRINT(DVP_ZONE_IMGDBG, "Opening file %s for debug output!\n",pImgd[i].filename); + } + } +#endif +} + +void ImageDebug_Write(ImageDebug_t *pImgd, DVP_U32 numImg) +{ +#if defined(DVP_USE_FS) + if (pImgd) + { + DVP_U32 i,j,y,p,len,n = 0; + + // write out all the data + for (i = 0; i < numImg; i++) + { + DVP_Image_t *pImage = pImgd[i].pImg; + DVP_Buffer_t *pBuffer = pImgd[i].pBuf; + + n = 0; // initialize for each debug image; + + if (pBuffer) + { + n += (uint32_t)fwrite(pBuffer->pData, 1, pBuffer->numBytes, pImgd[i].debug); + fflush(pImgd[i].debug); + } + else if(pImage) + { + // for equal sized plane images + if (pImage->planes == 1 || + pImage->color == FOURCC_RGBP || + pImage->color == FOURCC_YV24 || + pImage->color == FOURCC_YU24) + { + for (p = 0; p < pImage->planes; p++) // loop for each plane + { + for (y = 0; y < pImage->height; y++) // loop for each line + { + len = (pImage->x_stride * pImage->width); + j = (y * pImage->y_stride); + n += (uint32_t)fwrite(&pImage->pData[p][j], 1, len, pImgd[i].debug); + } + fflush(pImgd[i].debug); + } + } + else + { + DVP_U32 x_divisor = 1; + DVP_U32 y_divisor = 1; + if (pImage->color == FOURCC_YVU9 || + pImage->color == FOURCC_YUV9) + { + x_divisor = 4; + y_divisor = 1; + } + else if (pImage->color == FOURCC_YV16 || + pImage->color == FOURCC_YU16) + { + x_divisor = 2; + y_divisor = 1; + } + else if (pImage->color == FOURCC_YV12 || + pImage->color == FOURCC_IYUV) + { + x_divisor = 2; + y_divisor = 2; + } + else if (pImage->color == FOURCC_NV12 || + pImage->color == FOURCC_NV21) + { + y_divisor = 2; + } + for (y = 0; y < pImage->height; y++) + { + len = (pImage->x_stride * pImage->width); + j = (y * pImage->y_stride); + n += (DVP_U32)fwrite(&pImage->pData[0][j], 1, len, pImgd[i].debug); + } + fflush(pImgd[i].debug); + for (p = 1; p < pImage->planes; p++) + { + for (y = 0; y < pImage->height/y_divisor; y++) + { + len = (pImage->x_stride * pImage->width/x_divisor); +#ifdef DVP_USE_TILER + if (pImage->y_stride == TILER_STRIDE_8BIT) + j = (y * pImage->y_stride); // @NOTE In this case subsampled images are overallocated and use the same stride + else + j = (y * pImage->y_stride/x_divisor); +#else + j = (y * pImage->y_stride/x_divisor); +#endif + n+= (DVP_U32)fwrite(&pImage->pData[p][j], 1, len, pImgd[i].debug); + } + } + fflush(pImgd[i].debug); + } + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "DEBUG image/buffer pointers are NULL for file %s\n", pImgd[i].filename); + } + DVP_PRINT(DVP_ZONE_IMGDBG, "Wrote %u bytes to %s\n", n, pImgd[i].filename); + } + } +#endif +} + +void ImageDebug_Close(ImageDebug_t *pImgd, DVP_U32 numImg) +{ +#if defined(DVP_USE_FS) + DVP_U32 i = 0; + for (i = 0; i < numImg; i++) + fclose(pImgd[i].debug); +#endif +} + diff --git a/source/dvp/ImageDebugging/concerto.mak b/source/dvp/ImageDebugging/concerto.mak new file mode 100644 index 0000000..2c21259 --- /dev/null +++ b/source/dvp/ImageDebugging/concerto.mak @@ -0,0 +1,23 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(PRELUDE) +TARGET=imgdbg +TARGETTYPE=library +CPPSOURCES=ImageDebugging.cpp +ifeq ($(TARGET_CPU),ARM) +IDIRS+=$(TILER_INC) +endif +include $(FINALE) + diff --git a/source/dvp/VisionCam/Android.mk b/source/dvp/VisionCam/Android.mk new file mode 100644 index 0000000..da28ed2 --- /dev/null +++ b/source/dvp/VisionCam/Android.mk @@ -0,0 +1,87 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_SRC_FILES := VisionCamFactory.cpp \ + CameraEmulator.cpp \ + FileVisionCam.cpp \ + OMXVisionCam.cpp \ + SocketVisionCam.cpp \ + VisionCamFrame.cpp \ + VisionCamUtils.cpp +ifdef EXPORTED_3A +LOCAL_SRC_FILES += OMXVisionCam_3A_Export.cpp +endif + +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_CPPFLAGS := $(DVP_DEBUGGING) $(DVP_CPPFLAGS) -DVCAM_USE_OMX +LOCAL_MODULE := libvcam +include $(BUILD_STATIC_LIBRARY) + +# An Interactive Unit Test for VisionCam +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CPPFLAGS := $(DVP_DEBUGGING) $(DVP_CPPFLAGS) +ifeq ($(TARGET_PLATFORM), SDP) + LOCAL_CPPFLAGS+=-DSDP +endif + +LOCAL_SRC_FILES := VisionCamTest.cpp +ifdef EXPORTED_3A +LOCAL_SRC_FILES += VisionCamTest_3A_Export.cpp +endif + +LOCAL_C_INCLUDES +=$(DVP_INCLUDES) \ + frameworks/base/include/utils \ + $(TI_HW_ROOT)/omap4xxx/libtiutils +LOCAL_SHARED_LIBRARIES:= libdl libbinder $(DVP_SYSLIBS) libOMX_Core libdvp libcutils libutils libdvp +LOCAL_STATIC_LIBRARIES := libvcam libsosal libcthreaded +LOCAL_MODULE := vcam_test +include $(BUILD_EXECUTABLE) + +# A simple command line VisionCam Test +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CPPFLAGS := $(DVP_DEBUGGING) $(DVP_CPPFLAGS) +ifeq ($(TARGET_PLATFORM), SDP) + LOCAL_CPPFLAGS+=-DSDP +endif +LOCAL_SRC_FILES := VisionCamSimpleTest.cpp +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_SHARED_LIBRARIES:= libdl $(DVP_SYSLIBS) libOMX_Core libcutils libutils libdvp +LOCAL_STATIC_LIBRARIES := libvcam libsosal libimgdbg libcthreaded +LOCAL_MODULE := vcam_simple +include $(BUILD_EXECUTABLE) + +# A Socket Server of VisionCam +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CPPFLAGS := $(DVP_DEBUGGING) $(DVP_CPPFLAGS) $(DVP_FEATURES) +LOCAL_SRC_FILES := ServerVisionCam.cpp VisionCamServer.cpp VisionCamFrame.cpp +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_SHARED_LIBRARIES:= libdl $(DVP_SYSLIBS) libOMX_Core libcutils libutils libdvp +LOCAL_STATIC_LIBRARIES := libvcam libsosal libcthreaded +LOCAL_MODULE := vcam_server +include $(BUILD_EXECUTABLE) + diff --git a/source/dvp/VisionCam/CameraEmulator.cpp b/source/dvp/VisionCam/CameraEmulator.cpp new file mode 100644 index 0000000..11e4f6b --- /dev/null +++ b/source/dvp/VisionCam/CameraEmulator.cpp @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +CameraEmulator::CameraEmulator() +{ + uint32_t i = 0; + for (i = 0; i < VCAM_NUM_BUFFERS; i++) + { + memset(&m_buffers[i], 0, sizeof(VCAM_Buffer_t)); + } + + // intialize to the default values. + m_height = 320; + m_width = 240; + m_fps = 30; + m_space = FOURCC_UYVY; + m_timer = 1000/m_fps; + m_lastIdx = VCAM_NUM_BUFFERS - 1; + DVP_PRINT(DVP_ZONE_API, "+CameraEmulator()\n"); +} + +CameraEmulator::~CameraEmulator() +{ + DVP_PRINT(DVP_ZONE_API, "-CameraEmulator()\n"); +} + +status_e CameraEmulator::init(void *cookie) +{ + m_cookie = cookie; + return STATUS_SUCCESS; +} + +status_e CameraEmulator::deinit() +{ + return STATUS_SUCCESS; +} + +status_e CameraEmulator::useBuffers(DVP_Image_t *prvBufArr, + uint32_t numPrvBuf/*, void* extraDataBuf, int numExtraDataBuf*/, + VisionCamPort_e port __attribute__ ((unused))) +{ + // add the buffer to the list of usable buffers + uint32_t b, i = 0; + uint32_t numRegistered = 0; + for (b = 0; b < numPrvBuf; b++) + { + DVP_Image_t *pImage = &prvBufArr[b]; + DVP_PRINT(DVP_ZONE_CAM, "[%u] Attempting to register buffer %p to Camera\n", b, pImage); + for (i = 0; i < VCAM_NUM_BUFFERS; i++) + { + if (m_buffers[i].data == NULL) + { + m_buffers[i].data = pImage; + m_buffers[i].used = 0; + m_buffers[i].size = GetImageSize(m_width, m_height, m_space); + DVP_PRINT(DVP_ZONE_CAM, "Registered Buffer %p\n", m_buffers[i].data); + numRegistered++; + break; + } + } + } + DVP_PRINT(DVP_ZONE_CAM, "Registered %u buffers\n", numRegistered); + return STATUS_SUCCESS; +} + +status_e CameraEmulator::flushBuffers(VisionCamPort_e port __attribute__ ((unused))) +{ + // nothing to do + return STATUS_SUCCESS; +} + +status_e CameraEmulator::releaseBuffers(VisionCamPort_e port __attribute__ ((unused))) +{ + // nothing to do + return STATUS_SUCCESS; +} + +status_e CameraEmulator::setParameter(VisionCamParam_e paramId, + void* param, + uint32_t size, + VisionCamPort_e port __attribute__ ((unused))) +{ + status_e err = STATUS_SUCCESS; + switch (paramId) + { + case VCAM_PARAM_WIDTH: + memcpy(&m_width, param, size); + break; + case VCAM_PARAM_HEIGHT: + memcpy(&m_height, param, size); + break; + case VCAM_PARAM_FPS_FIXED: + memcpy(&m_fps, param, size); + m_timer = 1000/m_fps; + DVP_PRINT(DVP_ZONE_CAM, "Timer is set to %d ms\n", m_timer); + break; + case VCAM_PARAM_NAME: + memset(m_name, 0, sizeof(m_name)); + strncpy(m_name, (char *)param, size); + DVP_PRINT(DVP_ZONE_CAM, "Setting File Name to %s\n", m_name); + break; + case VCAM_PARAM_COLOR_SPACE_FOURCC: + memcpy(&m_space, param, size); + DVP_PRINT(DVP_ZONE_CAM, "Setting FOURCC 0x%08x\n", m_space); + break; + case VCAM_PARAM_CAP_MODE: + case VCAM_PARAM_FLICKER: + case VCAM_PARAM_SENSOR_SELECT: + case VCAM_PARAM_ROTATION: + case VCAM_PARAM_DO_MANUALFOCUS: + case VCAM_PARAM_STEREO_INFO: + case VCAM_PARAM_AWB_MODE: + case VCAM_PARAM_DO_AUTOFOCUS: + // just ignore these and pretend like it worked + break; + default: + err = STATUS_NOT_IMPLEMENTED; + if(paramId < VCAM_PARAM_MIN || paramId > VCAM_PARAM_MAX) + err = STATUS_INVALID_PARAMETER; + break; + } + return err; +} + +status_e CameraEmulator::getParameter(VisionCamParam_e paramId, + void* param, + uint32_t size, + VisionCamPort_e port __attribute__ ((unused))) +{ + status_e err = STATUS_SUCCESS; + switch (paramId) + { + case VCAM_PARAM_WIDTH: + memcpy( param, &m_width, size); + break; + case VCAM_PARAM_HEIGHT: + memcpy(param, &m_height, size); + break; + case VCAM_PARAM_FPS_FIXED: + memcpy(param, &m_fps, size); + m_timer = 1000/m_fps; + break; + case VCAM_PARAM_NAME: + strncpy((char *)param, m_name, (size < strlen(m_name) ? size : strlen(m_name))); + break; + case VCAM_PARAM_COLOR_SPACE_FOURCC: + memcpy(param, &m_space, size); + break; + case VCAM_PARAM_2DBUFFER_DIM: + { + VisionCamResType *pRes = (VisionCamResType *)param; + if (pRes && size == sizeof(VisionCamResType)) + { + pRes->mWidth = m_width; + pRes->mHeight = m_height; + DVP_PRINT(DVP_ZONE_CAM, "VCAM: %ux%u starting at %dx%d\n", m_width, m_height, 0, 0); + } + else + err = STATUS_INVALID_PARAMETER; + break; + } + default: + err = STATUS_INVALID_PARAMETER; + break; + } + return err; +} + +status_e CameraEmulator::returnFrame(VisionCamFrame *cameraFrame) +{ + for (uint32_t i = 0; i < VCAM_NUM_BUFFERS; i++) + { + if (m_buffers[i].data == cameraFrame->mFrameBuff) + { + DVP_PRINT(DVP_ZONE_CAM, "Returned buffer %d (%p)\n", i, cameraFrame->mFrameBuff); + m_buffers[i].used = 0; + return STATUS_SUCCESS; + } + } + return STATUS_INVALID_PARAMETER; +} + +// Default implementation +status_e CameraEmulator::sendCommand(VisionCamCmd_e cmdId, + void *param __attribute__ ((unused)) , + uint32_t size __attribute__ ((unused)) , + VisionCamPort_e port __attribute__ ((unused)) ) +{ + status_e err = STATUS_SUCCESS; + switch (cmdId) + { + case VCAM_CMD_PREVIEW_START: + StartThread(this); + break; + case VCAM_CMD_QUIT: + case VCAM_CMD_PREVIEW_STOP: + StopThread(); + break; + case VCAM_EXTRA_DATA_START: + case VCAM_EXTRA_DATA_STOP: + // ignore + break; + default: + err = STATUS_INVALID_PARAMETER; + break; + } + return err; +} + +int32_t CameraEmulator::getNextFreeBuffer() +{ + int32_t i = m_lastIdx; // start with the last index used + DVP_PRINT(DVP_ZONE_CAM, "Last Used Buffer was %d\n", i); + do { + // go to the next index + i = (i + 1) % VCAM_NUM_BUFFERS; + DVP_PRINT(DVP_ZONE_CAM, "Checking buffer %d\n", i); + if (m_buffers[i].data && m_buffers[i].used == 0) + { + // free to be used + m_lastIdx = i; + DVP_PRINT(DVP_ZONE_CAM, "Using Buffer %d\n", i); + return i; + } + } while (i != m_lastIdx); + + DVP_PRINT(DVP_ZONE_CAM, "No free buffer found!\n"); + return -1; +} + + diff --git a/source/dvp/VisionCam/CameraEmulator.h b/source/dvp/VisionCam/CameraEmulator.h new file mode 100644 index 0000000..7187a18 --- /dev/null +++ b/source/dvp/VisionCam/CameraEmulator.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CAMERA_EMULATOR_H_ +#define _CAMERA_EMULATOR_H_ + +#include +#include + +typedef struct _vcam_buffer_t { + DVP_Image_t *data; + int used; /**< This indicates whether the buffer has been registered but returned to the user at the moment */ + size_t size; +} VCAM_Buffer_t; + +class CameraEmulator + : public CThreaded, + public VisionCam +{ +protected: + VCAM_Buffer_t m_buffers[VCAM_NUM_BUFFERS]; + char m_name[MAX_PATH]; /**< The predicate name of the file */ + uint32_t m_width; /**< The width of the image */ + uint32_t m_height; /**< The height of the image */ + uint32_t m_fps; /**< The frame rate of the camera */ + fourcc_t m_space; /**< The fourcc_t code for the color space that the Camera is configured for */ + int32_t m_timer; /**< The frame return timer */ + int32_t m_lastIdx; /**< The last camera buffer we used */ +public: + CameraEmulator(); + virtual ~CameraEmulator(); + + virtual status_e init(void *cookie); + virtual status_e deinit(); + virtual status_e useBuffers(DVP_Image_t *prvBufArr, uint32_t numPrvBuf/*, void* extraDataBuf, int numExtraDataBuf*/, VisionCamPort_e port = VCAM_PORT_ALL ); + virtual status_e releaseBuffers(VisionCamPort_e port = VCAM_PORT_ALL ); + virtual status_e flushBuffers(VisionCamPort_e port = VCAM_PORT_ALL ); + virtual status_e sendCommand(VisionCamCmd_e cmdId, void *param, uint32_t size, VisionCamPort_e port = VCAM_PORT_ALL ); + virtual status_e setParameter(VisionCamParam_e paramId, void * param, uint32_t size, VisionCamPort_e port = VCAM_PORT_ALL); + virtual status_e getParameter(VisionCamParam_e paramId, void * param, uint32_t size, VisionCamPort_e port = VCAM_PORT_ALL ); + virtual status_e returnFrame(VisionCamFrame *cameraFrame); + + int32_t getNextFreeBuffer(); +}; + +#endif + diff --git a/source/dvp/VisionCam/FileVisionCam.cpp b/source/dvp/VisionCam/FileVisionCam.cpp new file mode 100644 index 0000000..e707a55 --- /dev/null +++ b/source/dvp/VisionCam/FileVisionCam.cpp @@ -0,0 +1,444 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +char *fourcc_to_str(fourcc_t fcc) +{ + static char code[5]; + strncpy(code, (char *)&fcc, 4); + code[4] = '\0'; + return code; +} + +FileVisionCam::FileVisionCam() + : CameraEmulator() +{ + m_file = NULL; + m_type = FILECAM_TYPE_UNKNOWN; + memset(m_path, 0, sizeof(m_path)); + DVP_PRINT(DVP_ZONE_API, "+FileVisionCam()\n"); +} + +FileVisionCam::~FileVisionCam() +{ + if (m_file) + fclose(m_file); + m_file = NULL; + DVP_PRINT(DVP_ZONE_API, "-FileVisionCam()\n"); +} + +uint32_t FileVisionCam::avi_chunk_parse(AVI_Chunk_t *aChunk) +{ + uint32_t s=0,size = aChunk->size + sizeof(fourcc_t) + sizeof(uint32_t); + DVP_PRINT(DVP_ZONE_CAM, "CHUNK %u %s\n", aChunk->size, fourcc_to_str(aChunk->chunkcode)); + if (aChunk->chunkcode == FOURCC_AVIH) + { + AVI_MainHeader_t mainHeader; + s+=fread(&mainHeader, sizeof(AVI_MainHeader_t), 1, m_file); + + if (m_width != mainHeader.width || + m_height != mainHeader.height) + { + DVP_PRINT(DVP_ZONE_ERROR, "AVI File Video Dimensions do not match expectations!\n"); + } + } + else if (aChunk->chunkcode == FOURCC_STRH) + { + AVI_StreamHeader_t strmHeader; + s+=fread(&strmHeader, sizeof(AVI_StreamHeader_t), 1, m_file); + if (strmHeader.fccType != FOURCC_VIDS) + { + DVP_PRINT(DVP_ZONE_ERROR, "AVI Stream is not video!\n"); + } + if (strmHeader.fccHandler == FOURCC_NONE && m_space != FOURCC_BGR) + { + // NONE is BI_BITFIELDS + DVP_PRINT(DVP_ZONE_ERROR, "AVI Stream is not in the expected color format!\n"); + } + } + else // skip over unknown types + { + fseek(m_file, aChunk->size, SEEK_CUR); + DVP_PRINT(DVP_ZONE_CAM, "\tUnknown CHUNK type %s, moving to %lu offset\n", fourcc_to_str(aChunk->chunkcode), ftell(m_file)); + } + return size; +} + +uint32_t FileVisionCam::avi_list_parse(AVI_List_t *aList) +{ + // we need to report to the caller the entire size of the list + uint32_t s=0,size = aList->size + sizeof(fourcc_t) + sizeof(uint32_t); + DVP_PRINT(DVP_ZONE_CAM, "LIST %u %s\n", aList->size, fourcc_to_str(aList->typecode)); + aList->size -= sizeof(fourcc_t); // remove the list type size since we've alread read it + do + { + fourcc_t code; // next sub item + s+=fread(&code, sizeof(fourcc_t), 1, m_file); + fseek(m_file, -(long)sizeof(fourcc_t), SEEK_CUR); // back up over the code + if (code == FOURCC_LIST) + { + AVI_List_t anotherList; + s+=fread(&anotherList, sizeof(AVI_List_t), 1, m_file); + aList->size -= avi_list_parse(&anotherList); + } + else + { + AVI_Chunk_t aChunk; + s+=fread(&aChunk, sizeof(AVI_Chunk_t), 1, m_file); + aList->size -= avi_chunk_parse(&aChunk); + } + } while (aList->size > 0); + return size; +} + +uint32_t FileVisionCam::avi_header_parse(AVI_Header_t *aHeader) +{ + uint32_t s=0; + if (aHeader->riffcode == FOURCC_RIFF && aHeader->typecode == FOURCC_AVI) + { + DVP_PRINT(DVP_ZONE_CAM, "RIFF %u %s\n", aHeader->size, fourcc_to_str(aHeader->typecode)); + m_fileSize = aHeader->size; + fourcc_t code; + s+=fread(&code, sizeof(fourcc_t), 1, m_file); + fseek(m_file,-(long)sizeof(fourcc_t), SEEK_CUR); + if (code == FOURCC_LIST) // first header + { + AVI_List_t aList; + s+=fread(&aList, sizeof(AVI_List_t), 1, m_file); + return avi_list_parse(&aList); + } + else + { + AVI_Chunk_t aChunk; + s+=fread(&aChunk, sizeof(AVI_Chunk_t), 1, m_file); + return avi_chunk_parse(&aChunk); + } + } + return 0; +} + +uint32_t FileVisionCam::avi_stream_parse(AVI_List_t *aList, DVP_Image_t *pImage) +{ + uint32_t b=0; + if (aList->listcode == FOURCC_LIST && aList->typecode == FOURCC_MOVI) + { + DVP_PRINT(DVP_ZONE_CAM, "Parsing Movie Section!\n"); + fourcc_t code; + b+=fread(&code, sizeof(fourcc_t), 1, m_file); + fseek(m_file, -(long)sizeof(fourcc_t), SEEK_CUR); + if (code == FOURCC_LIST) + { + AVI_List_t aList; + b+=fread(&aList, sizeof(AVI_List_t), 1, m_file); + //fseek(m_file, aList.size - sizeof(uint32_t), SEEK_CUR); + return avi_list_parse(&aList); + } + else // STREAM TAGS + { + AVI_Chunk_t aChunk; + AVI_StreamTag_t tag; + uint32_t s = 0; + b+=fread(&aChunk, sizeof(AVI_Chunk_t), 1, m_file); + memcpy(&tag, &aChunk.chunkcode, sizeof(tag)); + if (strncmp(tag.streamType,"db",2) == 0) + { + uint32_t i = 0; + int32_t y = 0; + if (m_space == FOURCC_BGR) + { + DVP_PrintImage(DVP_ZONE_CAM, pImage); + DVP_PRINT(DVP_ZONE_CAM, "About to read RGB AVI data into DVP_Image_t* %p {%p} stride=%d!\n", pImage, &(pImage->pData[0][i]),pImage->y_stride); + for (y = pImage->height - 1; y >= 0 ; y--) + { + i = (y * pImage->y_stride); + s += fread(&pImage->pData[0][i], 1, pImage->x_stride * pImage->width, m_file); + } + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Unsupported AVI to DVP_Image_t reading format (0x%08x)!\n", m_space); + fseek(m_file, aChunk.size, SEEK_CUR); + } + if (s < aChunk.size) + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to read enough image data from file! %u < %u\n", s, aChunk.size); + } + } + else + fseek(m_file, aChunk.size, SEEK_CUR); + return s; + } + } + else + { + DVP_PRINT(DVP_ZONE_CAM, "%s\n", fourcc_to_str(aList->listcode)); + } + return 0; +} +status_e FileVisionCam::sendCommand(VisionCamCmd_e cmdId, + void *param __attribute__ ((unused)), + uint32_t size __attribute__ ((unused)), + VisionCamPort_e port __attribute__ ((unused)) ) +{ + size_t bytes = 0; + status_e status = STATUS_SUCCESS; + switch (cmdId) + { + case VCAM_CMD_PREVIEW_START: + if (m_file == NULL) + { + char *ext; + char filename[255]; + memset(filename, 0, sizeof(filename)); + + DVP_PRINT(DVP_ZONE_CAM, "NAME: %s\n", m_name); + DVP_PRINT(DVP_ZONE_CAM, "PATH: %s\n", m_path); + DVP_PRINT(DVP_ZONE_CAM, "WIDTH: %u, HEIGHT: %u\n", m_width, m_height); + + ext = strchr(m_name, '.'); + if (ext == NULL) // no extension, we wanted to use the pyuv lib + m_type = FILECAM_TYPE_PYUV; + else // there is an extension + { + ext++; + if (strcmp(ext, "avi") == 0) + m_type = FILECAM_TYPE_AVI; + else if (strcmp(ext, "raw") == 0) + m_type = FILECAM_TYPE_RAW; + else + m_type = FILECAM_TYPE_UNKNOWN; + } + + if (m_type == FILECAM_TYPE_PYUV) + { + DVP_PRINT(DVP_ZONE_CAM, "Using PYUV Library to determine name!\n"); + PYUV_GetFilename(filename, strcat(m_path, PATH_DELIM), m_name, m_width, m_height, m_fps, m_space); + } + else if (m_type == FILECAM_TYPE_AVI) + { + DVP_PRINT(DVP_ZONE_CAM, "Using AVI Parsing!\n"); + if (m_path[0] != '\0') + sprintf(filename, "%s"PATH_DELIM"%s", m_path, m_name); + else + sprintf(filename, "%s", m_name); + } + else if (m_type == FILECAM_TYPE_RAW) + { + DVP_PRINT(DVP_ZONE_CAM, "Using RAW File!\n"); + if (m_path[0] != '\0') + sprintf(filename, "%s"PATH_DELIM"%s", m_path, m_name); + else + sprintf(filename, "%s", m_name); + } + m_file = fopen(filename, (char *)"rb"); + if (m_file) + { + DVP_PRINT(DVP_ZONE_CAM, "Opened file \"%s\"\n", filename); + if (m_type == FILECAM_TYPE_AVI) + { + AVI_Header_t hdr; + bytes+=fread(&hdr, sizeof(AVI_Header_t), 1, m_file); + avi_header_parse(&hdr); + } + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to open file \"%s\"\n", filename); + status = STATUS_FILE_NOT_FOUND; + break; + } + StartThread(this); // start regardless of file existence... + } + break; + case VCAM_CMD_QUIT: + case VCAM_CMD_PREVIEW_STOP: + StopThread(); + if (m_file) + fclose(m_file); + m_file = NULL; + break; + case VCAM_EXTRA_DATA_START: + case VCAM_EXTRA_DATA_STOP: + case VCAM_CMD_LOCK_AE: + case VCAM_CMD_LOCK_AWB: + default: + break; + } + return status; +} + +thread_ret_t FileVisionCam::RunThread() +{ + int32_t i = 0; + thread_ret_t err = 0; + VisionCamFrame *pFrame = new VisionCamFrame(); + DVP_Image_t *pImage = NULL; + AVI_List_t movList; + size_t bytes = 0; + size_t bytesRead; + + if (m_type == FILECAM_TYPE_AVI) + { + // read the next LIST, which should be the movie + fourcc_t code; + uint32_t b = 0; + DVP_PRINT(DVP_ZONE_CAM, "Finding MOVI LIST from %lu\n",ftell(m_file)); + do { + b = fread(&code, sizeof(fourcc_t), 1, m_file); + if (b == 0) { + thread_exit(0); + } + fseek(m_file, -(long)sizeof(fourcc_t), SEEK_CUR); + DVP_PRINT(DVP_ZONE_CAM, "FOUND \"%s\"\n", fourcc_to_str(code)); + if (code == FOURCC_LIST) + { + bytes+=fread(&movList, sizeof(AVI_List_t), 1, m_file); + } + else + { + AVI_Chunk_t aChunk; + bytes+=fread(&aChunk, sizeof(AVI_Chunk_t), 1, m_file); + fseek(m_file, aChunk.size, SEEK_CUR); + } + } while (movList.listcode != FOURCC_LIST && movList.typecode != FOURCC_MOVI); + } + + while (m_running) + { + // wait for the timer to expire + DVP_PRINT(DVP_ZONE_CAM, "RunThread sleep period is %u msecs\n", m_timer); + thread_msleep(m_timer); + if (m_running == false) + break; + DVP_PRINT(DVP_ZONE_CAM, "Woke up, processing frame!\n"); + + // grab a frame + i = getNextFreeBuffer(); + if (i == -1) + { +#ifdef FILE_SKIP_FRAMES + // skip the frame in the file to simulate frame dropping... + fseek(m_file, m_buffers[0].size, SEEK_CUR); + DVP_PRINT(DVP_ZONE_WARNING, "WARNING: No usable buffers, skipping frame!\n"); +#endif + continue; // no free buffers + } + else // fill in the data + { + bytesRead = 0; + uint32_t j = 0, y = 0, z = 0; // don't use i + + pImage = (DVP_Image_t *)m_buffers[i].data; + + if (m_type == FILECAM_TYPE_RAW || m_type == FILECAM_TYPE_PYUV) + { + if (pImage->color == FOURCC_UYVY || + pImage->color == FOURCC_NV12 || + pImage->color == FOURCC_Y800) + { + size_t numBytes = pImage->x_stride * pImage->width; + DVP_PRINT(DVP_ZONE_CAM, "About to read File data into DVP_Image_t* %p {%p} stride=%u!\n",pImage, &(pImage->pData[0][j]),pImage->y_stride); + for (z = 0; z < pImage->planes; z++) + { + uint32_t readHeight = (pImage->color == FOURCC_NV12 && z==1) ? pImage->height/2 : pImage->height; + for (y = 0; y < readHeight; y++) + { + j = (y * pImage->y_stride); + if (m_file == NULL) + { + if(y<1) // Limit the warning to only 1 line per frame, instead of each line + DVP_PRINT(DVP_ZONE_WARNING, "WARNING: File %s does not exist, using GRAY image instead!\n", m_name); + memset(&(pImage->pData[z][j]), 0x80, numBytes); + bytesRead += numBytes; + } + else + { + bytesRead += fread(&(pImage->pData[z][j]), 1, numBytes, m_file); + } + } + } + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Color format not yet supported for file reader!\n"); + } + } + else if (m_type == FILECAM_TYPE_AVI) + { + bytesRead = avi_stream_parse(&movList, pImage); + } + DVP_PRINT(DVP_ZONE_CAM, "Read "FMT_SIZE_T" bytes from Camera (supposed to read "FMT_SIZE_T")\n",bytesRead,m_buffers[i].size); + } + + // fill in the frame values + pFrame->mFrameBuff = m_buffers[i].data; + pFrame->mCookie = m_cookie; + pFrame->mFd = 0; + pFrame->mHeight = m_height; + pFrame->mWidth = m_width; + pFrame->mLength = bytesRead; // m_buffers[i].size; + pFrame->mOffsetX = 0; + pFrame->mOffsetY = 0; + pFrame->mStartX = 0; + pFrame->mStartY = 0; + pFrame->mTimestamp = rtimer_now(); + m_buffers[i].used = 1; + + // pass it back to the client + if (m_callback) + { + m_callback(pFrame); + } + else + { + DVP_PRINT(DVP_ZONE_WARNING, "WARNING: Callback to camera has been unregistered\n"); + } + + // client should return it before the next timer....(hopefully) + } + delete pFrame; + DVP_PRINT(DVP_ZONE_CAM, "RunThread exiting!\n"); + return err; +} + +status_e FileVisionCam::setParameter(VisionCamParam_e paramId, void* param, uint32_t size,VisionCamPort_e port __attribute__ ((unused)) ) +{ + status_e status = STATUS_SUCCESS; + if (paramId == VCAM_PARAM_PATH) + strncpy(m_path, (char *)param, (size > MAX_PATH ? MAX_PATH : size)); + else + status = CameraEmulator::setParameter(paramId, param, size); + return status; +} + +status_e FileVisionCam::getParameter(VisionCamParam_e paramId, void* param, uint32_t size, VisionCamPort_e port __attribute__ ((unused)) ) +{ + status_e status = STATUS_SUCCESS; + if (paramId == VCAM_PARAM_PATH) + strncpy((char *)param, m_path, (size > MAX_PATH ? MAX_PATH : size)); + else + status = CameraEmulator::getParameter(paramId, param, size); + return status; +} + + diff --git a/source/dvp/VisionCam/FileVisionCam.h b/source/dvp/VisionCam/FileVisionCam.h new file mode 100644 index 0000000..a819d36 --- /dev/null +++ b/source/dvp/VisionCam/FileVisionCam.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _FILE_VISION_CAM_H_ +#define _FILE_VISION_CAM_H_ + +#include +#include + +typedef struct _avi_header_t { + fourcc_t riffcode; + uint32_t size; + fourcc_t typecode; +} AVI_Header_t; + +typedef struct _avi_list_t { + fourcc_t listcode; + uint32_t size; + fourcc_t typecode; +} AVI_List_t; + +typedef struct _avi_chunk_t { + fourcc_t chunkcode; + uint32_t size; +} AVI_Chunk_t; + +typedef struct _avi_mainheader_t { + uint32_t microSecPerFrame; + uint32_t maxBytesPerSec; + uint32_t paddingGranularity; + uint32_t flags; + uint32_t totalFrames; + uint32_t initialFrames; + uint32_t streams; + uint32_t suggestedBufferSize; + uint32_t width; + uint32_t height; + uint32_t reserved[4]; +} AVI_MainHeader_t; + +typedef struct _avistreamheader { + fourcc_t fccType; + fourcc_t fccHandler; + uint32_t flags; + uint16_t priority; + uint16_t language; + uint32_t initialFrames; + uint32_t scale; + uint32_t rate; + uint32_t start; + uint32_t length; + uint32_t suggestedBufferSize; + uint32_t quality; + uint32_t sampleSize; + struct { + short int left; + short int top; + short int right; + short int bottom; + } rcFrame; +} AVI_StreamHeader_t; + +typedef struct _avi_stream_tag_t { + uint16_t streamNum; + char streamType[2]; +} AVI_StreamTag_t; + +typedef enum _filecamtype_e { + FILECAM_TYPE_UNKNOWN, + FILECAM_TYPE_PYUV, // Use the PYUV Library to determine names and format info + FILECAM_TYPE_AVI, + FILECAM_TYPE_RAW, +} FileCamType_e; + +typedef enum _filecamparam_e { + FILECAM_PARAM_PATH = VCAM_PARAM_MAX, + FILECAM_PARAM_MAX, +} FileCamParam_e; + +class FileVisionCam : public CameraEmulator +{ +protected: + FILE *m_file; + FileCamType_e m_type; + char m_path[MAX_PATH]; + size_t m_fileSize; + + uint32_t avi_list_parse(AVI_List_t *aList); + uint32_t avi_chunk_parse(AVI_Chunk_t *aChunk); + uint32_t avi_header_parse(AVI_Header_t *aHeader); + uint32_t avi_stream_parse(AVI_List_t *aList, DVP_Image_t *pImage); + +public: + FileVisionCam(); + virtual ~FileVisionCam(); + + thread_ret_t RunThread(); + + status_e sendCommand(VisionCamCmd_e cmdId, void *param, uint32_t size, VisionCamPort_e port = VCAM_PORT_ALL ); + status_e setParameter(VisionCamParam_e paramId, void *param, uint32_t size, VisionCamPort_e port = VCAM_PORT_ALL ); + status_e getParameter(VisionCamParam_e paramId, void *param, uint32_t size, VisionCamPort_e port = VCAM_PORT_ALL ); +}; + +#endif + diff --git a/source/dvp/VisionCam/OMXVisionCam.cpp b/source/dvp/VisionCam/OMXVisionCam.cpp new file mode 100644 index 0000000..8335783 --- /dev/null +++ b/source/dvp/VisionCam/OMXVisionCam.cpp @@ -0,0 +1,4838 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#undef VCAM_SET_FORMAT_ROTATION + +#ifndef EXPORTED_3A +#define USE_WB_GAIN_PATCH // enable the hardcoded WB gain get/set apis +#endif // EXPORTED_3A + +#define USE_SMALC_FOR_STEREO // uncomment this to enable stereo misalignment correction +//#define USE_VSTAB_FOR_STEREO // uncomment this to enable video stabilization + +#ifdef USE_WB_GAIN_PATCH + #include "OMXVisionCam_WB_patch.h" +#endif + +//#define _USE_GAMMA_RESET_HC_ // enable the hard coded reset system for gamma tables + +#include "OMXVisionCam_Gamma_Tbl.h" + +#define HERE {printf("=======> OMX - %d <=======\n", __LINE__);fflush(stdout);} + +#ifdef USE_WB_GAIN_PATCH + #define RED 0 + #define GREEN_RED 1 + #define GREEN_BLUE 2 + #define BLUE 3 + + #define CALCULATE_WB_GAINS_OFFSET(type,in,out) out = (type *)(in + 4 + in[4] + in[8]) +#endif // USE_WB_GAIN_PATCH + +#ifndef EXPORTED_3A +#define GAMMA_TABLE_SIZE (1024*sizeof(uint16_t)) +#endif // EXPORTED_3A + +#define OMX_CHECK(error, function) {\ + error = function;\ + if (error != OMX_ErrorNone) {\ + DVP_PRINT(DVP_ZONE_ERROR, "OMX Error 0x%08x in "#function" on line # %u\n", error, __LINE__);\ + }\ +} + +#define OMX_CONVERT_RETURN_IF_ERROR(error, function) {\ + error = function;\ + if (error != OMX_ErrorNone) {\ + DVP_PRINT(DVP_ZONE_ERROR, "OMX Error 0x%08x in "#function" on line # %u\n", error, __LINE__);\ + return ConvertError(error);\ + }\ +} + +#define OMX_STRUCT_INIT(str, type, pVersion) {\ + memset(&str, 0, sizeof(type));\ + str.nSize = sizeof(type);\ + memcpy(&str.nVersion, pVersion, sizeof(OMX_VERSIONTYPE));\ + str.nPortIndex = OMX_ALL;\ +} + +#define OMX_STRUCT_INIT_PTR(ptr, type, pVersion) {\ + memset(ptr, 0, sizeof(type));\ + ptr->nSize = sizeof(type);\ + memcpy(&ptr->nVersion, pVersion, sizeof(OMX_VERSIONTYPE));\ + ptr->nPortIndex = OMX_ALL;\ +} + +#define LOOP_PORTS( port, cnt ) \ + for( cnt = ( VCAM_PORT_ALL == port ? VCAM_PORT_PREVIEW : port ); \ + cnt < ( VCAM_PORT_ALL == port ? VCAM_PORT_MAX : port + 1 ); \ + cnt++ \ + ) + +thread_ret_t FocusThreadLauncher(void *arg) +{ + OMXVisionCam *pCam = reinterpret_cast(arg); + pCam->waitForFocus(); + return 0; +} + +thread_ret_t PreemptionThreadLauncher( void *arg ) +{ + OMXVisionCam *pCam = reinterpret_cast(arg); + pCam->PreemptionService(); + return 0; +} + +thread_ret_t FrameThreadFunc(void *arg) +{ + bool_e run = true_e; + OMXVisionCam *pCam = (OMXVisionCam *)arg; + SimpleMsg_t msg; + + semaphore_create(&pCam->mFrameSem, 1, false_e); // set max count + semaphore_wait(&pCam->mFrameSem); // pre-decrement first time to get count to 0. + while(run) + { + semaphore_wait(&pCam->mFrameSem); + + memset(&msg, 0, sizeof(SimpleMsg_t)); + if( queue_read(pCam->mFrameMessageQ, true_e, &msg) ) + { + DVP_PRINT(DVP_ZONE_CAM, "Frame Recv Func got event %d\n",msg.event); + switch(msg.event) + { + case EFrameReceived: + pCam->frameReceivedSrvc(msg.data); + break; + case EFrameReturned: + break; + + case EFrameManagerExit: + run = false_e; + break; + + default: + break; + + } + } + } + semaphore_delete(&pCam->mFrameSem); + + return NULL; +} + +static void PrintOMXState(OMX_STATETYPE state) +{ + char *state_names[OMX_StateWaitForResources+1] = { + "OMX_StateInvalid", + "OMX_StateLoaded", + "OMX_StateIdle", + "OMX_StateExecuting", + "OMX_StatePause", + "OMX_StateWaitForResources" + }; + if ((uint32_t)state < dimof(state_names)) { + DVP_PRINT(DVP_ZONE_CAM, "OMX-CAMERA is in state %s\n", state_names[state]); + } +} + +OMX_U32 frameRates[] = {1, 5, 15, 24, 30, 60}; +OMX_U32 numFrameRates = dimof(frameRates); + + +/* Constructor - Open the Shared Library, containing the Camera Adapter and +* gen an instance of the Adapter. +*/ +OMXVisionCam::OMXVisionCam() +{ + m_callback = NULL; + m_focuscallback = NULL; + mutex_init(&mFrameBufferLock); + mutex_init(&mUserRequestLock); + mEventSignalQ = list_create(); + memset(&mCurGreContext, 0, sizeof(mCurGreContext)); +} + +status_e OMXVisionCam::init(void *cookie) +{ + mFlushInProcess = false_e; + OMX_ERRORTYPE omxError = OMX_ErrorNone; + status_e greError = STATUS_SUCCESS; + +#if TIME_PROFILE + PopulateTimeProfiler(); +#endif // TIME_PROFILE + + DVP_PRINT(DVP_ZONE_CAM, "OMXVisionCam::OMXVisionCam\n"); + DVP_PRINT(DVP_ZONE_CAM, "OMXVisionCam compiled: %s, %s\n\n", __DATE__, __TIME__ ); + mLocalVersion = new OMX_VERSIONTYPE(); + m_callback = NULL; + m_focuscallback = NULL; + + m_cookie = cookie; // save the cookie value; + + mLocalVersion->s.nVersionMajor = 1; + mLocalVersion->s.nVersionMinor = 1; + mLocalVersion->s.nRevision = 0 ; + mLocalVersion->s.nStep = 0; + + semaphore_create(&mGreLocalSem, 1, false_e); // set the max count + semaphore_wait(&mGreLocalSem); // pre-decrement the current count otherwise the first wait will pass early + semaphore_create(&mGreFocusSem, 1, false_e); // set the max count + semaphore_wait(&mGreFocusSem); // pre-decrement the current count otherwise the first wait will pass early + + // Initialize the Vision Core + DVP_PRINT(DVP_ZONE_CAM, "Calling OMX_Init()\n"); + OMX_CONVERT_RETURN_IF_ERROR(omxError, OMX_Init()); + + OMX_CALLBACKTYPE omxCallbacks; + omxCallbacks.EventHandler = OMXVisionCam::EventHandler; + omxCallbacks.EmptyBufferDone = OMXVisionCam::EmptyBufferDone; + omxCallbacks.FillBufferDone = OMXVisionCam::FillBufferDone; + + memset( &(mCurGreContext), 0, sizeof( VCAM_ComponentContext ) ); + + mCurGreContext.mPortsInUse[VCAM_PORT_ALL] = OMX_ALL; + mCurGreContext.mPortsInUse[VCAM_PORT_PREVIEW] = VCAM_CAMERA_PORT_VIDEO_OUT_PREVIEW; + mCurGreContext.mPortsInUse[VCAM_PORT_VIDEO] = VCAM_CAMERA_PORT_VIDEO_OUT_VIDEO; + + for( int i = VCAM_PORT_MIN; i < VCAM_PORT_MAX; i++ ) + { + mBuffersInUse[i].mBuffers = NULL; + mBuffersInUse[i].mNumberBuffers = 0; + mCurGreContext.mCameraPortParams[i].mIsActive = false_e; + mCurGreContext.mCameraPortParams[i].mColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + mCurGreContext.mCameraPortParams[i].mWidth = QVGA_WIDTH; + mCurGreContext.mCameraPortParams[i].mHeight = QVGA_HEIGHT; + mCurGreContext.mCameraPortParams[i].mFrameRate = INITIAL_FRAMERATE; + for(uint32_t buf = 0; buf < VCAM_NUM_BUFFERS; buf++ ) + mCurGreContext.mCameraPortParams[i].mBufferHeader[buf] = NULL; + mFrameDescriptors[i] = NULL; + } + + mCurGreContext.mHandleComp = NULL; + + getAvailableSensors(mDetectedSensors); + + DVP_PRINT(DVP_ZONE_CAM, "Calling OMX_GetHandle()\n"); + OMX_CONVERT_RETURN_IF_ERROR(omxError,OMX_GetHandle(&( mCurGreContext.mHandleComp ), + (OMX_STRING)"OMX.TI.DUCATI1.VIDEO.CAMERA", + this , + &omxCallbacks)); + GetDucatiVersion(); + + OMX_CONVERT_RETURN_IF_ERROR(omxError,OMX_SendCommand(mCurGreContext.mHandleComp, + OMX_CommandPortDisable, + OMX_ALL, + NULL)); + + +#if defined(BLAZE) || defined(SDP) || defined(BLAZE_TABLET) + { + OMX_U32 pr = 4; + + memcpy( &mVisionCamPriority.nVersion, mLocalVersion, sizeof(OMX_VERSIONTYPE)); + mVisionCamPriority.nGroupID = CAMERA_GROUP_ID; + mVisionCamPriority.nGroupPriority = pr; + mVisionCamPriority.nSize = sizeof(OMX_PRIORITYMGMTTYPE); + + omxError = OMX_SetParameter(mCurGreContext.mHandleComp, OMX_IndexParamPriorityMgmt ,&mVisionCamPriority); + } +#else + DVP_PRINT(DVP_ZONE_WARNING, "No Priority Management is enabled on this platform!\n"); +#endif + + mFrameMessageQ = queue_create( VCAM_NUM_BUFFERS * VCAM_PORT_MAX, sizeof(SimpleMsg_t)); + + mFrameThread = thread_create(FrameThreadFunc, this ); + mUseFramePackaging = false_e; + + m_frameNum = 0; + mPreemptionState = VCAM_PREEMPT_INACTIVE; + mFaceDetectionEnabled = VCAM_FACE_DETECTION_DISABLED; + mReturnToExecuting = false_e; +#ifdef _USE_GAMMA_RESET_HC_ + mGammaResetPolulated = false_e; +#endif // _USE_GAMMA_RESET_HC_ + + mPendingConfigs = new VisionCamExecutionService(this); + + return greError; +} + +status_e OMXVisionCam::deinit() +{ + status_e greError = STATUS_SUCCESS; + OMX_ERRORTYPE omxError = OMX_ErrorNone; + + // Free the handle for the Camera component + if (mCurGreContext.mHandleComp) + { + // free the handle + DVP_PRINT(DVP_ZONE_CAM, "Calling OMX_FreeHandle(0x%08x)\n", (unsigned)(mCurGreContext.mHandleComp)); + omxError = OMX_FreeHandle(mCurGreContext.mHandleComp); + greError = ConvertError(omxError); + mCurGreContext.mHandleComp = 0; + if( STATUS_SUCCESS != greError ) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: error freeing OMX handle.\nOMX_FreeHandle() returned 0x%x\n", omxError); + } + + // Deinitialize the OMX Core + DVP_PRINT(DVP_ZONE_CAM, "Calling OMX_Deinit()\n"); + omxError = OMX_Deinit(); + greError = ConvertError(omxError); + if( STATUS_SUCCESS != greError ) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: error in OMX_Deinit.OMX err: 0x%x\n", omxError); + } + } + + SimpleMsg_t msg; + msg.event = EFrameManagerExit; + msg.data = NULL; + queue_write(mFrameMessageQ, true_e, &msg); + semaphore_post(&mFrameSem); + thread_join(mFrameThread); + queue_destroy(mFrameMessageQ); + +#if TIME_PROFILE + for(int i = 0; i < VCAM_TIME_TARGET_MAX; i++) + if( mTimeProfiler[i] ) // dump and clear + delete mTimeProfiler[i]; +#endif + + if(mLocalVersion) + { + + delete mLocalVersion; + mLocalVersion = NULL; + } + + semaphore_delete(&mGreLocalSem); + semaphore_delete(&mGreFocusSem); + + if( mPendingConfigs ) + { + delete mPendingConfigs; + mPendingConfigs = NULL; + } + + return greError; +} + +/* Destructor - free all recources used by Vision Cam and from us */ +OMXVisionCam::~OMXVisionCam() +{ + list_destroy(mEventSignalQ); + mutex_deinit(&mFrameBufferLock); + mutex_deinit(&mUserRequestLock); + DVP_PRINT(DVP_ZONE_CAM, "OMX Vision Cam is destroyed!\n"); +} + +/** +* This is used to get esier the state of component. +*/ +inline OMX_STATETYPE OMXVisionCam::getComponentState() +{ + OMX_STATETYPE state = OMX_StateInvalid; + + if( mCurGreContext.mHandleComp ) + { + OMX_GetState( mCurGreContext.mHandleComp, &state ); + } + PrintOMXState(state); + return state; +} + +int32_t OMXVisionCam::getAvailableSensors(VCamSensorAvailable &s) +{ + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + bool_e gotHandle = (mCurGreContext.mHandleComp ? true_e : false_e ); + + OMX_CALLBACKTYPE omxCallbacks; + omxCallbacks.EventHandler = OMXVisionCam::EventHandler; + omxCallbacks.EmptyBufferDone = OMXVisionCam::EmptyBufferDone; + omxCallbacks.FillBufferDone = OMXVisionCam::FillBufferDone; + + VisionCamCaptureMode monoModes[] = { + VCAM_VIDEO_NORMAL, + VCAM_VIDEO_HIGH_SPEED, + VCAM_GESTURE_MODE + }; + + VisionCamCaptureMode stereoModes[] = { + VCAM_STEREO_MODE, +#ifdef OMX_CAMERA_SUPPORTS_STEREO_GESTURES + VCAM_STEREO_GEST_MODE, +#endif +#ifdef OMX_CAMERA_SUPPORTS_SIMULTANEOUS_SENSOR_GESTURES + VCAM_GESTURE_DUAL_SENSOR_MODE +#endif + }; + + enum { + mono, + stereo, + modesNum + }; + + struct targetMode { + int32_t numModes; + VisionCamCaptureMode *modes; + }; + + struct targetMode targetModes[modesNum]; + targetModes[mono].numModes = ARR_SIZE(monoModes); + targetModes[mono].modes = monoModes; + + targetModes[stereo].numModes = ARR_SIZE(stereoModes); + targetModes[stereo].modes = stereoModes; + /// @todo Must be tesetd on OMAP5 !!! + for( int32_t channelMode = mono; channelMode < modesNum; channelMode++ ) + { + // until this jod is done outside ducati, we could have a lot of issues here, + // because we don't have on what to rely while we are detecting connected sensors ! + // (it is just the ducati specification that is changing...) + // so we'll try to reduce iniproper detections as much as possible, but can never be sure + // that all will go smoothly with this code !!! + int32_t start = ((channelMode == mono) ? OMX_PrimarySensor : OMX_TI_StereoSensor); + int32_t end = (channelMode == mono ? OMX_SecondarySensor : OMX_TI_StereoSensor ); + for (int32_t sn = start; sn <= end; sn++) + { + if( mCurGreContext.mHandleComp == NULL ) + { + // Get a handle to OMX component. This is workaround needed due to some Ducati issues. + omxError = OMX_GetHandle(&( mCurGreContext.mHandleComp ), (OMX_STRING)"OMX.TI.DUCATI1.VIDEO.CAMERA", this , &omxCallbacks); + if( OMX_ErrorNone != omxError ) + { + DVP_PRINT(DVP_ZONE_ERROR, "%s returned error 0x%x at line %d\n", __func__, omxError, __LINE__); + } + } + + if( mCurGreContext.mHandleComp && OMX_ErrorNone == omxError ) + { + omxError = OMX_SendCommand(mCurGreContext.mHandleComp, OMX_CommandPortDisable, OMX_ALL, NULL); + if( OMX_ErrorNone != omxError ) + { + DVP_PRINT(DVP_ZONE_ERROR, "%s returned error 0x%x at line %d\n", __func__, omxError, __LINE__); + } + } + + if( mCurGreContext.mHandleComp && OMX_ErrorNone == omxError ) + { + OMX_CONFIG_SENSORSELECTTYPE sen; + OMX_STRUCT_INIT(sen, OMX_CONFIG_SENSORSELECTTYPE, mLocalVersion); + sen.nPortIndex = mCurGreContext.mPortsInUse[VCAM_PORT_ALL]; + sen.eSensor = (OMX_SENSORSELECT)sn; + + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigSensorSelect, &sen ); + + if( OMX_ErrorNone != omxError ) + { + DVP_PRINT(DVP_ZONE_ERROR, "%s returned error 0x%x at line %d\n", __func__, omxError, __LINE__); + continue; + } + + bool_e new_one = false_e; + for( int32_t opModeCounter = 0; opModeCounter < targetModes[channelMode].numModes; opModeCounter++ ) + { + OMX_CONFIG_CAMOPERATINGMODETYPE opMode; + memcpy( &opMode.nVersion, mLocalVersion, sizeof(OMX_VERSIONTYPE) ); + opMode.nSize = sizeof( OMX_CONFIG_CAMOPERATINGMODETYPE ); + opMode.eCamOperatingMode = (OMX_CAMOPERATINGMODETYPE)getLutValue( targetModes[channelMode].modes[opModeCounter], + VCAM_VALUE_TYPE, + CaptureModeLUT, + ARR_SIZE(CaptureModeLUT) + ); + + omxError = OMX_SetParameter( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_IndexCameraOperatingMode, &opMode ); + + if( OMX_ErrorNone != omxError ) + { + continue; + } + + if( OMX_ErrorNone == omxError ) + { + if (STATUS_SUCCESS != transitToState( OMX_StateIdle )) + { + omxError = OMX_ErrorIncorrectStateTransition; + } + } + + if (OMX_ErrorNone != omxError ) + { + continue; + } + + if( OMX_ErrorNone == omxError && (s.sensorCount < VCAM_Max_Supported_Sensor_Count )) + { + int32_t senInd = s.sensorCount; + int32_t modeInd = s.sensors[senInd].supportedModesCnt; + s.sensors[senInd].supportedModes[modeInd] = targetModes[channelMode].modes[opModeCounter]; + s.sensors[senInd].supportedModesCnt++; + + if( 1 == s.sensors[senInd].supportedModesCnt ) + { + new_one = true_e; + } + } + +#if GET_SENSOR_CAPS + if( OMX_ErrorNone == omxError ) + { + getSensorCaps(s.sensors[s.sensorCount]); + } +#endif // GET_SENSOR_CAPS + transitToState(OMX_StateLoaded); + + } + if( new_one ) + { + s.sensors[s.sensorCount].nIndex = sn; + s.sensorCount++; + } + } + + // Release OMX component handle + if( mCurGreContext.mHandleComp ) + { + OMX_FreeHandle(mCurGreContext.mHandleComp); + mCurGreContext.mHandleComp = NULL; + } + } + } + +#ifdef sen_dump + dumpDetectedSensors(); +#endif // sen_dump + + // keep the handle if it has been present when we entered this code. + if( gotHandle && mCurGreContext.mHandleComp == NULL ) + { + // Get a handle to OMX component. This is workaround needed due to some Ducati issues. + omxError = OMX_GetHandle(&( mCurGreContext.mHandleComp ), (OMX_STRING)"OMX.TI.DUCATI1.VIDEO.CAMERA", this , &omxCallbacks); + } + + return s.sensorCount; +} + +#ifdef sen_dump +void OMXVisionCam::dumpDetectedSensors() +{ + DVP_PRINT(DVP_ZONE_ALWAYS,"sensorCount = %d\n", mDetectedSensors.sensorCount); + for( int idxSensor = 0; idxSensor < mDetectedSensors.sensorCount; idxSensor++) + { + DVP_PRINT(DVP_ZONE_ALWAYS,"\tsensors[%d].nIndex \t\t\t= %d\n",idxSensor, mDetectedSensors.sensors[idxSensor].nIndex); + DVP_PRINT(DVP_ZONE_ALWAYS,"\tsensors[%d].supportedModesCnt \t\t\t= %d\n",idxSensor, mDetectedSensors.sensors[idxSensor].supportedModesCnt); + for(int idxMode = 0; idxMode < mDetectedSensors.sensors[idxSensor].supportedModesCnt; idxMode++) + { + DVP_PRINT(DVP_ZONE_ALWAYS,"\tsensors[%d].supportedModes[%d] \t\t\t= %d\n",idxSensor, idxMode, mDetectedSensors.sensors[idxSensor].supportedModes[idxMode]); + } + } +} +#endif // sen_dump + +/** +* Initialisation of OMX_PARAM_PORTDEFINITIONTYPE +* needed for various configurations +*/ +inline OMX_ERRORTYPE OMXVisionCam::initPortCheck( OMX_PARAM_PORTDEFINITIONTYPE * portCheck , OMX_U32 portIndex ) +{ + OMX_ERRORTYPE omxError = OMX_ErrorNone; + OMX_STRUCT_INIT_PTR(portCheck, OMX_PARAM_PORTDEFINITIONTYPE, mLocalVersion) + + if( VCAM_PORT_ALL < portIndex && VCAM_PORT_MAX > portIndex ) + { + portCheck->nPortIndex = mCurGreContext.mPortsInUse[portIndex]; + omxError = OMX_GetParameter(mCurGreContext.mHandleComp, + OMX_IndexParamPortDefinition, + portCheck); + DVP_PRINT(DVP_ZONE_CAM, "PORT CHECK[%u], E:%d P:%d B#:%u %ux%u C:%d\n", + (uint32_t)portCheck->nPortIndex, + portCheck->bEnabled, + portCheck->bPopulated, + (uint32_t)portCheck->nBufferCountActual, + (uint32_t)portCheck->format.video.nFrameWidth, + (uint32_t)portCheck->format.video.nFrameHeight, + portCheck->format.video.eColorFormat); + + } + else + omxError = OMX_ErrorBadParameter; + + if( omxError != OMX_ErrorNone ) + { + DVP_PRINT(DVP_ZONE_ERROR, "OMX_GetParameter - 0x%x in initPortCheck(%lu)\n", + omxError, mCurGreContext.mPortsInUse[portIndex]); + } + return omxError; +} +/** + @brief Method to convert from OMX_ERRORTYPE to GesturError_e + @param error Any of the standard OMX error codes defined in the OpenMAX 1.x Specification. + @return status_e + */ +status_e OMXVisionCam::ConvertError(OMX_ERRORTYPE error) +{ + status_e status = STATUS_SUCCESS; + switch(error) + { + case OMX_ErrorNone: + status = STATUS_SUCCESS; + break; + case OMX_ErrorBadParameter: + status = STATUS_INVALID_PARAMETER; + break; + case OMX_ErrorIncorrectStateOperation: + status = STATUS_INVALID_STATE; + break; + case OMX_ErrorHardware: + status = STATUS_CATASTROPHIC; + break; + default: + status = STATUS_FAILURE; + break; + } + if (error != OMX_ErrorNone) { + DVP_PRINT(DVP_ZONE_ERROR, "Converting OMX Error 0x%08x to status_e %d\n", error, status); + } + return status; +} + +int OMXVisionCam::getLutValue( int searchVal, ValueTypeOrigin origin, const int lut[][2], int lutSize) +{ + int idxToGet = (origin == VCAM_VALUE_TYPE ? OMX_VALUE_TYPE : VCAM_VALUE_TYPE ); + for( int i = 0; i < lutSize; i++ ) + { + if( lut[i][origin] == searchVal ) + return lut[i][idxToGet]; + } + + return STATUS_INVALID_PARAMETER; +} + +void OMXVisionCam::GetDucatiVersion() +{ + if( mCurGreContext.mHandleComp ) + { + OMX_VERSIONTYPE compVersion; + OMX_VERSIONTYPE specVersion; + char compName[128]; + OMX_UUIDTYPE compUUID[128]; + OMX_ERRORTYPE omxError = OMX_ErrorNone; + DVP_PRINT(DVP_ZONE_CAM, "Querying Component Version!\n"); + omxError = OMX_GetComponentVersion(mCurGreContext.mHandleComp, + compName, + &compVersion, + &specVersion, + compUUID); + if (omxError == OMX_ErrorNone) + { + DVP_PRINT(DVP_ZONE_CAM, "\tComponent Name: [%s]\n", compName); + DVP_PRINT(DVP_ZONE_CAM, "\tComponent Version: [%u]\n", (unsigned int)compVersion.nVersion); + DVP_PRINT(DVP_ZONE_CAM, "\tSpec Version: [%u]\n", (unsigned int)specVersion.nVersion); + DVP_PRINT(DVP_ZONE_CAM, "\tComponent UUID: [%s]\n\n", (char*)compUUID); + } + } +} + +status_e OMXVisionCam::transitToState(OMX_STATETYPE targetState, serviceFunc transitionService, void * data ) +{ + status_e greError = STATUS_SUCCESS; + OMX_ERRORTYPE omxError = OMX_ErrorNone; + semaphore_t sem; // this semaphore does not need to be global + + if( OMX_StateInvalid == targetState ) + return STATUS_INVALID_PARAMETER; + + semaphore_create(&sem, 1, false_e); + semaphore_wait(&sem); // predecrement so that the later wait will actually block + + omxError = RegisterForEvent( mCurGreContext.mHandleComp, + OMX_EventCmdComplete, + OMX_CommandStateSet, + targetState, + &sem, + -1 // Infinite timeout + ); + + if( OMX_ErrorNone == omxError ) + { + omxError = OMX_SendCommand( mCurGreContext.mHandleComp , + OMX_CommandStateSet, + targetState, + NULL ); + switch( omxError ) + { + case OMX_ErrorNone: + { + if( transitionService ) + { + greError = transitionService( this, data ); + } + break; + } + + case OMX_ErrorIncorrectStateTransition: + { + greError = STATUS_INVALID_PARAMETER; + break; + } + + case OMX_ErrorInsufficientResources: + { + if( OMX_StateIdle == targetState ) + { + mPreemptionState = VCAM_PREEMPT_WAIT_TO_START; + greError = PreemptionService(); + } + break; + } + + case OMX_ErrorSameState: + greError = STATUS_SUCCESS; + break; + + default: + greError = ConvertError(omxError); + break; + } + + if( greError != STATUS_SUCCESS || OMX_ErrorSameState == omxError ) + { + // unregister the event + EventHandler( mCurGreContext.mHandleComp, + this, + (OMX_EVENTTYPE)OMX_EventCmdComplete, + (OMX_U32)OMX_CommandStateSet, + (OMX_U32)targetState, + NULL + ); + } + else //( STATUS_SUCCESS == greError ) + { + DVP_PRINT(DVP_ZONE_CAM, "Waiting for state transition. State requested: %d\n", (int)targetState); + semaphore_wait(&sem); + DVP_PRINT(DVP_ZONE_CAM, "Camera is now in state %d\n", (int)targetState); + } + } + + semaphore_delete(&sem); + + return greError; +} + +status_e OMXVisionCam::portEnableDisable( OMX_COMMANDTYPE enCmd, serviceFunc enableService, VisionCamPort_e port ) +{ + status_e greError = STATUS_SUCCESS; + OMX_ERRORTYPE omxError = OMX_ErrorNone; + + OMX_PARAM_PORTDEFINITIONTYPE portCheck; + VCAM_PortParameters * portData = NULL; + + int32_t p; + LOOP_PORTS( port , p ) + { + initPortCheck(&portCheck, p); + portData = &mCurGreContext.mCameraPortParams[p]; + + // check to see if the port is already enabled/disabled and that we wanted that state + if( (OMX_TRUE == portCheck.bEnabled) && (enCmd == OMX_CommandPortEnable) ) + { + portData->mIsActive = true_e; + continue; + } + + if( (OMX_FALSE == portCheck.bEnabled) && (enCmd == OMX_CommandPortDisable) ) + { + portData->mIsActive = false_e; + continue; + } + + // we wanted to transition from one state to the other + + // ports with no buffers can't be enabled or disabled. + if( portData->mNumBufs == 0 && OMX_StateLoaded < getComponentState() ) + { + continue; + } + + // we have buffers, so enable/disable the port! + DVP_PRINT(DVP_ZONE_CAM, "Registering for port enable/disable event\n"); + omxError = RegisterForEvent( mCurGreContext.mHandleComp, + OMX_EventCmdComplete, + enCmd, + mCurGreContext.mPortsInUse[p], + &mGreLocalSem, + -1 /*Infinite timeout */ + ); + + if( OMX_ErrorNone == omxError ) + { + omxError = OMX_SendCommand( mCurGreContext.mHandleComp, + enCmd, + mCurGreContext.mPortsInUse[p], + NULL + ); + } + + if( enableService && OMX_ErrorNone == omxError ) + { + greError = enableService( this, (void*)(&p) ); + } + + if( OMX_ErrorNone == omxError && STATUS_SUCCESS == greError ) + { + semaphore_wait(&mGreLocalSem); + } + else + { + // unregister event + EventHandler( mCurGreContext.mHandleComp, + this, + (OMX_EVENTTYPE)OMX_EventCmdComplete, + (OMX_U32)enCmd, + (OMX_U32)mCurGreContext.mPortsInUse[p], + NULL + ); + } + + initPortCheck(&portCheck, p); + + if( OMX_TRUE == portCheck.bEnabled ) + { + portData->mIsActive = true_e; + mFramePackage.mExpectedFrames[p] = true_e; + } + else + { + portData->mIsActive = false_e; + mFramePackage.mExpectedFrames[p] = false_e; + } + } + + mCurGreContext.mCameraPortParams[VCAM_PORT_ALL].mIsActive = true_e; + int32_t p2; + LOOP_PORTS(VCAM_PORT_ALL, p2) + { + if( mCurGreContext.mCameraPortParams[p2].mIsActive == false_e ) + { + mCurGreContext.mCameraPortParams[VCAM_PORT_ALL].mIsActive = false_e; + break; + } + } + + return greError; +} + +status_e OMXVisionCam::fillPortBuffers( VisionCamPort_e port ) +{ + status_e greError = STATUS_SUCCESS; + OMX_ERRORTYPE omxError = OMX_ErrorNone; + VCAM_PortParameters *portData = NULL; + + portData = &mCurGreContext.mCameraPortParams[port]; + if (portData->mIsActive == true_e) + { + + for( int index = 0; index < portData->mNumBufs; index++ ) + { + if( portData && portData->mBufferHeader[index] ) + { + DVP_PRINT(DVP_ZONE_CAM, "FILL BUFF HDR[%d]:%p PORT:%u\n", index, portData->mBufferHeader[index], (uint32_t)mCurGreContext.mPortsInUse[port]); + omxError = OMX_FillThisBuffer(mCurGreContext.mHandleComp, + (OMX_BUFFERHEADERTYPE*)( portData->mBufferHeader[index])); + if (omxError != OMX_ErrorNone) + { + DVP_PRINT(DVP_ZONE_ERROR, "OMX_FillThisBuffer() returned error 0x%x\n", omxError ); + greError = ConvertError(omxError); + break; + } + } + else + { + greError = STATUS_NO_RESOURCES; // STATUS_NO_MAPPING; + } + } + } + else + { + greError = STATUS_NO_RESOURCES; // can't fill a port that isn't active + } + if (omxError != OMX_ErrorNone) + { + greError = ConvertError(omxError); + } + + return greError; +} + +status_e OMXVisionCam::freePortBuffers( VisionCamPort_e port ) +{ + status_e greError = STATUS_SUCCESS; + OMX_ERRORTYPE omxError = OMX_ErrorNone; + VCAM_PortParameters *portData = NULL; + + SOSAL::AutoLock lock( &mFrameBufferLock ); + + int32_t p; + LOOP_PORTS( port , p ) + { + portData = &mCurGreContext.mCameraPortParams[p]; + for( int buff = 0; buff < portData->mNumBufs; buff++ ) + { + omxError = OMX_FreeBuffer( mCurGreContext.mHandleComp, + mCurGreContext.mPortsInUse[p], + portData->mBufferHeader[buff] + ); + portData->mBufferHeader[buff] = NULL; + if (omxError != OMX_ErrorNone) + { + DVP_PRINT(DVP_ZONE_ERROR, "OMX_FreeBuffer() returned error 0x%x\n", omxError ); + greError = ConvertError(omxError); + break; + } + } + } + + return greError; +} + +status_e OMXVisionCam::populatePort( VisionCamPort_e port ) +{ + status_e greError = STATUS_SUCCESS; + OMX_ERRORTYPE omxError = OMX_ErrorNone; + VCAM_PortParameters * data = NULL; + + int32_t p; + LOOP_PORTS( port , p ) + { +#if defined(DVP_USE_GRALLOC) || defined(DVP_USE_ION) + // @NOTE in ICS/JB, we have to send "gralloc" buffers which may be TILER 2D or SGX buffers + OMX_TI_PARAMUSENATIVEBUFFER useNativeHandles; + OMX_STRUCT_INIT(useNativeHandles, OMX_TI_PARAMUSENATIVEBUFFER, mLocalVersion); + useNativeHandles.nPortIndex = mCurGreContext.mPortsInUse[p]; + useNativeHandles.bEnable = OMX_TRUE; + omxError = OMX_SetParameter(mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexUseNativeBuffers, &useNativeHandles); + DVP_PRINT(DVP_ZONE_CAM, "Configuring port %u for GRALLOC/ION handles (err=0x%08x)\n", p, omxError); +#elif defined(DVP_USE_BO) + OMX_TI_PARAM_USEBUFFERDESCRIPTOR desc; + OMX_STRUCT_INIT(desc, OMX_TI_PARAM_USEBUFFERDESCRIPTOR, mLocalVersion); + // No idea + desc.nPortIndex = mCurGreContext.mPortsInUse[p]; + // For 2D buffer + desc.bEnabled = OMX_FALSE; + omxError = OMX_SetParameter(mCurGreContext.mHandleComp, (OMX_INDEXTYPE) OMX_TI_IndexUseDmaBuffers, &desc); + DVP_PRINT(DVP_ZONE_CAM, "Configuring port %u for DMAbuf handles (err=0x%08x)\n", p, omxError); +#endif + data = &mCurGreContext.mCameraPortParams[p]; + + for( int indBuff = 0; indBuff < data->mNumBufs; indBuff++ ) + { + OMX_BUFFERHEADERTYPE *pBufferHdr = NULL; + OMX_U8 *buffer = NULL; +#if defined(DVP_USE_BO) + OMX_S32 fds[DVP_MAX_PLANES]; + OMX_U32 i; + alloc_omap_bo_t **bos = NULL; + + memset(fds, 0, sizeof(fds)); +#endif + + DVP_PrintImage(DVP_ZONE_CAM, &mBuffersInUse[p].mBuffers[indBuff]); +#if defined(DVP_USE_GRALLOC) || defined(DVP_USE_ION) + // Pull the handle (Gralloc or ION) out of the DVP_Image_t structure reserved + buffer = (OMX_U8 *)mBuffersInUse[p].mBuffers[indBuff].reserved; + + DVP_PRINT(DVP_ZONE_CAM, "VCAM: Using GRALLOC/ION handle %p\n", buffer); +#elif defined(DVP_USE_BO) + bos = (alloc_omap_bo_t **)mBuffersInUse[p].mBuffers[indBuff].reserved; + for (i = 0; i < mBuffersInUse[p].mBuffers[indBuff].planes; i++) + fds[i] = bos[i]->dmabuf_fd; + buffer = (OMX_U08 *)fds; + DVP_PRINT(DVP_ZONE_CAM, "VCAM: Passing DMAbuf FDs in %p\n", buffer); +#endif + omxError = OMX_UseBuffer( mCurGreContext.mHandleComp, + &pBufferHdr, + mCurGreContext.mPortsInUse[p], + 0, + data->mBufSize, + buffer); + + if( OMX_ErrorNone != omxError ) + { + DVP_PRINT(DVP_ZONE_ERROR, "VCAM: ERROR: OMX_UseBuffer() returned 0x%x ( %d )\n", omxError, omxError); + greError = ConvertError(omxError); + break; + } + + pBufferHdr->pAppPrivate = (OMX_PTR)&mBuffersInUse[p].mBuffers[indBuff]; + pBufferHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); + memcpy( &(pBufferHdr->nVersion), mLocalVersion, sizeof( OMX_VERSIONTYPE ) ); + + data->mBufferHeader[indBuff] = pBufferHdr; + + if( NULL == mFrameDescriptors[p][indBuff]->mFrameBuff ) + mFrameDescriptors[p][indBuff]->mFrameBuff = pBufferHdr->pAppPrivate; + } + } + + return greError; +} + +status_e OMXVisionCam::useBuffers( DVP_Image_t *pImages, uint32_t numImages, VisionCamPort_e port ) +{ + status_e greError = STATUS_SUCCESS; + + if ( pImages == NULL || numImages == 0 || port <= VCAM_PORT_ALL || port >= VCAM_PORT_MAX) + { + DVP_PRINT(DVP_ZONE_ERROR, "Invalid parameters to useBuffers()\n"); + return STATUS_INVALID_PARAMETER; + } + + // alloc the array for frame descriptors + if( !mFrameDescriptors[port] ) + { + mFrameDescriptors[port] = new VisionCamFrame* [numImages]; + if( NULL == mFrameDescriptors[port] ) + { + greError = STATUS_NOT_ENOUGH_MEMORY; + } + + for( uint32_t i = 0; i < numImages && STATUS_SUCCESS == greError; i++ ) + { + mFrameDescriptors[port][i] = new VisionCamFrame(); + + if( mFrameDescriptors[port][i] ) + { + mFrameDescriptors[port][i]->clear(); + } + else + { + while( i ) + delete mFrameDescriptors[port][--i]; + + delete [] mFrameDescriptors[port]; + mFrameDescriptors[port] = NULL; + + greError = STATUS_NOT_ENOUGH_MEMORY; + } + } + } + + if( STATUS_SUCCESS == greError ) + { + VCAM_PortParameters * data = &mCurGreContext.mCameraPortParams[port]; + + mBuffersInUse[port].mBuffers = pImages; + mBuffersInUse[port].mNumberBuffers = (uint32_t)numImages; + + data->mNumBufs = mBuffersInUse[port].mNumberBuffers; + data->mStride = mBuffersInUse[port].mBuffers[0].y_stride; + + if( OMX_StateIdle != getComponentState() ) + { + greError = transitToState( OMX_StateIdle ); + } + } + + return greError; +} + +status_e OMXVisionCam::flushBuffers( VisionCamPort_e port) +{ + status_e greError = STATUS_SUCCESS; + OMX_ERRORTYPE omxError = OMX_ErrorNone; + + if( OMX_StateExecuting != getComponentState() ) + { + return greError; + } + + int32_t p; + LOOP_PORTS( port , p ) + { + semaphore_t sem; + semaphore_create(&sem, 1, false_e ); + semaphore_wait(&sem); // predecrement so that the next wait won't fire ahead of time. + omxError = RegisterForEvent(mCurGreContext.mHandleComp, + OMX_EventCmdComplete, + OMX_CommandFlush, + mCurGreContext.mPortsInUse[p], + &sem, + -1 /*Infinite timeout*/ + ); + + if( OMX_ErrorNone == omxError ) + { + omxError = OMX_SendCommand( mCurGreContext.mHandleComp, + OMX_CommandFlush, + mCurGreContext.mPortsInUse[p], + NULL ); + } + + if( OMX_ErrorNone == omxError ) + { + semaphore_wait(&sem); + } + + semaphore_delete(&sem); + } + return greError; +} + +/* Send command to Camera */ +status_e OMXVisionCam::sendCommand( VisionCamCmd_e cmdId, void *param, uint32_t size, VisionCamPort_e port) +{ + status_e greError = STATUS_SUCCESS; + OMX_ERRORTYPE omxError = OMX_ErrorNone; + + SOSAL::AutoLock lock( &mUserRequestLock ); + + size = size; // warnings + DVP_PRINT(DVP_ZONE_CAM, "SEND CMD: 0x%04x, %p, "FMT_SIZE_T", %d\n", cmdId, param, size, port); + + switch (cmdId) + { + case VCAM_CMD_PREVIEW_START: + { + greError = startPreview(port); + break; + } + + case VCAM_CMD_PREVIEW_STOP: + { + if( OMX_StateExecuting == getComponentState() ) + greError = stopPreview(port); + else + greError = STATUS_INVALID_STATE; + break; + } + + case VCAM_EXTRA_DATA_START: + { + int i, EDataType; + for( i = 0; i < VCAM_EXTRA_DATA_TYPE_MAX; i++ ) + { + if( ExtraDataTypeLUT[ i ][ 0 ] == *( (int32_t*)param ) ) + { + EDataType = ExtraDataTypeLUT[ i ][ 1 ]; + break; + } + } + if( i == VCAM_EXTRA_DATA_TYPE_MAX ) + { + greError = STATUS_INVALID_PARAMETER; + break; + } + + OMX_CONFIG_EXTRADATATYPE xData; + OMX_STRUCT_INIT(xData, OMX_CONFIG_EXTRADATATYPE, mLocalVersion); +#if defined(OMX_CAMERA_SUPPORTS_CAMERA_VIEW) + xData.eCameraView = OMX_2D_Prv; +#endif + if( OMX_ExtraDataNone == EDataType ) + { + for( int i = 1; i < VCAM_EXTRA_DATA_TYPE_MAX; i++ ) + {// stop extra data transfer for all types of data + if( STATUS_SUCCESS == greError ) + { + xData.eExtraDataType = (OMX_EXT_EXTRADATATYPE)ExtraDataTypeLUT[i][1]; + xData.bEnable = OMX_FALSE; + int32_t p; + LOOP_PORTS( port, p ) + { + xData.nPortIndex = p; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, ( OMX_INDEXTYPE )OMX_IndexConfigOtherExtraDataControl, &xData); + } + } + } + } + else + { + if( STATUS_SUCCESS == greError ) + { + xData.eExtraDataType = ( OMX_EXT_EXTRADATATYPE )EDataType; + xData.bEnable = OMX_TRUE; + + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, ( OMX_INDEXTYPE )OMX_IndexConfigOtherExtraDataControl, &xData); + } + } + break; + } + + case VCAM_EXTRA_DATA_STOP: + { + int i, EDataType; + for( i = 0; i < VCAM_EXTRA_DATA_TYPE_MAX; i++ ) + { + if( ExtraDataTypeLUT[ i ][ 0 ] == *( (int*)param ) ) + { + EDataType = ExtraDataTypeLUT[ i ][ 1 ]; + break; + } + } + if( i == VCAM_EXTRA_DATA_TYPE_MAX ) + { + greError = STATUS_INVALID_PARAMETER; + break; + } + + OMX_CONFIG_EXTRADATATYPE xData; + OMX_STRUCT_INIT(xData, OMX_CONFIG_EXTRADATATYPE, mLocalVersion); +#if defined(OMX_CAMERA_SUPPORTS_CAMERA_VIEW) + xData.eCameraView = OMX_2D_Prv; +#endif + if( OMX_ExtraDataNone == EDataType ) + { + for( int i = 1; i < VCAM_EXTRA_DATA_TYPE_MAX; i++ ) + { + // greError = OMX_GetConfig( mCurGreContext.mHandleComp, ( OMX_INDEXTYPE )OMX_IndexConfigOtherExtraDataControl, &xData); + if( STATUS_SUCCESS == greError ) + { + xData.eExtraDataType = (OMX_EXT_EXTRADATATYPE)ExtraDataTypeLUT[i][1]; + xData.bEnable = OMX_FALSE; + int32_t p; + LOOP_PORTS(port, p) + { + xData.nPortIndex = p; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, ( OMX_INDEXTYPE )OMX_IndexConfigOtherExtraDataControl, &xData); + } + } + } + } + else + { + if( STATUS_SUCCESS == greError ) + { + xData.eExtraDataType = ( OMX_EXT_EXTRADATATYPE )EDataType; +// greError = OMX_GetConfig( mCurGreContext.mHandleComp, ( OMX_INDEXTYPE )OMX_IndexConfigOtherExtraDataControl, &xData); + + xData.bEnable = OMX_FALSE; + + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, ( OMX_INDEXTYPE )OMX_IndexConfigOtherExtraDataControl, &xData); + } + } + break; + } + + case VCAM_CMD_LOCK_AE: + case VCAM_CMD_LOCK_AWB: + { + OMX_INDEXTYPE index; + OMX_IMAGE_CONFIG_LOCKTYPE lockCfg; + OMX_STRUCT_INIT(lockCfg, OMX_IMAGE_CONFIG_LOCKTYPE, mLocalVersion); + if (VCAM_CMD_LOCK_AE == cmdId) + { + index = (OMX_INDEXTYPE)OMX_IndexConfigImageExposureLock; + } + else if (VCAM_CMD_LOCK_AWB == cmdId) + { + index = (OMX_INDEXTYPE)OMX_IndexConfigImageWhiteBalanceLock; + } + else + { + greError = STATUS_INVALID_PARAMETER; + break; + } + OMX_GetConfig(mCurGreContext.mHandleComp, index, &lockCfg); + lockCfg.bLock = *((OMX_BOOL*)param); + OMX_SetConfig(mCurGreContext.mHandleComp, index, &lockCfg); + break; + } +#if TIME_PROFILE + case VCAM_DUMP_TIMES: + { + for( int i = 0; i < VCAM_TIME_TARGET_MAX; i++ ) + if( mTimeProfiler[i] ) + mTimeProfiler[i]->dump(); + break; + } +#endif // TIME_PROFILE + case VCAM_CMD_FACE_DETECTION: + { + if( *((bool_e*)(param)) ) + { + mFaceDetectionEnabled |= (int32_t)VCAM_FACE_DETECTION; + } + else + { + mFaceDetectionEnabled &= (int32_t)(~VCAM_FACE_DETECTION); + } + + enableFaceDetect(port, VCAM_FACE_DETECTION); + break; + } + + case VCAM_CMD_FACE_DETECTION_RAW: + { + if( *((bool_e*)(param)) ) + { + mFaceDetectionEnabled |= (int32_t)VCAM_FACE_DETECTION_RAW; + } + else + { + mFaceDetectionEnabled &= (int32_t)(~VCAM_FACE_DETECTION_RAW); + } + + enableFaceDetect(port, VCAM_FACE_DETECTION_RAW); + + break; + } +#if ( defined(DUCATI_1_5) || defined(DUCATI_2_0) ) && defined(OMX_CAMERA_SUPPORTS_MANUAL_CONTROLS) + case VCAM_CMD_FREEZE_AWB_PARAMS: + { + OMX_TI_CONFIG_FREEZE_AWB wbFreeze; + OMX_STRUCT_INIT( wbFreeze, OMX_TI_CONFIG_FREEZE_AWB, mLocalVersion); + wbFreeze.nTimeDelay = *((uint32_t*)param); + + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigFreezeAWB, &wbFreeze ); + break; + } + + case VCAM_CMD_FREEZE_AGC_PARAMS: + { + OMX_TI_CONFIG_FREEZE_AE aeFreeze; + OMX_STRUCT_INIT( aeFreeze, OMX_TI_CONFIG_FREEZE_AE, mLocalVersion); + aeFreeze.nTimeDelay = *((uint32_t*)param); + + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigFreezeAutoExp, &aeFreeze ); + break; + } +#endif + case VCAM_CMD_SET_CLIENT_NOTIFICATION_CALLBACK: + { + mClientNotifier.mNotificationCallback = (VisionCamClientNotifier::VisionCamClientNotifierCallback)(param); + break; + } + + case VCAM_CMD_PACK_FRAMES: + { + mUseFramePackaging = *((bool_e*)param); + break; + } + + default: + { + DVP_PRINT(DVP_ZONE_ERROR, "Impossible command id requested: %d\n", cmdId); + DVP_PRINT(DVP_ZONE_ERROR, "see VisionCamParam_e for possible command ids\n"); + greError = STATUS_INVALID_PARAMETER; + } + } + + if (greError == STATUS_SUCCESS) + greError = ConvertError(omxError); + + if (greError != STATUS_SUCCESS) + { + DVP_PRINT(DVP_ZONE_ERROR, "OMXVisionCam::sendCommand() exits with error %d for command id %d\n", greError, cmdId); + } + + return greError; +} + +/* +* APIs to configure Vision Cam +*/ +status_e OMXVisionCam::setParameter( VisionCamParam_e paramId, void* param, uint32_t size, VisionCamPort_e port) +{ + status_e greError = STATUS_SUCCESS; + OMX_ERRORTYPE omxError = OMX_ErrorNone; + + SOSAL::AutoLock lock( &mUserRequestLock ); + + if (param == NULL || size == 0 || port >= VCAM_PORT_MAX) + { + DVP_PRINT(DVP_ZONE_ERROR, "NULL param pointer passed to %s()\n",__func__); + return STATUS_INVALID_PARAMETER; + } + else + { + DVP_PRINT(DVP_ZONE_CAM, "SET PARAM: 0x%04x, %p, "FMT_SIZE_T" (0x%08x), %d\n", paramId, param, size, (size==4?*(uint32_t *)param:0), port); + } + + if (getComponentState() == OMX_StateInvalid) + return STATUS_INVALID_STATE; + + switch( paramId ) + { + case VCAM_PARAM_HEIGHT: + { + int32_t p; + LOOP_PORTS( port , p ) + mCurGreContext.mCameraPortParams[p].mHeight = *((OMX_U32*)param); + break; + } + + case VCAM_PARAM_WIDTH: + { + int32_t p; + LOOP_PORTS( port , p ) + mCurGreContext.mCameraPortParams[p].mWidth = *((OMX_U32*)param); + break; + } + + + case VCAM_PARAM_COLOR_SPACE_FOURCC: + { + greError = setColorSpace(param, size, port); + break; + } + + case VCAM_PARAM_DO_AUTOFOCUS: + { + greError = startAutoFocus( *((VisionCamFocusMode*)param) ); + break; + } + + case VCAM_PARAM_DO_MANUALFOCUS: + { + mManualFocusDistance = *((uint32_t*)param); + greError = startAutoFocus( VCAM_FOCUS_CONTROL_ON ); + break; + } + + case VCAM_PARAM_BRIGHTNESS: + { + greError = setBrightness(param, size, port); + break; + } + + case VCAM_PARAM_CONTRAST: + { + greError = setContrast(param, size, port); + break; + } + + case VCAM_PARAM_SHARPNESS: + { + greError = setSharpness(param, size, port); + break; + } + + case VCAM_PARAM_SATURATION: + { + greError = setSaturation(param, size, port); + break; + } + + case VCAM_PARAM_FPS_FIXED: + { + greError = setFrameRate_Fixed(param, size, port); + break; + } + + case VCAM_PARAM_FPS_VAR: + { + greError = setFrameRate_Variable(param, size, port); + break; + } + + case VCAM_PARAM_FLICKER: + { + greError = setFlicker(param, size, port); + break; + } + + case VCAM_PARAM_CROP: + { + greError = setCrop(param, size, port); + break; + } + + case VCAM_PARAM_STEREO_INFO: + { + greError = setStereoInfo(param, size, port); + break; + } + + case VCAM_PARAM_CAP_MODE: + { + greError = setCameraOperatingMode(param, size, port ); + break; + } + + case VCAM_PARAM_SENSOR_SELECT: + { + greError = setSensor(param, size, port); + break; + } + + case VCAM_PARAM_EXPOSURE_COMPENSATION: + { + greError = setExposureCompensation(param, size, port ); + break; + } + + case VCAM_PARAM_RESOLUTION: + { + greError = setResolution (param, size, port); + break; + } + + case VCAM_PARAM_MANUAL_EXPOSURE: + { + greError = setManualExporureTime(param, size, port); + break; + } + + case VCAM_PARAM_EXPOSURE_ISO: + { + greError = setISO(param, size, port); + break; + } + + case VCAM_PARAM_AWB_MODE: + { + greError = setWhiteBalanceMode(param, size, port); + break; + } + + case VCAM_PARAM_COLOR_TEMP: + { + + greError = setColorTemp(param, size, port); + break; + } +#ifndef EXPORTED_3A + case VCAM_PARAM_WB_COLOR_GAINS: + { +#ifdef USE_WB_GAIN_PATCH + VisionCamWhiteBalGains wbGains = *((VisionCamWhiteBalGains*)param); + uint16_t * tmp; + CALCULATE_WB_GAINS_OFFSET(uint16_t,mWBbuffer,tmp); + + tmp[ RED ] = wbGains.mRed; + tmp[ GREEN_RED ] = wbGains.mGreen_r; + tmp[ GREEN_BLUE ] = wbGains.mGreen_b; + tmp[ BLUE ] = wbGains.mBlue; + + OMX_TI_CONFIG_SHAREDBUFFER skipBuffer; + skipBuffer.nSize = sizeof( OMX_TI_CONFIG_SHAREDBUFFER ); + memcpy( &skipBuffer.nVersion , mLocalVersion , sizeof(OMX_VERSIONTYPE) ); + + if( wbGains.mRed >= COLOR_GAIN_MIN && wbGains.mRed <= COLOR_GAIN_MAX + && wbGains.mGreen_b >= COLOR_GAIN_MIN && wbGains.mGreen_b <= COLOR_GAIN_MAX + && wbGains.mGreen_r >= COLOR_GAIN_MIN && wbGains.mGreen_r <= COLOR_GAIN_MAX + && wbGains.mBlue >= COLOR_GAIN_MIN && wbGains.mBlue <= COLOR_GAIN_MAX ) + { + skipBuffer.pSharedBuff = (OMX_U8*)mWBbuffer; + skipBuffer.nSharedBuffSize = sizeof(mWBbuffer); + } + else if( !wbGains.mRed && !wbGains.mGreen_b && !wbGains.mGreen_r && !wbGains.mBlue ) + { /// all gains are zero => auto mode + skipBuffer.pSharedBuff = (OMX_U8*)mWBresetBuffer; + skipBuffer.nSharedBuffSize = sizeof(mWBresetBuffer); + } + else + { + greError = STATUS_INVALID_PARAMETER; + break; + } + + int32_t p = port; +// LOOP_PORTS(port, p) + { + skipBuffer.nPortIndex = p; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, + (OMX_INDEXTYPE) OMX_TI_IndexConfigAAAskipBuffer, + &skipBuffer ); + } +#endif // USE_WB_GAIN_PATCH + break; + } + + case VCAM_PARAM_GAMMA_TBLS: + { + VisionCamGammaTableType *gammaTbl = (VisionCamGammaTableType*)(param); + OMX_TI_CONFIG_SHAREDBUFFER skipBuffer; + OMX_STRUCT_INIT(skipBuffer, OMX_TI_CONFIG_SHAREDBUFFER, mLocalVersion); + + uint32_t* base = (uint32_t *)(mGammaTablesBuf + 12); // 12 bytes offset for first table + uint16_t *redTbl = (uint16_t*)(base[0] + (uint32_t)&base[2]); + uint16_t *blueTbl = (uint16_t*)(base[1] + (uint32_t)&base[2]); + uint16_t *greenTbl = (uint16_t*)(base[2] + (uint32_t)&base[2]); + +#ifdef _USE_GAMMA_RESET_HC_ + if( !mGammaResetPolulated ) + { + skipBuffer.pSharedBuff = (OMX_U8*)mGammaResetTablesBuf; + skipBuffer.nSharedBuffSize = sizeof(mGammaResetTablesBuf); + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, + (OMX_INDEXTYPE) OMX_TI_IndexConfigAAAskipBuffer, + &skipBuffer ); + + if( OMX_ErrorNone == omxError ) + mGammaResetPolulated = true; + } +#endif // _USE_GAMMA_RESET_HC_ + + if( gammaTbl->mRedTable && gammaTbl->mGreenTable && gammaTbl->mBlueTable ) + { + if( gammaTbl->mRedTable != redTbl ) + { + memcpy(redTbl, gammaTbl->mRedTable, GAMMA_TABLE_SIZE ); + } + + if( gammaTbl->mGreenTable != greenTbl ) + { + memcpy(greenTbl, gammaTbl->mGreenTable, GAMMA_TABLE_SIZE ); + } + + if( gammaTbl->mBlueTable != blueTbl ) + { + memcpy(blueTbl, gammaTbl->mBlueTable, GAMMA_TABLE_SIZE ); + } + + skipBuffer.pSharedBuff = (OMX_U8*)mGammaTablesBuf; + skipBuffer.nSharedBuffSize = sizeof(mGammaTablesBuf)/sizeof(mGammaTablesBuf[0]); + } + else + { +#ifdef _USE_GAMMA_RESET_HC_ + if( mGammaResetPolulated ) + { + skipBuffer.pSharedBuff = (OMX_U8*)mGammaResetTablesBuf; + skipBuffer.nSharedBuffSize = sizeof(mGammaResetTablesBuf)/sizeof(mGammaResetTablesBuf[0]); + } + else + { + DVP_PRINT(DVP_ZONE_WARNING, "No data present in reset Gamma Tables. Leaving Gamma unchanged!!!"); + } +#else + skipBuffer.pSharedBuff = (OMX_U8*)mGammaResetTablesBuf; + skipBuffer.nSharedBuffSize = sizeof(mGammaResetTablesBuf)/sizeof(mGammaResetTablesBuf[0]); +#endif // _USE_GAMMA_RESET_HC_ + } + + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, + (OMX_INDEXTYPE) OMX_TI_IndexConfigAAAskipBuffer, + &skipBuffer ); + + break; + } +#endif // not defined EXPORTED_3A + +#if defined(VCAM_SET_FORMAT_ROTATION) + case VCAM_PARAM_ROTATION: + { + int32_t p; + LOOP_PORTS( port , p ) + { + mCurGreContext.mCameraPortParams[p].mRotation = *((OMX_S32 *)param); + } + break; + } +#else + case VCAM_PARAM_ROTATION: + { + OMX_CONFIG_ROTATIONTYPE rotation; + OMX_STRUCT_INIT(rotation, OMX_CONFIG_ROTATIONTYPE, mLocalVersion); + rotation.nRotation = *((OMX_S32*)param); + + int32_t p; + LOOP_PORTS( port , p ) + { + rotation.nPortIndex = mCurGreContext.mPortsInUse[p]; + OMX_CHECK(omxError, OMX_SetConfig(mCurGreContext.mHandleComp, + OMX_IndexConfigCommonRotate, + &rotation)); + DVP_PRINT(DVP_ZONE_CAM, "Setting Rotation to %ld (size: %u)\n", rotation.nRotation, sizeof(rotation)); + } + break; + } +#endif + case VCAM_PARAM_MIRROR: + { + /// @todo test Mirror again (because ot the getLutvalue() usage) + greError = setMirror(param, size, port); + break; + } + +#if ( defined(DUCATI_1_5) || defined(DUCATI_2_0) ) && defined(OMX_CAMERA_SUPPORTS_MANUAL_CONTROLS) + case VCAM_PARAM_AWB_MIN_DELAY_TIME: + { + greError = setAWBminDelayTime(param, size, port); + break; + } + + case VCAM_PARAM_GESTURES_INFO: + { + greError = setGestureInfo(param, size, port); + break; + } + + case VCAM_PARAM_AGC_MIN_DELAY_TIME: + { + greError = setAGC_MinimumDelay(param, size, port); + break; + } + + case VCAM_PARAM_AGC_LOW_TH: + { + greError = setAGC_LowThreshold(param, size, port); + break; + } + case VCAM_PARAM_AGC_HIGH_TH: + { + greError = setAGC_HighThreshold(param, size, port); + break; + } +#endif + case VCAM_PARAM_NAME: + // do nothing as this is not supported but it should not fail either + break; + +#ifdef EXPORTED_3A + case VCAM_PARAM_EXPORTED_3A_HOLD: + { + greError = m3A_Export.hold_3A(); + break; + } + + case VCAM_PARAM_EXPORTED_3A_SET: + { + VisionCam_3Asettings_Base_t* p = (VisionCam_3Asettings_Base_t* )param; + greError = m3A_Export.set( p->eParamType, p->pData, sizeof(p->pData) ); + + if( !m3A_Export.isHeld() && STATUS_SUCCESS == greError ) + { + greError = _3A_ApplyExported(); + } + + break; + } + + case VCAM_PARAM_EXPORTED_3A_APPLY: + { + greError = m3A_Export.release_3A(); + + if( STATUS_SUCCESS == greError ) + { + greError = _3A_ApplyExported(); + } + + break; + } + + case VCAM_PARAM_EXPORTED_3A_RESET: + { + greError = m3A_Export.reset(); + break; + } +#endif // EXPORTED_3A +#if defined(OMX_CAMERA_SUPPORTS_IMAGE_PYRAMID) + case VCAM_PARAM_IMAGE_PYRAMID: + { + greError = setImagePyramid(param, size, port); + break; + } +#endif + default: + { + DVP_PRINT(DVP_ZONE_ERROR, "Impossible parameter id requested: %d\n", paramId); + DVP_PRINT(DVP_ZONE_ERROR, "see VisionCamParam_e for possible parameter ids\n"); + greError = STATUS_NOT_IMPLEMENTED; + if(paramId < VCAM_PARAM_MIN || paramId > VCAM_PARAM_MAX) + greError = STATUS_INVALID_PARAMETER; + } + } + + if( OMX_ErrorNone != omxError ) + { + greError = ConvertError(omxError); + } + + if( greError != STATUS_SUCCESS ) + { + DVP_PRINT(DVP_ZONE_ERROR, "setParameter() exits with error 0x%x (dec: %d) [OMX:0x%08x] for param id 0x%x\n", + greError, greError, omxError, paramId); + } + + return greError; +} + +status_e OMXVisionCam::setColorSpace(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + status_e vcamError = STATUS_SUCCESS; + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + + if( param != NULL ) + { + fourcc_t colorSpace = *((fourcc_t*)param); + if( port != VCAM_PORT_VIDEO && ( colorSpace == FOURCC_RGB565 || colorSpace == FOURCC_BGR565) ) + { + DVP_PRINT(DVP_ZONE_ERROR, "Requested Color format requested is not supported on this port!!\n"); + DVP_PRINT(DVP_ZONE_ERROR, "Leaving it unchanged.\n"); + vcamError = STATUS_INVALID_PARAMETER; + return vcamError; + } + +// int i = 0; +// while( ColorFormatLUT[ i ][ 1 ] != OMX_COLOR_FormatMax ) +// { +// if( ColorFormatLUT[ i ][ 0 ] == (int)colorSpace ) +// { +// mCurGreContext.mCameraPortParams[port].mColorFormat = (OMX_COLOR_FORMATTYPE)ColorFormatLUT[ i ][ 1 ]; +// break; +// } +// i++; +// } + +// if( ColorFormatLUT[ i ][ 1 ] == OMX_COLOR_FormatMax ) +// { +// DVP_PRINT(DVP_ZONE_ERROR, "Color format requested is not supported!!\n Leaving it unchanged.\n"); +// vcamError = STATUS_INVALID_PARAMETER; +// } + + int32_t format = (OMX_COLOR_FORMATTYPE)getLutValue( colorSpace, VCAM_VALUE_TYPE, + ColorFormatLUT, ARR_SIZE(ColorFormatLUT) + ); + if( STATUS_INVALID_PARAMETER == format ) + { + vcamError = STATUS_INVALID_PARAMETER; + return vcamError; + } + else + { + mCurGreContext.mCameraPortParams[port].mColorFormat = (OMX_COLOR_FORMATTYPE)format; + + if( STATUS_SUCCESS == vcamError ) + { + OMX_STATETYPE compState = getComponentState(); + + if( OMX_StateExecuting == compState || OMX_StatePause == compState ) + { + vcamError = STATUS_INVALID_STATE; + } + } + + if( STATUS_SUCCESS == vcamError ) + { + OMX_PARAM_PORTDEFINITIONTYPE portCheck; + + int32_t p; + LOOP_PORTS( port , p ) + { + omxError = initPortCheck( &portCheck, p ); + if( omxError == OMX_ErrorNone ) + { + portCheck.format.video.eColorFormat = mCurGreContext.mCameraPortParams[p].mColorFormat; + omxError = OMX_SetParameter( mCurGreContext.mHandleComp, + OMX_IndexParamPortDefinition, + &portCheck + ); + if ( omxError != OMX_ErrorNone ) { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! OMX_SetParameter returned 0x%08x\n",vcamError); + } + } + else + vcamError = ConvertError(omxError); + } + } + else + { + vcamError = STATUS_INVALID_PARAMETER; + } + } + } + + return vcamError; +} + +status_e OMXVisionCam::setBrightness(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + + OMX_CONFIG_BRIGHTNESSTYPE brightness; + brightness.nSize = sizeof(OMX_CONFIG_BRIGHTNESSTYPE); + brightness.nBrightness = *((int*)param); + memcpy( &brightness.nVersion, mLocalVersion, sizeof(mLocalVersion) ); + + int32_t p = port; +// LOOP_PORTS( port , p ) + { + brightness.nPortIndex = mCurGreContext.mPortsInUse[p]; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, OMX_IndexConfigCommonBrightness, &brightness); + } + + return ConvertError(omxError); +} + +status_e OMXVisionCam::setContrast(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + + OMX_CONFIG_CONTRASTTYPE contrast; + contrast.nSize = sizeof( OMX_CONFIG_CONTRASTTYPE ); + contrast.nContrast = *((int*)param); + memcpy( &contrast.nVersion, mLocalVersion, sizeof(mLocalVersion) ); + + int32_t p = port; +// LOOP_PORTS( port , p ) + { + contrast.nPortIndex = mCurGreContext.mPortsInUse[p]; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, OMX_IndexConfigCommonContrast, &contrast); + } + return ConvertError(omxError); +} + +status_e OMXVisionCam::setSharpness(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + OMX_IMAGE_CONFIG_PROCESSINGLEVELTYPE procSharpness; + procSharpness.nSize = sizeof( OMX_IMAGE_CONFIG_PROCESSINGLEVELTYPE ); + procSharpness.nLevel = *((int*)param); + memcpy( &procSharpness.nVersion, mLocalVersion, sizeof(mLocalVersion) ); + + if( procSharpness.nLevel == 0 ) + procSharpness.bAuto = OMX_TRUE; + else + procSharpness.bAuto = OMX_FALSE; + + int32_t p = port; +// LOOP_PORTS( port , p ) + { + procSharpness.nPortIndex = mCurGreContext.mPortsInUse[p]; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_IndexConfigSharpeningLevel, &procSharpness); + } + + return ConvertError(omxError); +} + +status_e OMXVisionCam::setSaturation(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + OMX_CONFIG_SATURATIONTYPE saturation; + saturation.nSize = sizeof(OMX_CONFIG_SATURATIONTYPE); + saturation.nSaturation = *((int*)param); + memcpy( &saturation.nVersion, mLocalVersion, sizeof(mLocalVersion) ); + + int32_t p = port; +// LOOP_PORTS( port , p ) + { + saturation.nPortIndex = mCurGreContext.mPortsInUse[p]; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, + OMX_IndexConfigCommonSaturation, + &saturation + ); + } + return ConvertError(omxError); +} + +status_e OMXVisionCam::setFrameRate_Fixed( void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port __attribute__ ((unused))) +{ + status_e vCamError = STATUS_BASE; + + bool_e enableAgain[VCAM_PORT_MAX]; + + int32_t p; + LOOP_PORTS(VCAM_PORT_ALL , p) + enableAgain[p] = mCurGreContext.mCameraPortParams[p].mIsActive; + + vCamError = stopPreview(VCAM_PORT_ALL); +#if 0 + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + { + // If this is a SMART Sensor, we have to "fix" the frame rate to a non-variable rate + OMX_CONFIG_BOOLEANTYPE bOMX; + bOMX.nSize = sizeof(OMX_CONFIG_BOOLEANTYPE); + memcpy(&bOMX.nVersion, mLocalVersion, sizeof(OMX_VERSIONTYPE)); + bOMX.bEnabled = OMX_TRUE; + omxError = OMX_SetParameter(mCurGreContext.mHandleComp, + (OMX_INDEXTYPE)OMX_TI_IndexParamSensorVTMode, + &bOMX); + } + vCamError = ConvertError(omxError); +#endif + int32_t i; + LOOP_PORTS(VCAM_PORT_ALL , i) + { + mCurGreContext.mCameraPortParams[i].mFrameRate = (*((uint32_t*)param)); + if( enableAgain[i] ) + { + vCamError = startPreview( (VisionCamPort_e)i ); + } + } + return vCamError; +} + +#if defined(OMX_CAMERA_SUPPORTS_IMAGE_PYRAMID) +status_e OMXVisionCam::setImagePyramid(void *param, size_t size, VisionCamPort_e port) +{ + OMX_TI_PARAM_IMAGEPYRAMIDTYPE imagePyramid; + OMX_CONFIG_EXTRADATATYPE xData; + OMX_ERRORTYPE omxError; + + if( (param == NULL) || (size != sizeof(VisionCamImagePyramidType)) ) { + return STATUS_INVALID_PARAMETER; + } + + memcpy( &imagePyramid.nVersion, mLocalVersion, sizeof(mLocalVersion) ); + imagePyramid.nSize = sizeof( OMX_TI_PARAM_IMAGEPYRAMIDTYPE ); + imagePyramid.nPortIndex = mCurGreContext.mPortsInUse[port]; + imagePyramid.nLevelsCount = ((VisionCamImagePyramidType *)param)->mLevelsCount; + imagePyramid.nScalingFactor = ((VisionCamImagePyramidType *)param)->mScalingFactor; + + omxError = OMX_SetParameter( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexParamImagePyramid, &imagePyramid ); + + if ( OMX_ErrorNone == omxError ) + { + OMX_STRUCT_INIT(xData, OMX_CONFIG_EXTRADATATYPE, mLocalVersion); + xData.nPortIndex = mCurGreContext.mPortsInUse[port]; + xData.eExtraDataType = OMX_TI_ImagePyramid; + if( imagePyramid.nLevelsCount > 1 ) { + xData.bEnable = OMX_TRUE; + } else { + xData.bEnable = OMX_FALSE; + } + omxError = OMX_SetConfig(mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_IndexConfigOtherExtraDataControl, &xData); + } + + return ConvertError(omxError); +} + +status_e OMXVisionCam::getImagePyramid(void *param, size_t size, VisionCamPort_e port) +{ + OMX_TI_PARAM_IMAGEPYRAMIDTYPE imagePyramid; + OMX_ERRORTYPE omxError; + + if( (param == NULL) || (size != sizeof(VisionCamImagePyramidType)) ) { + return STATUS_INVALID_PARAMETER; + } + + memcpy( &imagePyramid.nVersion, mLocalVersion, sizeof(mLocalVersion) ); + imagePyramid.nSize = sizeof( OMX_TI_PARAM_IMAGEPYRAMIDTYPE ); + imagePyramid.nPortIndex = mCurGreContext.mPortsInUse[port]; + + omxError = OMX_GetParameter( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexParamImagePyramid, &imagePyramid ); + + ((VisionCamImagePyramidType *)param)->mLevelsCount = imagePyramid.nLevelsCount; + ((VisionCamImagePyramidType *)param)->mScalingFactor = imagePyramid.nScalingFactor; + + return ConvertError(omxError); +} +#endif + +status_e OMXVisionCam::setFrameRate_Variable(void *param, size_t size, VisionCamPort_e port __attribute__ ((unused))) +{ + status_e vcamError = STATUS_BASE; + VisionCamVarFramerateType varFrate; + + if( sizeof(VisionCamVarFramerateType) == size || 0 == size ) + { + memcpy( &varFrate , param , sizeof( VisionCamVarFramerateType ) ); + } + else + { + vcamError = STATUS_INVALID_PARAMETER; + } + + bool_e enableAgain[VCAM_PORT_MAX]; + + int32_t p; + LOOP_PORTS( VCAM_PORT_ALL , p ) + { + enableAgain[p] = mCurGreContext.mCameraPortParams[p].mIsActive; + } + + vcamError = stopPreview(VCAM_PORT_ALL); + + if( varFrate.mMin != 0 && vcamError == STATUS_SUCCESS ) + { + // @todo implement when needed OMX interface is present + varFrate = varFrate; + } + + int32_t i; + LOOP_PORTS( VCAM_PORT_ALL , i ) + { + mCurGreContext.mCameraPortParams[i].mFrameRate = varFrate.mMax; + if( enableAgain[i] ) + { + vcamError = startPreview( (VisionCamPort_e)i ); + } + } + return vcamError; +} + +status_e OMXVisionCam::setFlicker(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + + OMX_CONFIG_FLICKERCANCELTYPE flicker; + flicker.nSize = sizeof( OMX_CONFIG_FLICKERCANCELTYPE ); + memcpy( &flicker.nVersion, mLocalVersion, sizeof(mLocalVersion) ); + flicker.eFlickerCancel = *(OMX_COMMONFLICKERCANCELTYPE *)param; + + int32_t p = port; +// LOOP_PORTS( VCAM_PORT_ALL , p ) + { + flicker.nPortIndex = mCurGreContext.mPortsInUse[p]; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_IndexConfigFlickerCancel, &flicker ); + } + + return ConvertError(omxError); +} + +status_e OMXVisionCam::setCrop(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + + OMX_CONFIG_RECTTYPE crop; + crop.nSize = sizeof( OMX_CONFIG_RECTTYPE ); + crop.nLeft = ((VisionCamRectType*)param)->mLeft; + crop.nTop = ((VisionCamRectType*)param)->mTop; + crop.nWidth = ((VisionCamRectType*)param)->mWidth; + crop.nHeight = ((VisionCamRectType*)param)->mHeight; + memcpy( &crop.nVersion, mLocalVersion, sizeof(mLocalVersion) ); + + int32_t p = port; +// LOOP_PORTS( port , p ) + { + crop.nPortIndex = mCurGreContext.mPortsInUse[p]; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, OMX_IndexConfigCommonOutputCrop, &crop ); + } + return ConvertError(omxError); +} +status_e OMXVisionCam::setStereoInfo(void *param, size_t size, VisionCamPort_e port) +{ + status_e greError = STATUS_BASE; + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + + VisionCamStereoInfo *info = (VisionCamStereoInfo *)param; + OMX_TI_FRAMELAYOUTTYPE frameLayout; + OMX_STRUCT_INIT(frameLayout, OMX_TI_FRAMELAYOUTTYPE, mLocalVersion); + OMX_TI_CONFIG_CONVERGENCETYPE acParams; + OMX_STRUCT_INIT(acParams, OMX_TI_CONFIG_CONVERGENCETYPE, mLocalVersion); + +#ifndef USE_SMALC_FOR_STEREO + OMX_TI_CONFIG_MM mmSettings; + OMX_STRUCT_INIT(mmSettings, OMX_TI_CONFIG_MM, mLocalVersion); +#endif +#ifndef USE_VSTAB_FOR_STEREO + OMX_CONFIG_BOOLEANTYPE vssEnable; + vssEnable.nSize = sizeof(OMX_CONFIG_BOOLEANTYPE); + memcpy(&vssEnable.nVersion, mLocalVersion, sizeof(mLocalVersion)); +#endif + + if ( info && size == sizeof(VisionCamStereoInfo)) + { + int32_t p = port; +// LOOP_PORTS( port , p ) + { + int value = 0; + frameLayout.nPortIndex = mCurGreContext.mPortsInUse[p]; + DVP_PRINT(DVP_ZONE_CAM, "Stereo Info: Layout %u, SubSampling: %u\n", info->layout, info->subsampling); + + value = getLutValue((int)info->layout, VCAM_VALUE_TYPE, StereoLayoutLUT, ARR_SIZE(StereoLayoutLUT)); + + // some feature was compiled out. + if (value == STATUS_INVALID_PARAMETER) + return (status_e)value; + + frameLayout.eFrameLayout = (OMX_TI_STEREOFRAMELAYOUTTYPE)value; + +// if (info->layout == VCAM_STEREO_LAYOUT_TOPBOTTOM) +// frameLayout.eFrameLayout = OMX_TI_StereoFrameLayoutTopBottom; +// else if (info->layout == VCAM_STEREO_LAYOUT_LEFTRIGHT) +// frameLayout.eFrameLayout = OMX_TI_StereoFrameLayoutLeftRight; + frameLayout.nSubsampleRatio = info->subsampling << 7; // in Q15.7 format + omxError = OMX_SetParameter( mCurGreContext.mHandleComp, + (OMX_INDEXTYPE)OMX_TI_IndexParamStereoFrmLayout, + &frameLayout + ); + greError = ConvertError(omxError); + if( OMX_ErrorNone == omxError ) + { + acParams.nPortIndex = mCurGreContext.mPortsInUse[p]; + + acParams.nManualConverence = 0; + acParams.eACMode = OMX_TI_AutoConvergenceModeDisable; + + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, + (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoConvergence, + &acParams + ); + greError = ConvertError(omxError); + if( OMX_ErrorNone != omxError ) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR OMXVisionCam: Failed to disable auto convergence.\n"); + } + +#ifndef USE_SMALC_FOR_STEREO + // Turn off mechanical misalignment correction. + mmSettings.nPortIndex = mCurGreContext.mPortsInUse[p]; + mmSettings.bMM = OMX_FALSE; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, + (OMX_INDEXTYPE)OMX_TI_IndexConfigMechanicalMisalignment, + &mmSettings + ); + if( OMX_ErrorNone != omxError ) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR OMXVisionCam: Failed to disable mechanical misalignment correction.\n"); + } +#endif // USE_SMALC_FOR_STEREO + +#ifndef USE_VSTAB_FOR_STEREO + // Turn off video stabilization + vssEnable.bEnabled = OMX_FALSE; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, + (OMX_INDEXTYPE)OMX_IndexParamFrameStabilisation, + &vssEnable + ); + if( OMX_ErrorNone != omxError ) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR OMXVisionCam: Failed to disable video stabilization.\n"); + } +#endif // USE_VSTAB_FOR_STEREO + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR OMXVisionCam: Failed to set stereo layout\n"); + } + } +#if 0 // This code is hanging around just to test the non-zero buffer offset for future compatibility + OMX_CONFIG_BOOLEANTYPE ldc; + ldc.nSize = sizeof(OMX_CONFIG_BOOLEANTYPE); + memcpy(&ldc.nVersion, mLocalVersion, sizeof(OMX_VERSIONTYPE)); + ldc.bEnabled = OMX_TRUE; // Just for testing the nOffset +// ldc.bEnabled = (info->bLensCorrection == true_e ? OMX_TRUE:OMX_FALSE); + omxError = OMX_SetParameter( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_IndexParamLensDistortionCorrection, &ldc); + + OMX_PARAM_ISONOISEFILTERTYPE iso; + OMX_STRUCT_INIT(iso, OMX_PARAM_ISONOISEFILTERTYPE, mLocalVersion); + iso.nPortIndex = VCAM_PORT_ALL; +// if (info->bNoiseFilter) + iso.eMode = OMX_ISONoiseFilterModeOn; +// else +// iso.eMode = OMX_ISONoiseFilterModeOff; + omxError = OMX_SetParameter( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_IndexParamHighISONoiseFiler, &iso); +#endif + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR OMXVisionCam: attempt to set param with id VCAM_PARAM_STEREO_INFO with an invalid args\n"); + greError = STATUS_INVALID_PARAMETER; + } + return greError; +} + +status_e OMXVisionCam::setCameraOperatingMode(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port __attribute__ ((unused))) +{ + status_e greError = STATUS_BASE; + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + VisionCamCaptureMode mode = *(VisionCamCaptureMode *)param; + + for( int32_t sen = 0; sen < mDetectedSensors.sensorCount; sen++ ) + { + for( int32_t mod = 0; mod < mDetectedSensors.sensors[sen].supportedModesCnt; mod++ ) + { + if( mDetectedSensors.sensors[sen].supportedModes[mod] == mode ) + { + greError = STATUS_SUCCESS; + } + } + } + + if( VCAM_GESTURE_DUAL_SENSOR_MODE == mode && STATUS_SUCCESS == greError ) + { + OMX_CONFIG_SENSORSELECTTYPE sensor; + OMX_STRUCT_INIT(sensor, OMX_CONFIG_SENSORSELECTTYPE, mLocalVersion); + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigSensorSelect, &sensor); + + if( OMX_ErrorNone == omxError ) + { + if ( OMX_PrimarySensor != sensor.eSensor ) + { + greError = STATUS_INVALID_STATE; + DVP_PRINT( DVP_ZONE_CAM, "You must select primary sensor to get in dual sensor mode!\n"); + } + } + else + greError = STATUS_FAILURE; + } + + if (param != NULL && STATUS_SUCCESS == greError ) + { + int value = 0; + OMX_CONFIG_CAMOPERATINGMODETYPE opMode; + opMode.nSize = sizeof( OMX_CONFIG_CAMOPERATINGMODETYPE ); + memcpy( &opMode.nVersion, mLocalVersion, sizeof(mLocalVersion) ); + + value = getLutValue(mode, VCAM_VALUE_TYPE, CaptureModeLUT, ARR_SIZE(CaptureModeLUT) ); + + if (value == STATUS_INVALID_PARAMETER) + return STATUS_INVALID_PARAMETER; // mode not supported. + + opMode.eCamOperatingMode = (OMX_CAMOPERATINGMODETYPE)value; + + DVP_PRINT(DVP_ZONE_CAM, "Requested VisionCamCaptureMode %d\n", mode); + DVP_PRINT(DVP_ZONE_CAM, "Requested OMX_CAMOPERATINGMODETYPE %d\n", opMode.eCamOperatingMode); + + bool_e enableAgain[VCAM_PORT_MAX]; + + int32_t p;// mark and stop all working ports + LOOP_PORTS( VCAM_PORT_ALL , p ) + { + enableAgain[p] = mCurGreContext.mCameraPortParams[p].mIsActive; + if( mCurGreContext.mCameraPortParams[p].mIsActive ) + portEnableDisable(OMX_CommandPortDisable, freePortBuffersSrvc, (VisionCamPort_e)p ); + } + + int32_t oldstate = getComponentState(); + for(int32_t st = oldstate - 1; st >= OMX_StateLoaded; st--) + { + if( OMX_StatePause == oldstate && OMX_StateExecuting == st ) + continue; + + transitToState( (OMX_STATETYPE)st ); + } + + if( OMX_StateLoaded == getComponentState() || OMX_StateWaitForResources == getComponentState() ) + { + omxError = OMX_SetParameter( mCurGreContext.mHandleComp, + (OMX_INDEXTYPE)OMX_IndexCameraOperatingMode, + &opMode ); + + greError = ConvertError(omxError); + } + + for(int32_t st = (1 + getComponentState()); st <= oldstate; st++) + { + if( OMX_StatePause == oldstate && OMX_StateExecuting == st) + continue; + + transitToState( (OMX_STATETYPE)st ); + } + + int32_t por; + LOOP_PORTS( VCAM_PORT_ALL , por ) + if( enableAgain[por]) + { + portEnableDisable(OMX_CommandPortEnable, populatePortSrvc, (VisionCamPort_e)por); + fillPortBuffers((VisionCamPort_e)por); + } + } + else + { + greError = STATUS_INVALID_PARAMETER; + } + + return greError; +} + +status_e OMXVisionCam::setSensor(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port __attribute__ ((unused))) +{ + status_e vcamError = STATUS_BASE; + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + if (param != NULL) + { + omxError = OMX_ErrorHardware; + + OMX_CONFIG_SENSORSELECTTYPE sensor; + OMX_STRUCT_INIT(sensor, OMX_CONFIG_SENSORSELECTTYPE, mLocalVersion); + sensor.nPortIndex = mCurGreContext.mPortsInUse[VCAM_PORT_ALL]; + sensor.eSensor = *((OMX_SENSORSELECT*)param); + for( int32_t cnt = 0; cnt < mDetectedSensors.sensorCount; cnt++ ) + { + if( sensor.eSensor == mDetectedSensors.sensors[cnt].nIndex ) + { + DVP_PRINT(DVP_ZONE_CAM, "Selecting sensor index = %u\n", sensor.eSensor); + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigSensorSelect, &sensor); + vcamError = ConvertError(omxError); + break; + } + } + } + else + { + vcamError = STATUS_INVALID_PARAMETER; + } + + return vcamError; +} + +status_e OMXVisionCam::setExposureCompensation(void * param, size_t size __attribute__ ((unused)), VisionCamPort_e port ) +{ + status_e vcamError = STATUS_SUCCESS; + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + OMX_CONFIG_EXPOSUREVALUETYPE expValues; + OMX_STRUCT_INIT(expValues, OMX_CONFIG_EXPOSUREVALUETYPE, mLocalVersion); + + memcpy( &expValues.nVersion , mLocalVersion , sizeof( *mLocalVersion ) ); + omxError = OMX_GetConfig( mCurGreContext.mHandleComp , OMX_IndexConfigCommonExposureValue , &expValues ); + vcamError = ConvertError(omxError); + + if( STATUS_SUCCESS == vcamError ) + { + int compVal = *((int*)param); + expValues.xEVCompensation = ( compVal * ( 1 << 16 ) ) / 10; + + int32_t p = port; +// LOOP_PORTS( port , p ) + { + expValues.nPortIndex = mCurGreContext.mPortsInUse[p]; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp , OMX_IndexConfigCommonExposureValue , &expValues ); + vcamError = ConvertError(omxError); + } + } + return vcamError; +} + +status_e OMXVisionCam::setResolution (void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + status_e vcamError = STATUS_SUCCESS; + + if( param != NULL ) + { + + if( *((int32_t*)param) < 0 || *((int32_t*)param) >= VCAM_RESOL_MAX ) + { + vcamError = STATUS_INVALID_PARAMETER; + } + + if( STATUS_SUCCESS == vcamError ) + { + int32_t p = port; + LOOP_PORTS( port , p ) + { + int32_t res = *((int32_t*)param); + if( STATUS_SUCCESS == vcamError ) + { + if( mCurGreContext.mCameraPortParams[p].mIsActive ) + { + vcamError = STATUS_INVALID_STATE; + break; + } + } + + if( STATUS_SUCCESS == vcamError ) + { + if( VCAM_PORT_VIDEO == p + && ( VisionCamResolutions[res].mWidth > VisionCamResolutions[VCAM_RES_VGA].mWidth + || VisionCamResolutions[res].mHeight > VisionCamResolutions[VCAM_RES_VGA].mHeight ) ) + { + res = VCAM_RES_VGA; + } + + mCurGreContext.mCameraPortParams[p].mWidth = VisionCamResolutions[res].mWidth; + mCurGreContext.mCameraPortParams[p].mHeight = VisionCamResolutions[res].mHeight; + } + } + } + } + else + { + vcamError = STATUS_INVALID_PARAMETER; + } + + return vcamError; +} + +status_e OMXVisionCam::setManualExporureTime(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + status_e vcamError = STATUS_BASE; + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + OMX_CONFIG_EXPOSUREVALUETYPE expValues; + OMX_STRUCT_INIT(expValues, OMX_CONFIG_EXPOSUREVALUETYPE, mLocalVersion); + + int32_t p = port; + +// LOOP_PORTS( port , p ) + { + expValues.nPortIndex = mCurGreContext.mPortsInUse[p]; + omxError = OMX_GetConfig( mCurGreContext.mHandleComp , OMX_IndexConfigCommonExposureValue , &expValues ); + vcamError = ConvertError(omxError); + if( STATUS_SUCCESS == vcamError ) + { + if( *(OMX_U32*)param ) + { + expValues.nShutterSpeedMsec = *(OMX_U32*)param; + expValues.bAutoShutterSpeed = OMX_FALSE; + } + else + expValues.bAutoShutterSpeed = OMX_TRUE; + + omxError = OMX_SetConfig( mCurGreContext.mHandleComp , OMX_IndexConfigCommonExposureValue , &expValues ); + vcamError = ConvertError(omxError); + } + } + return vcamError; +} + +status_e OMXVisionCam::setISO(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + status_e vcamError = STATUS_BASE; + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + OMX_CONFIG_EXPOSUREVALUETYPE expValues; + OMX_STRUCT_INIT(expValues, OMX_CONFIG_EXPOSUREVALUETYPE, mLocalVersion); + + int32_t p = port; +// LOOP_PORTS( port , p ) + { + + expValues.nPortIndex = mCurGreContext.mPortsInUse[p]; + omxError = OMX_GetConfig(mCurGreContext.mHandleComp, OMX_IndexConfigCommonExposureValue, &expValues); + vcamError = ConvertError(omxError); + if( STATUS_SUCCESS == vcamError ) + { + if( *(OMX_U32*)param ) + { + expValues.nSensitivity = *(OMX_U32*)param; + expValues.bAutoSensitivity = OMX_FALSE; + } + else + expValues.bAutoSensitivity = OMX_TRUE; + + omxError = OMX_SetConfig( mCurGreContext.mHandleComp , OMX_IndexConfigCommonExposureValue , &expValues ); + vcamError = ConvertError(omxError); + } + } + return vcamError; +} + +status_e OMXVisionCam::setWhiteBalanceMode(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + status_e vcamError= STATUS_BASE; + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + + OMX_CONFIG_WHITEBALCONTROLTYPE wb; + OMX_STRUCT_INIT(wb, OMX_CONFIG_WHITEBALCONTROLTYPE, mLocalVersion); + + int32_t p = port; +// LOOP_PORTS( port , p ) + { + wb.nPortIndex = mCurGreContext.mPortsInUse[p]; + wb.eWhiteBalControl = *(OMX_WHITEBALCONTROLTYPE *)param; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, + OMX_IndexConfigCommonWhiteBalance, + &wb); + vcamError = ConvertError(omxError); + } + return vcamError; +} + +status_e OMXVisionCam::setColorTemp(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + status_e vcamError= STATUS_BASE; + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + OMX_CONFIG_WHITEBALCONTROLTYPE wb; + OMX_STRUCT_INIT(wb, OMX_CONFIG_WHITEBALCONTROLTYPE, mLocalVersion); + + if( 0 == *(int*)param ) + { + wb.eWhiteBalControl = OMX_WhiteBalControlAuto; + } + else + { + wb.eWhiteBalControl = OMX_WhiteBalControlOff; // @todo change to manual when proper OMX headers arrive + } + + int32_t p = port; +// LOOP_PORTS( port , p ) + { + wb.nPortIndex = mCurGreContext.mPortsInUse[p]; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, + OMX_IndexConfigCommonWhiteBalance, + &wb ); + vcamError = ConvertError(omxError); + if( STATUS_SUCCESS == vcamError ) + { +#if 0 + OMX_CONFIG_WHITEBALANCECOLORTEMPTPYPE colTemp; + OMX_STRUCT_INIT(colTemp, OMX_CONFIG_WHITEBALANCECOLORTEMPTPYPE, mLocalVersion); + colTemp.nPortIndex = mCurGreContext.mPortsInUse[port]; + colTemp.nColorTemperature = *(OMX_U32 *)param; + + omxError = OMX_SetConfig(mCurGreContext.mHandleComp, + OMX_IndexConfigWhiteBalanceManualColorTemp, + &colTemp ); + vcamError = ConvertError(omxError); +#endif + } + } + return vcamError; +} + +status_e OMXVisionCam::setMirror(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + status_e vcamError = STATUS_BASE; + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + OMX_CONFIG_MIRRORTYPE mirror; + OMX_STRUCT_INIT(mirror, OMX_CONFIG_MIRRORTYPE, mLocalVersion); + + int32_t result = (OMX_MIRRORTYPE)getLutValue( *(int32_t*)param, VCAM_VALUE_TYPE, + MirrorTypeLUT, ARR_SIZE(MirrorTypeLUT) + ); + + if( result != STATUS_INVALID_PARAMETER ) + { + mirror.eMirror = (OMX_MIRRORTYPE)result; + + int32_t p; + LOOP_PORTS( port , p ) + { + mirror.nPortIndex = mCurGreContext.mPortsInUse[p]; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, + OMX_IndexConfigCommonMirror, + &mirror ); + vcamError = ConvertError(omxError); + if( omxError != OMX_ErrorNone ) + { + break; + } + } + } + else + { + vcamError = STATUS_INVALID_PARAMETER; + } + + return vcamError; +} + +#if ( defined(DUCATI_1_5) || defined(DUCATI_2_0) ) && defined(OMX_CAMERA_SUPPORTS_MANUAL_CONTROLS) +status_e OMXVisionCam::setAWBminDelayTime(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + status_e vcamError = STATUS_BASE; + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + + uint32_t timeDelay = *((uint32_t*)param); + + if( timeDelay > AE_Delay_Time_Max ) + { + vcamError = STATUS_INVALID_PARAMETER; + } + else + { + OMX_TI_CONFIG_AWB_DELAY awbDelay; + OMX_STRUCT_INIT( awbDelay, OMX_TI_CONFIG_AWB_DELAY, mLocalVersion ); + awbDelay.nDelayTime = timeDelay; + + int32_t p = port; +// LOOP_PORTS( port , p ) + { + awbDelay.nPortIndex = p; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, + ( OMX_INDEXTYPE )OMX_TI_IndexConfigAWBMinDelayTime, + &awbDelay + ); + } + vcamError = ConvertError(omxError); + } + return vcamError; +} + +status_e OMXVisionCam::setGestureInfo(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + status_e greError = STATUS_BASE; + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + + VisionCamGestureInfo *info = (VisionCamGestureInfo*)param; + if( info->mGestureType >= VCAM_GESTURE_EVENT_MAX || info->mGestureType < VCAM_GESTURE_EVENT_INVALID ) + { + greError= STATUS_INVALID_PARAMETER; + } + + if( info->mRegionsNum >= VCAM_Max_Gesture_Per_Frame ) + { + greError= STATUS_INVALID_PARAMETER; + } + + if( STATUS_SUCCESS == greError ) + { + int value = 0; + OMX_TI_CONFIG_GESTURES_INFO gestInfo; + OMX_STRUCT_INIT( gestInfo, OMX_TI_CONFIG_GESTURES_INFO , mLocalVersion ); + + gestInfo.nTimeStamp = info->timeStamp; + gestInfo.nNumDetectedGestures = info->mRegionsNum; + value = getLutValue( info->mGestureType, VCAM_VALUE_TYPE, + GestureTypeLUT, ARR_SIZE(GestureTypeLUT) + ); + if ( value != STATUS_INVALID_PARAMETER ) + { + gestInfo.eType = (OMX_TI_GESTURES_TYPE)value; + for(uint32_t i = 0; i < info->mRegionsNum ; i++ ) + { + OMX_STRUCT_INIT(gestInfo.nGestureAreas[i], OMX_CONFIG_OBJECT_RECT_TYPE , mLocalVersion ); + value = getLutValue( (int)(info->mRegions[i].mObjType), VCAM_VALUE_TYPE, + ObjectTypeLUT, ARR_SIZE(ObjectTypeLUT) + ); + if (value == STATUS_INVALID_PARAMETER) + continue; + gestInfo.nGestureAreas[i].eType = (OMX_TI_OBJECT_TYPE)value; + gestInfo.nGestureAreas[i].nTop = info->mRegions[i].mTop; + gestInfo.nGestureAreas[i].nLeft = info->mRegions[i].mLeft; + gestInfo.nGestureAreas[i].nWidth = info->mRegions[i].mWidth; + gestInfo.nGestureAreas[i].nHeight = info->mRegions[i].mHeight; + } + + if( OMX_TI_GESTURE_NO_GESTURE != gestInfo.eType) + { + int32_t p = port; + // LOOP_PORTS( port , p ) + { + gestInfo.nPortIndex = mCurGreContext.mPortsInUse[p]; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, + (OMX_INDEXTYPE)OMX_TI_IndexConfigDetectedGesturesInfo, + &gestInfo + ); + } + greError = ConvertError(omxError); + } + else + { + greError = STATUS_INVALID_PARAMETER; + } + } + else + { + greError = (status_e)value; + } + } + return greError; +} + +status_e OMXVisionCam::setAGC_MinimumDelay(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + status_e vcamError = STATUS_BASE; + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + int32_t delay = *((int32_t*)param); + OMX_TI_CONFIG_AE_DELAY agcDelTime; + OMX_STRUCT_INIT( agcDelTime, OMX_TI_CONFIG_AE_DELAY, mLocalVersion ); + agcDelTime.nDelayTime = delay; + + int32_t p = port; +// LOOP_PORTS( port , p ) + { + agcDelTime.nPortIndex = p; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, + (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoExpMinDelayTime, + &agcDelTime ); + vcamError = ConvertError(omxError); + } + return vcamError; +} + +status_e OMXVisionCam::setAGC_LowThreshold(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + status_e vcamError = STATUS_BASE; + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + int32_t lowTH = *((int32_t*)param); + OMX_TI_CONFIG_AE_THRESHOLD ae; + + OMX_STRUCT_INIT( ae, OMX_TI_CONFIG_AE_THRESHOLD, mLocalVersion ); + + int32_t p = port; +// LOOP_PORTS( port , p ) + { + ae.nPortIndex = p; + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoExpThreshold, &ae ); + + vcamError = ConvertError(omxError); + if( STATUS_SUCCESS == vcamError ) + { + ae.uMinTH = lowTH; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoExpThreshold, &ae ); + vcamError = ConvertError(omxError); + } + } + return vcamError; +} + +status_e OMXVisionCam::setAGC_HighThreshold(void *param, size_t size __attribute__ ((unused)), VisionCamPort_e port) +{ + status_e vcamError = STATUS_BASE; + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + int32_t highTH = *((int32_t*)param); + + OMX_TI_CONFIG_AE_THRESHOLD ae; + OMX_STRUCT_INIT( ae, OMX_TI_CONFIG_AE_THRESHOLD, mLocalVersion ); + + int32_t p = port; +// LOOP_PORTS( port , p ) + { + ae.nPortIndex = p; + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoExpThreshold, &ae ); + vcamError = ConvertError(omxError); + if( STATUS_SUCCESS == vcamError ) + { + ae.uMaxTH = highTH; + omxError = OMX_SetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoExpThreshold, &ae ); + vcamError = ConvertError(omxError); + } + } + return vcamError; +} + +#endif + +#if defined(EXPORTED_3A) +status_e OMXVisionCam::_3A_ApplyExported() +{ + status_e ret = STATUS_BASE; + bool_e user3Aheld = m3A_Export.isHeld(); + + if ( false_e == user3Aheld ) + { + OMX_ERRORTYPE omxStatus = OMX_ErrorUndefined; + OMX_TI_CONFIG_SHAREDBUFFER skipBuffer; + + OMX_STRUCT_INIT( skipBuffer, OMX_TI_CONFIG_SHAREDBUFFER , mLocalVersion ) + + skipBuffer.nPortIndex = OMX_ALL; // port; + skipBuffer.pSharedBuff = (OMX_U8*)m3A_Export.d3A_Buffer->getData(); + skipBuffer.nSharedBuffSize = m3A_Export.d3A_Buffer->getSize(); + + omxStatus = OMX_SetConfig( mCurGreContext.mHandleComp, + (OMX_INDEXTYPE)OMX_TI_IndexConfigAAAskipBuffer, + &skipBuffer + ); + ret = ConvertError(omxStatus); + } + else + { + ret = STATUS_INVALID_STATE; + } + return ret; +} +#endif + +/* +* APIs to get configured Vision Cam parameters +*/ +status_e OMXVisionCam::getParameter( VisionCamParam_e paramId, void* param, uint32_t size, VisionCamPort_e port) +{ + status_e greError = STATUS_SUCCESS; + OMX_ERRORTYPE omxError = OMX_ErrorNone; + + SOSAL::AutoLock lock( &mUserRequestLock ); + + if (param == NULL || size == 0 || port >= VCAM_PORT_MAX) + { + DVP_PRINT(DVP_ZONE_ERROR, "NULL param pointer passed to %s\n", __func__); + return STATUS_INVALID_PARAMETER; + } + else + { + DVP_PRINT(DVP_ZONE_CAM, "GET PARAM: 0x%04x, %p, %u (0x%08x)\n", paramId, param, size, (size==4?*(uint32_t *)param:0)); + } + + if( VCAM_PORT_ALL == port) + { + DVP_PRINT(DVP_ZONE_ERROR, "%s called on port ALL. Please specifu a port!\n", __func__); + return STATUS_INVALID_PARAMETER; + } + switch( paramId ) + { + case VCAM_PARAM_HEIGHT: + { + OMX_PARAM_PORTDEFINITIONTYPE portCheck; + omxError = initPortCheck( &portCheck , port ); + + if( OMX_ErrorNone == omxError ) + { + *(int*)param = portCheck.format.video.nFrameHeight; + } + break; + } + + case VCAM_PARAM_WIDTH: + { + OMX_PARAM_PORTDEFINITIONTYPE portCheck; + omxError = initPortCheck( &portCheck , port ); + + if( OMX_ErrorNone == omxError ) + { + *(int*)param = portCheck.format.video.nFrameWidth; + } + break; + } + + case VCAM_PARAM_COLOR_SPACE_FOURCC: + { + int i = 0; + OMX_PARAM_PORTDEFINITIONTYPE portCheck; + omxError = initPortCheck( &portCheck, port ); + + if( OMX_ErrorNone == omxError ) + { + while( ColorFormatLUT[ i ][ 1 ] != OMX_COLOR_FormatMax ) + { + if( ColorFormatLUT[ i ][ 1 ] == portCheck.format.video.eColorFormat ) + { + *( (int*)param) = ColorFormatLUT[ i ][ 0 ]; + break; + } + i++; + } + } + break; + } + + case VCAM_PARAM_DO_AUTOFOCUS: + { + int i = 0; + OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focus; + OMX_STRUCT_INIT(focus, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE, mLocalVersion); + + omxError = OMX_GetConfig(mCurGreContext.mHandleComp, OMX_IndexConfigFocusControl, &focus); + if( OMX_ErrorNone == omxError ) + { + for( i = 0; i < VCAM_FOCUS_CONTROL_MAX; i++ ) + { + if ( FocusModeLUT[ i ][ 1 ] == focus.eFocusControl ) + { + *(int*)param = FocusModeLUT[ i ][ 0 ]; + break; + } + } + if( VCAM_FOCUS_CONTROL_MAX == i ) + greError = STATUS_INVALID_PARAMETER; + } + + break; + } + + case VCAM_PARAM_DO_MANUALFOCUS: + { + OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focus; + OMX_STRUCT_INIT(focus, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE, mLocalVersion); + + omxError = OMX_GetConfig(mCurGreContext.mHandleComp, OMX_IndexConfigFocusControl, &focus); + if( OMX_ErrorNone == omxError ) + { + (*(int*)param) = focus.nFocusSteps; + } + break; + } + + case VCAM_PARAM_BRIGHTNESS: + { + OMX_CONFIG_BRIGHTNESSTYPE brightness; + OMX_STRUCT_INIT(brightness, OMX_CONFIG_BRIGHTNESSTYPE, mLocalVersion ); + + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, OMX_IndexConfigCommonBrightness, &brightness); + if( OMX_ErrorNone == omxError ) + { + *((uint32_t*)param) = brightness.nBrightness; + } + break; + } + + case VCAM_PARAM_CONTRAST: + { + OMX_CONFIG_CONTRASTTYPE contrast; + OMX_STRUCT_INIT(contrast, OMX_CONFIG_CONTRASTTYPE, mLocalVersion ); + + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, OMX_IndexConfigCommonContrast, &contrast); + if( OMX_ErrorNone == omxError ) + { + *((int*)param) = contrast.nContrast; + } + break; + } + + case VCAM_PARAM_SHARPNESS: + { + OMX_IMAGE_CONFIG_PROCESSINGLEVELTYPE procSharpness; + OMX_STRUCT_INIT( procSharpness, OMX_IMAGE_CONFIG_PROCESSINGLEVELTYPE, mLocalVersion ); + + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_IndexConfigSharpeningLevel, &procSharpness); + + if( OMX_ErrorNone == omxError ) + { + if( OMX_TRUE == procSharpness.bAuto ) + *((int*)param) = 0; + else + *((int*)param) = procSharpness.nLevel; + } + break; + } + + case VCAM_PARAM_SATURATION: + { + OMX_CONFIG_SATURATIONTYPE saturation; + OMX_STRUCT_INIT(saturation, OMX_CONFIG_SATURATIONTYPE, mLocalVersion); + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, OMX_IndexConfigCommonSaturation, &saturation); + + if( OMX_ErrorNone == omxError ) + { + *((int*)param) = saturation.nSaturation; + } + break; + } + + case VCAM_PARAM_FPS_FIXED: + { + OMX_PARAM_PORTDEFINITIONTYPE portCheck; + omxError = initPortCheck( &portCheck , port ); + + if( OMX_ErrorNone == omxError ) + { + *((uint32_t*)param) = portCheck.format.video.xFramerate >> 16; + } + break; + } + + case VCAM_PARAM_FPS_VAR: + { + DVP_PRINT(DVP_ZONE_WARNING, "No Getting Api for this Parameter %d\n", paramId); + break; + } + + case VCAM_PARAM_FLICKER: + { + OMX_CONFIG_FLICKERCANCELTYPE flicker; + OMX_STRUCT_INIT( flicker, OMX_CONFIG_FLICKERCANCELTYPE, mLocalVersion ); + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_IndexConfigFlickerCancel, &flicker ); + + if( OMX_ErrorNone == omxError ) + { + *((int32_t*)param) = flicker.eFlickerCancel; + } + break; + } + + case VCAM_PARAM_CROP: + { + OMX_CONFIG_RECTTYPE crop; + OMX_STRUCT_INIT(crop, OMX_CONFIG_RECTTYPE, mLocalVersion); + + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, OMX_IndexConfigCommonOutputCrop, &crop ); + + if( OMX_ErrorNone == omxError ) + { + ((VisionCamRectType*)param)->mLeft = crop.nLeft; + ((VisionCamRectType*)param)->mTop = crop.nTop; + ((VisionCamRectType*)param)->mWidth = crop.nWidth; + ((VisionCamRectType*)param)->mHeight = crop.nHeight; + } + break; + } + + case VCAM_PARAM_CAP_MODE: + { + if (param != NULL) + { + int i = 0; + OMX_CONFIG_CAMOPERATINGMODETYPE opMode; + opMode.nSize = sizeof(OMX_CONFIG_CAMOPERATINGMODETYPE); + memcpy(&opMode .nVersion, mLocalVersion , sizeof(OMX_VERSIONTYPE)); + + omxError = OMX_GetParameter( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_IndexCameraOperatingMode, &opMode ); + + if( OMX_ErrorNone == omxError ) + { + for (i = 0; i < VCAM_CAP_MODE_MAX; i++) + { + if (CaptureModeLUT[i][1] == opMode.eCamOperatingMode) + { + memcpy( param, &CaptureModeLUT[i][0], sizeof(int32_t) ); + break; + } + } + + if( VCAM_CAP_MODE_MAX == CaptureModeLUT[i][0]) + { + greError = STATUS_INVALID_PARAMETER; + break; + } + } + } + break; + } + + case VCAM_PARAM_SENSOR_SELECT: + { + OMX_CONFIG_SENSORSELECTTYPE sensor; + OMX_STRUCT_INIT(sensor, OMX_CONFIG_SENSORSELECTTYPE, mLocalVersion); + + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigSensorSelect, &sensor); + + if( OMX_ErrorNone == omxError) + { + *((int*)param) = sensor.eSensor; + } + break; + } + + case VCAM_PARAM_EXPOSURE_COMPENSATION: + { + OMX_CONFIG_EXPOSUREVALUETYPE expValues; + OMX_STRUCT_INIT( expValues, OMX_CONFIG_EXPOSUREVALUETYPE, mLocalVersion ); + omxError = OMX_GetConfig( mCurGreContext.mHandleComp , OMX_IndexConfigCommonExposureValue , &expValues ); + + if( OMX_ErrorNone == omxError ) + { + expValues.xEVCompensation *= 10; + int compVal = expValues.xEVCompensation / (1 << 16); + *((int*)param) = compVal; + } + break; + } + + case VCAM_PARAM_RESOLUTION: + { + int i = VCAM_RESOL_MAX; + unsigned int width, height; + OMX_PARAM_PORTDEFINITIONTYPE portCheck; + omxError = initPortCheck( &portCheck , port ); + + if( OMX_ErrorNone == omxError ) + { + width = portCheck.format.video.nFrameWidth; + height = portCheck.format.video.nFrameHeight; + for( i = 0; i < VCAM_RESOL_MAX; i++) + { + if( VisionCamResolutions[i].mWidth == width + && VisionCamResolutions[i].mHeight == height) + { + *((int*)param) = i; + break; + } + } + if( VCAM_RESOL_MAX == i ) + { + greError = STATUS_INVALID_PARAMETER; + } + } + break; + } + + case VCAM_PARAM_2DBUFFER_DIM: + { + OMX_CONFIG_RECTTYPE frame; + OMX_STRUCT_INIT(frame, OMX_CONFIG_RECTTYPE, mLocalVersion); + VisionCamResType *pRes = (VisionCamResType *)param; + + frame.nPortIndex = mCurGreContext.mPortsInUse[port]; + if (pRes && size == sizeof(VisionCamResType)) + { + // Set the port definition to update width and height first. + omxError = setPortDef( port ); + + if( OMX_ErrorNone == omxError ) + { + omxError = OMX_GetParameter(mCurGreContext.mHandleComp, + (OMX_INDEXTYPE)OMX_TI_IndexParam2DBufferAllocDimension, + &frame); + } + + if (OMX_ErrorNone == omxError) + { + pRes->mWidth = frame.nWidth; + pRes->mHeight = frame.nHeight; + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to query the 2D Buffer Dimensions! (err=0x%08x)\n", omxError); + memset(pRes, 0, sizeof(VisionCamResType)); + // omxError will convert to greError + } + } + else + greError = STATUS_INVALID_PARAMETER; + break; + } + + case VCAM_PARAM_MANUAL_EXPOSURE: + { + OMX_CONFIG_EXPOSUREVALUETYPE expValues; + OMX_STRUCT_INIT(expValues, OMX_CONFIG_EXPOSUREVALUETYPE, mLocalVersion); + + omxError = OMX_GetConfig( mCurGreContext.mHandleComp , OMX_IndexConfigCommonExposureValue , &expValues ); + + if( OMX_ErrorNone == omxError ) + { + if( OMX_TRUE == expValues.bAutoShutterSpeed ) + { + *(OMX_U32*)param = 0; + } + else + { + *(OMX_U32*)param = expValues.nShutterSpeedMsec; + } + } + break; + } + + case VCAM_PARAM_EXPOSURE_ISO: + { + OMX_CONFIG_EXPOSUREVALUETYPE expValues; + OMX_STRUCT_INIT( expValues, OMX_CONFIG_EXPOSUREVALUETYPE, mLocalVersion ); + + omxError = OMX_GetConfig( mCurGreContext.mHandleComp , OMX_IndexConfigCommonExposureValue , &expValues ); + + if( OMX_ErrorNone == omxError ) + { + if( OMX_TRUE == expValues.bAutoSensitivity ) + { + *(uint32_t*)param = 0; + } + else + *(uint32_t*)param = expValues.nSensitivity; + } + break; + } + + case VCAM_PARAM_AWB_MODE: + { + OMX_CONFIG_WHITEBALCONTROLTYPE wb; + OMX_STRUCT_INIT(wb, OMX_CONFIG_WHITEBALCONTROLTYPE, mLocalVersion ); + + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, + OMX_IndexConfigCommonWhiteBalance, + &wb); + + if( OMX_ErrorNone == omxError ) + { + *(int *)param = (int)wb.eWhiteBalControl; + } + break; + } + + case VCAM_PARAM_COLOR_TEMP: + { + DVP_PRINT(DVP_ZONE_WARNING, "No Getting Api for this Parameter %d\n", paramId); + break; + } + +#ifndef EXPORTED_3A + case VCAM_PARAM_WB_COLOR_GAINS: + { +#ifdef USE_WB_GAIN_PATCH + OMX_TI_CONFIG_SHAREDBUFFER skipBuffer; + + skipBuffer.nSize = sizeof( OMX_TI_CONFIG_SHAREDBUFFER ); + memcpy( &skipBuffer.nVersion , mLocalVersion , sizeof(OMX_VERSIONTYPE) ); + skipBuffer.pSharedBuff = (OMX_U8*)mWBbuffer; + skipBuffer.nSharedBuffSize = sizeof(mWBbuffer); + + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, + (OMX_INDEXTYPE) OMX_TI_IndexConfigAAAskipBuffer, + &skipBuffer ); + + if( OMX_ErrorNone == omxError ) + { + VisionCamWhiteBalGains wbGains; + uint16_t * tmp; + CALCULATE_WB_GAINS_OFFSET(uint16_t, mWBbuffer, tmp ); + + wbGains.mRed = tmp[ RED ]; + wbGains.mGreen_r = tmp[ GREEN_RED ]; + wbGains.mGreen_b = tmp[ GREEN_BLUE ]; + wbGains.mBlue = tmp[ BLUE ]; + + *((VisionCamWhiteBalGains*)param) = wbGains; + } +#endif // USE_WB_GAIN_PATCH + break; + } + + case VCAM_PARAM_GAMMA_TBLS: + { + + VisionCamGammaTableType *gammaTbl = (VisionCamGammaTableType*)param; + OMX_TI_CONFIG_SHAREDBUFFER skipBuffer; + skipBuffer.nSize = sizeof( OMX_TI_CONFIG_SHAREDBUFFER ); + memcpy( &skipBuffer.nVersion , mLocalVersion , sizeof(OMX_VERSIONTYPE) ); + + skipBuffer.pSharedBuff = (OMX_U8*)mGammaTablesBuf; + skipBuffer.nSharedBuffSize = sizeof(mGammaTablesBuf); + + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, + (OMX_INDEXTYPE) OMX_TI_IndexConfigAAAskipBuffer, + &skipBuffer ); + + if( OMX_ErrorNone == omxError ) + { + gammaTbl->mTableSize = GAMMA_TABLE_SIZE; + + uint32_t* base = (uint32_t *)(mGammaTablesBuf + 12); // 12 bytes offset for red table + gammaTbl->mRedTable = (uint16_t*)(base[0] + (uint32_t)&base[2]); + gammaTbl->mBlueTable = (uint16_t*)(base[1] + (uint32_t)&base[2]); + gammaTbl->mGreenTable = (uint16_t*)(base[2] + (uint32_t)&base[2]); + } + break; + } +#endif // EXPORTED_3A + + case VCAM_PARAM_ROTATION: + { + OMX_CONFIG_ROTATIONTYPE rotation; + OMX_STRUCT_INIT(rotation, OMX_CONFIG_ROTATIONTYPE, mLocalVersion); + omxError = OMX_GetConfig(mCurGreContext.mHandleComp, + OMX_IndexConfigCommonRotate, + &rotation); + if (OMX_ErrorNone == omxError) + *((OMX_S32*)param) = rotation.nRotation; + break; + } + + case VCAM_PARAM_MIRROR: + { + if( VCAM_PORT_ALL == port ) + { + greError = STATUS_INVALID_PARAMETER; + } + else + { + int i; + OMX_CONFIG_MIRRORTYPE mirror; + mirror.nSize = sizeof( OMX_CONFIG_MIRRORTYPE ); + mirror.nPortIndex = mCurGreContext.mPortsInUse[port]; + memcpy( &mirror.nVersion, mLocalVersion, sizeof(OMX_VERSIONTYPE)); + + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, + OMX_IndexConfigCommonMirror, + &mirror ); + + if( OMX_ErrorNone == omxError ) + { + for( i = 0; i < VCAM_MIRROR_MAX; i++ ) + { + if( MirrorTypeLUT[i][1] == mirror.eMirror ) + { + *((VisionCamMirrorType*)param) = (VisionCamMirrorType) MirrorTypeLUT[i][0]; + break; + } + } + + if( i >= VCAM_MIRROR_MAX ) + greError = STATUS_INVALID_PARAMETER; + } + } + break; + } + +#if ( defined(DUCATI_1_5) || defined(DUCATI_2_0) ) && defined(OMX_CAMERA_SUPPORTS_MANUAL_CONTROLS) + case VCAM_PARAM_AWB_MIN_DELAY_TIME: + { + uint32_t *timeDelay = (uint32_t*)param; + OMX_TI_CONFIG_AE_DELAY aeDelay; + OMX_STRUCT_INIT( aeDelay, OMX_TI_CONFIG_AE_DELAY, mLocalVersion ); + + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, + ( OMX_INDEXTYPE )OMX_TI_IndexConfigAutoExpMinDelayTime, + &aeDelay + ); + if( OMX_ErrorNone == omxError ) + { + *timeDelay = aeDelay.nDelayTime; + } + break; + } +#endif +#if ( defined(DUCATI_1_5) || defined(DUCATI_2_0) ) && defined(OMX_CAMERA_SUPPORTS_GESTURES) + case VCAM_PARAM_GESTURES_INFO: + { + VisionCamGestureInfo *info = (VisionCamGestureInfo *)param; + OMX_TI_CONFIG_GESTURES_INFO gestInfo; + int ret = 0; + + OMX_STRUCT_INIT( gestInfo, OMX_TI_CONFIG_GESTURES_INFO , mLocalVersion ); + + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, + (OMX_INDEXTYPE)OMX_TI_IndexConfigDetectedGesturesInfo, + &gestInfo + ); + + if( OMX_ErrorNone != omxError ) + break; + + ret = getLutValue( gestInfo.eType, OMX_VALUE_TYPE, + GestureTypeLUT, ARR_SIZE(GestureTypeLUT) + ); + + if( STATUS_INVALID_PARAMETER == ret ) + { + greError = STATUS_INVALID_PARAMETER; + } + else + { + info->mGestureType = (VisionCamGestureEvent_e)ret; + info->mRegionsNum = gestInfo.nNumDetectedGestures; + if( info->mRegionsNum >= VCAM_Max_Gesture_Per_Frame ) + { + greError= STATUS_INVALID_PARAMETER; + break; + } + + #ifdef __cplusplus + info->mRegions = new VisionCamObjectRectType[ info->mRegionsNum ]; + #else + if( NULL == info->mRegions ) + { + DVP_PRINT(DVP_ZONE_ERROR, "Please allocate the mRegions buffer"); + DVP_PRINT(DVP_ZONE_ERROR, "Check for necessery size in mRegionsNum"); + + greError= STATUS_NO_RESOURCES; + break; + } + #endif + + for(uint32_t i = 0; i < info->mRegionsNum; i++ ) + { + int value = getLutValue( (int)(gestInfo.nGestureAreas[i].eType), + OMX_VALUE_TYPE, + ObjectTypeLUT, + ARR_SIZE(ObjectTypeLUT) + ); + if (value == STATUS_INVALID_PARAMETER) + continue; + info->mRegions[i].mObjType = (VisionCamObjectType)value; + gestInfo.nGestureAreas[i].nTop = info->mRegions[i].mTop; + gestInfo.nGestureAreas[i].nLeft = info->mRegions[i].mLeft; + gestInfo.nGestureAreas[i].nWidth = info->mRegions[i].mWidth; + gestInfo.nGestureAreas[i].nHeight = info->mRegions[i].mHeight; + } + + info->timeStamp = gestInfo.nTimeStamp; + } + + break; + } +#endif +#if ( defined(DUCATI_1_5) || defined(DUCATI_2_0) ) && defined(OMX_CAMERA_SUPPORTS_MANUAL_CONTROLS) + case VCAM_PARAM_AGC_MIN_DELAY_TIME: + { + uint32_t *delay = (uint32_t*)param; + OMX_TI_CONFIG_AE_DELAY agcDelTime; + OMX_STRUCT_INIT( agcDelTime, OMX_TI_CONFIG_AE_DELAY, mLocalVersion ); + + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, + (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoExpMinDelayTime, + &agcDelTime ); + + if( OMX_ErrorNone != omxError ) + break; + + *delay = agcDelTime.nDelayTime; + break; + } + + case VCAM_PARAM_AGC_LOW_TH: + { + uint32_t *lowTH = (uint32_t*)param; + OMX_TI_CONFIG_AE_THRESHOLD ae; + + OMX_STRUCT_INIT( ae, OMX_TI_CONFIG_AE_THRESHOLD, mLocalVersion ); + + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoExpThreshold, &ae ); + + if( OMX_ErrorNone != omxError ) + break; + + *lowTH = ae.uMinTH; + break; + } + + case VCAM_PARAM_AGC_HIGH_TH: + { + uint32_t *highTH = (uint32_t*)param; + + OMX_TI_CONFIG_AE_THRESHOLD ae; + OMX_STRUCT_INIT( ae, OMX_TI_CONFIG_AE_THRESHOLD, mLocalVersion ); + + omxError = OMX_GetConfig( mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigAutoExpThreshold, &ae ); + + if( OMX_ErrorNone != omxError ) + break; + + *highTH = ae.uMaxTH; + break; + } +#endif +#if defined(OMX_CAMERA_SUPPORTS_IMAGE_PYRAMID) + case VCAM_PARAM_IMAGE_PYRAMID: + { + greError = getImagePyramid(param, size, port); + break; + } +#endif + default: + { + DVP_PRINT(DVP_ZONE_ERROR, "Impossible parameter id requested: %d\n", paramId); + DVP_PRINT(DVP_ZONE_ERROR, "see VisionCamParam_e for possible parameter ids\n"); + greError = STATUS_INVALID_PARAMETER; + } + } + + if( OMX_ErrorNone != omxError ) + { + greError = ConvertError(omxError); + } + + if( greError != STATUS_SUCCESS ) + { + DVP_PRINT(DVP_ZONE_ERROR, "getParameter() exits with error 0x%x (dec: %d) for param id %d\n", greError, greError, paramId); + } + + return greError; +} + +OMX_ERRORTYPE OMXVisionCam::getFocusStatus(OMX_FOCUSSTATUSTYPE *status) +{ + OMX_ERRORTYPE eError = OMX_ErrorNone; + OMX_PARAM_FOCUSSTATUSTYPE focusStatus; + OMX_STRUCT_INIT(focusStatus, OMX_PARAM_FOCUSSTATUSTYPE, mLocalVersion); + + // Get the focus status + OMX_CHECK(eError,OMX_GetConfig(mCurGreContext.mHandleComp, + OMX_IndexConfigCommonFocusStatus, + &focusStatus)); + if (eError == OMX_ErrorNone) + *status = focusStatus.eFocusStatus; + return eError; +} + +status_e OMXVisionCam::waitForFocus() +{ + OMX_ERRORTYPE omxError = OMX_ErrorNone; + OMX_FOCUSSTATUSTYPE focusStatus; + + omxError = RegisterForEvent(mCurGreContext.mHandleComp, + (OMX_EVENTTYPE) OMX_EventIndexSettingChanged, + OMX_ALL, + OMX_IndexConfigCommonFocusStatus, + &mGreFocusSem, + -1); + if (OMX_ErrorNone == omxError) + { + OMX_CONFIG_CALLBACKREQUESTTYPE focusRequestCallback; + OMX_STRUCT_INIT(focusRequestCallback, OMX_CONFIG_CALLBACKREQUESTTYPE, mLocalVersion); + focusRequestCallback.bEnable = OMX_TRUE; + focusRequestCallback.nIndex = OMX_IndexConfigCommonFocusStatus; + + // subscribe for focus state changes + OMX_CHECK(omxError,OMX_SetConfig(mCurGreContext.mHandleComp, + (OMX_INDEXTYPE) OMX_IndexConfigCallbackRequest, + &focusRequestCallback)); +#ifdef VCAM_CAUTIOUS + // make sure it's been registered + OMX_CHECK(omxError,OMX_GetConfig(mCurGreContext.mHandleComp, + (OMX_INDEXTYPE) OMX_IndexConfigCallbackRequest, + &focusRequestCallback)); + +#endif + if (OMX_ErrorNone == omxError && focusRequestCallback.bEnable == OMX_TRUE) + { + DVP_PRINT(DVP_ZONE_CAM, "Waiting for Focus Callback!\n"); + // wait for focus to arrive + semaphore_wait(&mGreFocusSem); + + // Give the client the focus greError + omxError = getFocusStatus(&focusStatus); + DVP_PRINT(DVP_ZONE_CAM, "Focus Status: %u\n", focusStatus); + if (OMX_ErrorNone == omxError) + { + if (m_focuscallback) + m_focuscallback((int)focusStatus); + } + } + } + return ConvertError(omxError); +} + +status_e OMXVisionCam::startAutoFocus( VisionCamFocusMode focusMode ) +{ + OMX_ERRORTYPE omxError = OMX_ErrorNone; + bool_e hasEvent = true_e; + + OMX_CONFIG_BOOLEANTYPE enable; + +// for( int32_t port = VCAM_PORT_MIN; port < VCAM_PORT_MAX; port++ ) + { + // @todo in case of two sensors running sumiltaneously check on which port to actiivate focus and for which to enqueue it. + if( !mCurGreContext.mCameraPortParams[VCAM_PORT_PREVIEW].mIsActive ) + { + mPendingConfigs->Register( ePending_Focus, + (VisionCamExecutionService::execFuncPrt_t)&OMXVisionCam::startAutoFocus, + sizeof(VisionCamFocusMode), + &focusMode + ); + return STATUS_SUCCESS; + } + } + + enable.nSize = sizeof(OMX_CONFIG_BOOLEANTYPE); + memcpy( &enable.nVersion, mLocalVersion, sizeof(OMX_VERSIONTYPE)); + if( focusMode == VCAM_FOCUS_CONTROL_OFF ) + { + enable.bEnabled = OMX_FALSE; + } + else + { + enable.bEnabled = OMX_TRUE; + } + + omxError = OMX_SetConfig(mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_TI_IndexConfigAutofocusEnable, &enable); + + if (focusMode == VCAM_FOCUS_CONTROL_OFF || + focusMode == VCAM_FOCUS_CONTROL_AUTO || + focusMode == VCAM_FOCUS_CONTROL_CONTINOUS_NORMAL || + focusMode == VCAM_FOCUS_CONTROL_CONTINOUS_EXTENDED) + { + hasEvent = false_e; + } + + if( OMX_ErrorNone == omxError ) + { + int value = 0; + OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focus; + OMX_STRUCT_INIT(focus, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE, mLocalVersion); + value = getLutValue(focusMode, VCAM_VALUE_TYPE, FocusModeLUT, ARR_SIZE(FocusModeLUT)); + + if (value == STATUS_INVALID_PARAMETER) + return (status_e)value; + + focus.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE )value; + + if( focus.eFocusControl == OMX_IMAGE_FocusControlOn ) + focus.nFocusSteps = mManualFocusDistance; + + DVP_PRINT(DVP_ZONE_CAM, "Focus Requested Steps @ %lu, Index @ %lu\n", focus.nFocusSteps, focus.nFocusStepIndex); + + // tell the OMX component to change the focus control mode + omxError = OMX_SetConfig(mCurGreContext.mHandleComp, OMX_IndexConfigFocusControl, &focus); + +#ifdef VCAM_CAUTIOUS + if( OMX_ErrorNone == omxError ) + { + // ask it what mode it's in now + OMX_CHECK(omxError, OMX_GetConfig(mCurGreContext.mHandleComp, OMX_IndexConfigFocusControl, &focus)); + } +#endif + DVP_PRINT(DVP_ZONE_CAM, "Focus Control Mode = 0x%08x\n", focus.eFocusControl); + } + + if ( OMX_ErrorNone == omxError ) + { + if (hasEvent) + { + thread_create(FocusThreadLauncher, this); + // the thread will die by itself, we don't need to join it. + } + } + + return ConvertError(omxError); +} + +/* This will set the preview buffer sizes, format, etc. + */ +OMX_ERRORTYPE OMXVisionCam::setPortDef( int32_t port ) +{ + OMX_ERRORTYPE omxError = OMX_ErrorNone; + + VCAM_PortParameters * portData = NULL; + OMX_PARAM_PORTDEFINITIONTYPE portCheck; + + int32_t p; + LOOP_PORTS( port , p ) + { + omxError = initPortCheck(&portCheck, p); + + if( omxError == OMX_ErrorNone ) + { + portData = &mCurGreContext.mCameraPortParams[p]; + portCheck.format.video.nFrameWidth = portData->mWidth; + portCheck.format.video.nFrameHeight = portData->mHeight; + portCheck.format.video.eColorFormat = portData->mColorFormat; + portCheck.format.video.nStride = portData->mStride; + portCheck.format.video.xFramerate = portData->mFrameRate << 16; + portCheck.nBufferCountActual = portData->mNumBufs; + omxError = OMX_SetParameter(mCurGreContext.mHandleComp, + OMX_IndexParamPortDefinition, + &portCheck); + } + + if( omxError == OMX_ErrorNone ) + omxError = initPortCheck(&portCheck, p); + + if( omxError == OMX_ErrorNone ) + portData->mBufSize = portCheck.nBufferSize; + +#if defined(VCAM_SET_FORMAT_ROTATION) + // set the rotation type on the port + if (omxError == OMX_ErrorNone) + { + OMX_CONFIG_ROTATIONTYPE rotType; + OMX_STRUCT_INIT(rotType, OMX_CONFIG_ROTATIONTYPE, mLocalVersion); + rotType.nRotation = mCurGreContext.mCameraPortParams[p].mRotation; + rotType.nPortIndex = mCurGreContext.mPortsInUse[p]; + DVP_PRINT(DVP_ZONE_CAM, "VCAM: Configuring for Rotation %li\n",rotType.nRotation); + OMX_CHECK(omxError, OMX_SetConfig(mCurGreContext.mHandleComp, + OMX_IndexConfigCommonRotate, + &rotType)); + } +#endif + } + + return omxError; +} + +/* This will start the preview. + * Before that setParameter() sould be called, to configure the preview port. + * This method is only called internal for OMXVisionCam + * by sendCommand(). + */ +status_e OMXVisionCam::startPreview( VisionCamPort_e port ) +{ + status_e greError = STATUS_SUCCESS; + OMX_ERRORTYPE omxError; + + if( port < VCAM_PORT_ALL || port > VCAM_PORT_MAX - 1 ) + { + DVP_PRINT(DVP_ZONE_ERROR, "startPreview() called, but port is not specified properly.\n"); + return STATUS_INVALID_PARAMETER; + } + + switch((int32_t)getComponentState()) + { + case OMX_StateIdle: + { + greError = transitToState( OMX_StateExecuting ); + mReturnToExecuting = true_e; + break; + } + case OMX_StateLoaded: + case OMX_StateWaitForResources: + case OMX_StateInvalid: + { + DVP_PRINT(DVP_ZONE_ERROR, "Calling startPreview() in an inproper state.\n"); + greError = STATUS_INVALID_STATE; + break; + } + case OMX_StateExecuting: + case OMX_StatePause: + { + break; + } + default: + break; + } + + SOSAL::AutoLock lock( &mFrameBufferLock ); + + if( STATUS_SUCCESS == greError ) + mFlushInProcess = false_e; + + if( STATUS_SUCCESS == greError ) + { + omxError = setPortDef( port ); + greError = ConvertError(omxError); + } + + if( STATUS_SUCCESS == greError ) + { + greError = portEnableDisable( OMX_CommandPortEnable, populatePortSrvc, port); + } + + if( STATUS_SUCCESS == greError ) + { + // Some configurations couldn't be set before preview has been started + // so we need to call their executuion right after preview is started + // let us make it by the time the very first frame is received ! + pFrameReceivedSrvc = &OMXVisionCam::FirstFrameFunc; + + // first fill the video port buffers, then preview port + // otherwise preview port will start working right after it receive its frames + // so it won't wait for video port to get ready + if( VCAM_PORT_ALL == port || VCAM_PORT_VIDEO == port ) + { + greError = fillPortBuffers(VCAM_PORT_VIDEO); + } + + if( VCAM_PORT_ALL == port || VCAM_PORT_PREVIEW == port ) + { + greError = fillPortBuffers(VCAM_PORT_PREVIEW); + } + } + + return greError; +} + +/** + * This will stop the preview + * + */ +status_e OMXVisionCam::stopPreview( VisionCamPort_e port ) +{ + status_e greError = STATUS_SUCCESS; + bool_e goToIdle = true_e; + + mFlushInProcess = true_e; + + flushBuffers( port ); + greError = portEnableDisable( OMX_CommandPortDisable, freePortBuffersSrvc, port ); + + if( STATUS_SUCCESS == greError ) + { + for( int p = VCAM_PORT_MIN; p < VCAM_PORT_MAX; p++) + { + if( mCurGreContext.mCameraPortParams[p].mIsActive ) + { + goToIdle = false_e; + break; + } + } + + if ( goToIdle && OMX_StateExecuting == getComponentState() ) + { + transitToState( OMX_StateIdle ); + } + } + + return greError; +} + +/** + * This will free all the buffers on the preview port + * and switch to loaded state. + */ +status_e OMXVisionCam::releaseBuffers( VisionCamPort_e port) +{ + status_e greError = STATUS_SUCCESS; + + OMX_PARAM_PORTDEFINITIONTYPE portCheck[ VCAM_PORT_MAX ]; + + int32_t p; + LOOP_PORTS( port , p ) + { + initPortCheck(&portCheck[p], p); + + for( uint32_t indBuff = 0; indBuff < portCheck[p].nBufferCountActual; indBuff++ ) + { + if( mFrameDescriptors && mFrameDescriptors[p] && mFrameDescriptors[p][indBuff] ) + delete mFrameDescriptors[p][indBuff]; + } + + if( mFrameDescriptors && mFrameDescriptors[p] ) + { + delete mFrameDescriptors[p]; + mFrameDescriptors[p] = NULL; + } + } + + if (OMX_StateIdle == getComponentState()) + greError = transitToState( OMX_StateLoaded, NULL, NULL ); + + return greError; +} + +/** This will configure the component to start/stop face detection. + * Will also start/stop face detection extra data + * faces coordinates will be written into camera frame received + * in preview callback + */ +status_e OMXVisionCam::enableFaceDetect(VisionCamPort_e port, VisionCamFaceDetectionType_t fdType ) +{ + OMX_ERRORTYPE omxError = OMX_ErrorNone; + OMX_CONFIG_OBJDETECTIONTYPE objDetection; + OMX_STRUCT_INIT( objDetection, OMX_CONFIG_OBJDETECTIONTYPE ,mLocalVersion); + objDetection.nPortIndex = mCurGreContext.mPortsInUse[port]; + + if ( mFaceDetectionEnabled & VCAM_FACE_DETECTION_ALL ) + { + objDetection.bEnable = OMX_TRUE; + } + else + { + objDetection.bEnable = OMX_FALSE; + } + + omxError = OMX_SetConfig(mCurGreContext.mHandleComp, (OMX_INDEXTYPE) OMX_IndexConfigImageFaceDetection, &objDetection); + + if ( OMX_ErrorNone == omxError ) + { + OMX_CONFIG_EXTRADATATYPE xData; + OMX_STRUCT_INIT(xData, OMX_CONFIG_EXTRADATATYPE, mLocalVersion); + + xData.nPortIndex = mCurGreContext.mPortsInUse[port]; + +#if defined(OMX_CAMERA_SUPPORTS_CAMERA_VIEW) + xData.eCameraView = OMX_2D_Prv; +#endif + + for( int32_t i = VCAM_FACE_DETECTION_MIN; i < VCAM_FACE_DETECTION_MAX; i <<= 1 ) + { + if( i & fdType ) + { + switch(i) + { + case VCAM_FACE_DETECTION: + xData.eExtraDataType = OMX_FaceDetection; + break; +#if defined(OMX_CAMERA_SUPPORTS_FD_RAW) + case VCAM_FACE_DETECTION_RAW: + xData.eExtraDataType = OMX_TI_FaceDetectionRaw; + break; +#endif + } + + xData.bEnable = ( (mFaceDetectionEnabled & fdType) ? OMX_TRUE : OMX_FALSE ); + omxError = OMX_SetConfig(mCurGreContext.mHandleComp, (OMX_INDEXTYPE)OMX_IndexConfigOtherExtraDataControl, &xData); + + if( OMX_ErrorNone != omxError ) + { + DVP_PRINT(DVP_ZONE_ERROR, "Unable to start/stop face detect.\n"); + break; + } + } + } + } + + return ConvertError(omxError); +} + +/** Fill the face coordinates field in camera frame, + * which will be received by OMXVisionCam client at each frame. + */ +void OMXVisionCam::getFacesCoordinates( VisionCamFrame *frame) +{ + OMX_OTHER_EXTRADATATYPE* extraData = NULL; + OMX_U8 *pExtraLimit = (OMX_U8 *)(frame->mExtraDataBuf) + frame->mExtraDataLength; + OMX_FACEDETECTIONTYPE *facesData = NULL; + + OMX_EXT_EXTRADATATYPE expectedFD = (OMX_EXT_EXTRADATATYPE)OMX_ExtraDataNone; + uint32_t *frameFacesCount = NULL; + VisionCamFaceType *frameFacesData = NULL; + + if( !frame->mExtraDataBuf ) + { + frame->mDetectedFacesNum = 0; + frame->mDetectedFacesNumRaw = 0; + return; + } + + for( int32_t fdSeek = VCAM_FACE_DETECTION_MIN; fdSeek < VCAM_FACE_DETECTION_ALL; fdSeek <<= 1 ) + { + switch(fdSeek & mFaceDetectionEnabled) + { +#if defined(OMX_CAMERA_SUPPORTS_FD_RAW) + case VCAM_FACE_DETECTION_RAW: + { + expectedFD = OMX_TI_FaceDetectionRaw; + frameFacesCount = &frame->mDetectedFacesNumRaw; + frameFacesData = &frame->mFacesRaw[0]; + break; + } +#endif + case VCAM_FACE_DETECTION: + { + expectedFD = OMX_FaceDetection; + frameFacesCount = &frame->mDetectedFacesNum; + frameFacesData = &frame->mFaces[0]; + break; + } + default: + continue; + } + + *frameFacesCount = 0; + memset( frameFacesData, 0, MAX_FACES_COUNT*sizeof(VisionCamFaceType) ); + + extraData = (OMX_OTHER_EXTRADATATYPE*)frame->mExtraDataBuf; + + while( expectedFD != (OMX_EXT_EXTRADATATYPE)extraData->eType && extraData->data ) + { + DVP_PRINT(DVP_ZONE_CAM, "Current Extra Data Section Size: %lu\n", extraData->nDataSize); + extraData = (OMX_OTHER_EXTRADATATYPE*)(extraData->data + extraData->nDataSize); + + if( (OMX_U8 *)extraData >= pExtraLimit ) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: METADATA: Bad size field in metadata. %p >= %p\n", extraData, pExtraLimit); + return; + } + + if( 0 == extraData->nDataSize ) + { + DVP_PRINT(DVP_ZONE_WARNING, "METADATA: No face data detected!\n"); + return; + } + } + + if( extraData->data ) + { + facesData = (OMX_FACEDETECTIONTYPE *)(extraData->data); + *frameFacesCount = facesData->ulFaceCount; + + DVP_PRINT(DVP_ZONE_CAM, "METADATA: FACE # %d!\n", facesData->ulFaceCount); + + for(uint32_t i = 0; i < facesData->ulFaceCount; i++) + { + memcpy( &(frameFacesData[i]), &(facesData->tFacePosition[i].nScore), sizeof(VisionCamFaceType)) ; + } + } + } +} + +/** Parse through the extra data type structure to find the pointer to the relevent + * data type. This is to abstract the port number, version, and packet structure from the client. + */ +void OMXVisionCam::getMetadataPtrs( VisionCamFrame *frame) +{ + OMX_OTHER_EXTRADATATYPE* extraData = (OMX_OTHER_EXTRADATATYPE*)frame->mExtraDataBuf; + OMX_U8 *pExtraLimit = (OMX_U8 *)extraData + frame->mExtraDataLength; + frame->mMetadata.mAutoWBGains = NULL; + frame->mMetadata.mManualWBGains = NULL; + frame->mMetadata.mAncillary = NULL; + frame->mMetadata.mHistogram2D = NULL; + frame->mMetadata.mHistogramL = NULL; + frame->mMetadata.mHistogramR = NULL; + frame->mMetadata.mMTIS_Data = NULL; + frame->mMetadata.mUnsaturatedRegions = NULL; + frame->mMetadata.mFocusRegionData = NULL; + frame->mMetadata.mGamma2D = NULL; + frame->mMetadata.mGammaL = NULL; + frame->mMetadata.mGammaR = NULL; + + if( extraData == NULL ) + { + return; + } + + while( extraData->eType && extraData->nDataSize && extraData->data ) // keep looping while there is more extra data and double check size + { + switch( (OMX_EXT_EXTRADATATYPE)extraData->eType ) + { + case OMX_AncillaryData: + { + OMX_TI_ANCILLARYDATATYPE *ancillaryData = NULL; + DVP_PRINT(DVP_ZONE_CAM, "METADATA: Found Ancillary Data Section!\n"); + ancillaryData = (OMX_TI_ANCILLARYDATATYPE *)(extraData->data); + frame->mMetadata.mAncillary= (VisionCamAncillary*)&ancillaryData->nAncillaryDataVersion; + break; + } + + case OMX_WhiteBalance: + { + OMX_TI_WHITEBALANCERESULTTYPE *wbData = NULL; + DVP_PRINT(DVP_ZONE_CAM, "METADATA: Found White Balance Result Data Section!\n"); + wbData = (OMX_TI_WHITEBALANCERESULTTYPE *)(extraData->data); + frame->mMetadata.mAutoWBGains = (VisionCamWhiteBalGains*)&wbData->nGainR; + break; + } +#if defined(OMX_CAMERA_SUPPORTS_WHITEBALANCE_OVERWRITE) + case OMX_TI_WhiteBalanceOverWrite: + { + OMX_TI_WHITEBALANCERESULTTYPE *wbManData = NULL; + DVP_PRINT(DVP_ZONE_CAM, "METADATA: Found White Balance Overwrite Data Section!\n"); + wbManData = (OMX_TI_WHITEBALANCERESULTTYPE *)(extraData->data); + frame->mMetadata.mManualWBGains = (VisionCamWhiteBalGains*)&wbManData->nGainR; + break; + } +#endif +#if defined(OMX_CAMERA_SUPPORTS_HISTOGRAM) + case OMX_Histogram: + { + OMX_TI_HISTOGRAMTYPE *histData = NULL; + DVP_PRINT(DVP_ZONE_CAM, "METADATA: Found Histogram Result Data Section!\n"); + histData = (OMX_TI_HISTOGRAMTYPE *)(extraData->data); +#if defined(OMX_CAMERA_SUPPORTS_CAMERA_VIEW) + if((OMX_TI_CAMERAVIEWTYPE)(histData->eCameraView) == OMX_2D_Prv) + frame->mMetadata.mHistogram2D = (VisionCamHistogram*)&histData->nBins; + else if((OMX_TI_CAMERAVIEWTYPE)(histData->eCameraView) == OMX_3D_Left_Prv) + frame->mMetadata.mHistogramL = (VisionCamHistogram*)&histData->nBins; + else if((OMX_TI_CAMERAVIEWTYPE)(histData->eCameraView) == OMX_3D_Right_Prv) + frame->mMetadata.mHistogramR = (VisionCamHistogram*)&histData->nBins; +#else + frame->mMetadata.mHistogram2D = (VisionCamHistogram*)&histData->nBins; +#endif + break; + } +#endif + case OMX_UnsaturatedRegions: + { + OMX_TI_UNSATURATEDREGIONSTYPE *usReg = NULL; + DVP_PRINT(DVP_ZONE_CAM, "METADATA: Found Unsaturated Regions Data Section!\n"); + usReg = (OMX_TI_UNSATURATEDREGIONSTYPE *)(extraData->data); + frame->mMetadata.mUnsaturatedRegions = + (VisionCamUnsaturatedRegions *)&usReg->nPaxelsX; + break; + } + +#if defined(OMX_CAMERA_SUPPORTS_MTIS) + case OMX_MTISType: + { + OMX_MTISTYPE *mtisData = NULL; + DVP_PRINT(DVP_ZONE_CAM, "METADATA: Found MTIS Data Section!\n"); + mtisData = (OMX_MTISTYPE *)(extraData->data); + frame->mMetadata.mMTIS_Data =(VisionCamMTIS*)&mtisData->eCameraView; + break; + } +#elif defined(OMX_CAMERA_SUPPORTS_TI_MTIS) + case OMX_TI_MTISType: + { + OMX_TI_MTISTYPE *mtisData = NULL; + DVP_PRINT(DVP_ZONE_CAM, "METADATA: Found MTIS Data Section!\n"); + mtisData = (OMX_TI_MTISTYPE *)(extraData->data); + frame->mMetadata.mMTIS_Data =(VisionCamMTIS*)&mtisData->eCameraView; + break; + } +#endif + case OMX_FocusRegion: + { + OMX_CONFIG_EXTFOCUSREGIONTYPE *focusRegData = NULL; + DVP_PRINT(DVP_ZONE_CAM, "METADATA: Found Focus Region Data Section!\n"); + focusRegData = (OMX_CONFIG_EXTFOCUSREGIONTYPE *)(extraData->data); + frame->mMetadata.mFocusRegionData =(VisionCamFocusRegion*)&focusRegData->nLeft; + break; + } + +#if defined(OMX_CAMERA_SUPPORTS_HMSGAMMA) + case OMX_TI_HMSGamma: + { + OMX_HMSGAMMATYPE *histGammaData = NULL; + DVP_PRINT(DVP_ZONE_CAM, "METADATA: Found Gamma Data Section!\n"); + histGammaData = (OMX_HMSGAMMATYPE *)(extraData->data); +#if defined(OMX_CAMERA_SUPPORTS_CAMERA_VIEW) + if((OMX_TI_CAMERAVIEWTYPE)(histGammaData->eCameraView) == OMX_2D_Prv) + frame->mMetadata.mGamma2D = (VisionCamGamma*)&histGammaData->nItems; + else if((OMX_TI_CAMERAVIEWTYPE)(histGammaData->eCameraView) == OMX_3D_Left_Prv) + frame->mMetadata.mGammaL = (VisionCamGamma*)&histGammaData->nItems; + else if((OMX_TI_CAMERAVIEWTYPE)(histGammaData->eCameraView) == OMX_3D_Right_Prv) + frame->mMetadata.mGammaR = (VisionCamGamma*)&histGammaData->nItems; +#else + frame->mMetadata.mGamma2D = (VisionCamGamma*)&histGammaData->nItems; +#endif + break; + } +#endif + +// case OMX_FaceDetection: + // done in getFacesCoordinates() +// break; + +// case OMX_TI_FaceDetectionRaw: + // done in getFacesCoordinates() +// break; + + default: + { + break; + } + } + DVP_PRINT(DVP_ZONE_CAM, "Current Extra Data Section Size: %lu\n", extraData->nDataSize); + extraData = (OMX_OTHER_EXTRADATATYPE*)(extraData->data + extraData->nDataSize); + if( (OMX_U8 *)extraData >= pExtraLimit ) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: METADATA: Bad size field in metadata. %p >= %p\n", extraData, pExtraLimit); + break; + } + } +} + +/** This shall be called by the user of this class when it finishes working + * with the frame and to notify VisionCam that the frame buffer is + * free. + */ +status_e OMXVisionCam::returnFrame(VisionCamFrame *cameraFrame) +{ + OMX_ERRORTYPE omxError = OMX_ErrorNone; + int32_t i = 0; + if (mFlushInProcess) + return STATUS_SUCCESS; + + if (cameraFrame == NULL) + return STATUS_INVALID_PARAMETER; + + if (OMX_StateExecuting == getComponentState()) + { + VisionCamPort_e port = cameraFrame->mFrameSource; + VCAM_PortParameters * portData = &mCurGreContext.mCameraPortParams[port]; + for (i = 0; i < portData->mNumBufs; i++) + { + if (portData->mBufferHeader[i] && + portData->mBufferHeader[i]->pAppPrivate == cameraFrame->mFrameBuff) + { + omxError = OMX_FillThisBuffer(mCurGreContext.mHandleComp, + mCurGreContext.mCameraPortParams[port].mBufferHeader[i]); + if (OMX_ErrorNone != omxError) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: OMX_FillThisBuffer() returned 0x%x in %s\n", omxError, __func__); + } + else + { + DVP_PRINT(DVP_ZONE_CAM, "frame returned successfully in %s\n", __func__); + } + break; + } + } + if( i == portData->mNumBufs) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: returned frame not found in %s\n", __func__); + } + } + else + { + DVP_PRINT(DVP_ZONE_WARNING, "Returning Frame when OMX-CAMERA is in the wrong state or image is NULL\n"); + } + + return ConvertError(omxError); +} + +status_e OMXVisionCam::PreemptionService(/*VisionCamPreemptionActivity_e activity*/) +{ + OMX_ERRORTYPE omxError = OMX_ErrorNone; + VCAM_PortParameters * portData = NULL; + + switch( mPreemptionState ) + { + case VCAM_PREEMPT_SUSPEND: + { + // Register for Loaded state switch event + omxError = RegisterForEvent(mCurGreContext.mHandleComp, + OMX_EventCmdComplete, + OMX_CommandStateSet, + OMX_StateLoaded, + &mGreLocalSem, + -1); // Infinite timeout + + if( OMX_ErrorNone == omxError ) + { + for( int port = VCAM_PORT_PREVIEW; port < VCAM_PORT_MAX; port++ ) + { + // Free the OMX Buffers + portData = &mCurGreContext.mCameraPortParams[port]; + for( int i = 0; i < portData->mNumBufs; i++ ) + { + omxError = OMX_FreeBuffer(mCurGreContext.mHandleComp, + mCurGreContext.mPortsInUse[port], + portData->mBufferHeader[i]); + + portData->mBufferHeader[i] = NULL; + + if( OMX_ErrorNone != omxError ) + { + DVP_PRINT(DVP_ZONE_ERROR, + "Preemption Service: Error 0x%x while freeing buffers!", omxError); + break; + } + } + } + } + + if( OMX_ErrorNone == omxError ) + semaphore_wait(&mGreLocalSem); + + if( mClientNotifier.mNotificationCallback && OMX_ErrorNone == omxError ) + mClientNotifier.mNotificationCallback(VisionCamClientNotifier::VCAM_MESSAGE_PREEMPT_SUSPEND_ACTIVITY); + + // Register for WAIT state switch event + omxError = RegisterForEvent(mCurGreContext.mHandleComp, + OMX_EventCmdComplete, + OMX_CommandStateSet, + OMX_StateWaitForResources, + &mGreLocalSem, + -1); // Infinite timeout + + if( OMX_ErrorNone == omxError ) + { + omxError = OMX_SendCommand(mCurGreContext.mHandleComp, + OMX_CommandStateSet, + OMX_StateWaitForResources, + NULL); + } + + if( OMX_ErrorNone == omxError ) + semaphore_wait(&mGreLocalSem); + + break; + } + case VCAM_PREEMPT_RESUME: + { + if( mClientNotifier.mNotificationCallback ) + mClientNotifier.mNotificationCallback(VisionCamClientNotifier::VCAM_MESSAGE_PREEMPT_RESUME_ACTIVITY); + + // Register for IDLE state switch event + omxError = RegisterForEvent(mCurGreContext.mHandleComp, + OMX_EventCmdComplete, + OMX_CommandStateSet, + OMX_StateIdle, + &mGreLocalSem, + -1); //Infinite timeout + if( OMX_ErrorNone != omxError ) + { + DVP_PRINT(DVP_ZONE_ERROR, + "Preemption Service: Error 0x%x while registering for Idle state wait.", omxError); + break; + } + + for( int port = VCAM_PORT_PREVIEW; port < VCAM_PORT_MAX; port++ ) + { + portData = &mCurGreContext.mCameraPortParams[port]; + for( int buff = 0; buff < portData->mNumBufs; buff++ ) + { + OMX_BUFFERHEADERTYPE *pBufferHdr; + OMX_U8 *buffer = mBuffersInUse[port].mBuffers[buff].pData[0]; + + omxError = OMX_UseBuffer( mCurGreContext.mHandleComp, + &pBufferHdr, + mCurGreContext.mPortsInUse[port], + 0, + portData->mBufSize, + buffer + ); + + if( OMX_ErrorNone != omxError ) + { + DVP_PRINT(DVP_ZONE_ERROR, + "Preemption Service: Error 0x%x while passing buffers to OMX Component.", omxError); + break; + } + + pBufferHdr->pAppPrivate = (OMX_PTR)&mBuffersInUse[port].mBuffers[buff]; + + pBufferHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); + + memcpy( &(pBufferHdr->nVersion), mLocalVersion, sizeof( OMX_VERSIONTYPE ) ); + + portData->mBufferHeader[buff] = pBufferHdr; + } + } + + semaphore_wait(&mGreLocalSem); + +// if (mReturnToExecuting) +// { + for( int port = VCAM_PORT_PREVIEW; port < VCAM_PORT_MAX; port++ ) + { + if( mCurGreContext.mCameraPortParams[port].mIsActive ) + startPreview( (VisionCamPort_e)port ); + } +// } + break; + } + + case VCAM_PREEMPT_WAIT_TO_START: + { + if( mClientNotifier.mNotificationCallback && OMX_ErrorNone == omxError ) + mClientNotifier.mNotificationCallback(VisionCamClientNotifier::VCAM_MESSAGE_PREEMPT_WAIT_RESOURCES); + + // Register for WAIT state switch event + omxError = RegisterForEvent(mCurGreContext.mHandleComp, + OMX_EventCmdComplete, + OMX_CommandStateSet, + OMX_StateWaitForResources, + &mGreLocalSem, + -1); // Infinite timeout + + if( OMX_ErrorNone == omxError ) + { + omxError = OMX_SendCommand(mCurGreContext.mHandleComp, + OMX_CommandStateSet, + OMX_StateWaitForResources, + NULL); + } + + if( OMX_ErrorNone == omxError ) + semaphore_wait(&mGreLocalSem); + + // Register for WAIT state switch event + omxError = RegisterForEvent(mCurGreContext.mHandleComp, + OMX_EventResourcesAcquired, + 0, + 0, + &mGreLocalSem, + -1); // Infinite timeout + + if( OMX_ErrorNone == omxError ) + semaphore_wait(&mGreLocalSem); + + if( mClientNotifier.mNotificationCallback && OMX_ErrorNone == omxError ) + mClientNotifier.mNotificationCallback(VisionCamClientNotifier::VCAM_MESSAGE_PREAMPT_RESOURCES_READY); + + break; + } + default: + + break; + } + + if( OMX_ErrorNone == omxError ) + mPreemptionState = VCAM_PREEMPT_INACTIVE; + + return ConvertError(omxError); +} + +OMX_ERRORTYPE OMXVisionCam::RegisterForEvent(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, + OMX_IN OMX_U32 nData2, + OMX_IN semaphore_t *semaphore, + OMX_IN OMX_U32 timeout) +{ + OMXVCAM_Msg_t *msg = (OMXVCAM_Msg_t *)calloc(1, sizeof(OMXVCAM_Msg_t)); + node_t *node = (node_t *)calloc(1, sizeof(node_t)); + OMX_ERRORTYPE err = OMX_ErrorNone; + if (msg && node) + { + msg->eEvent = eEvent; + msg->nData1 = nData1; + msg->nData2 = nData2; + msg->semaphore = semaphore; + msg->hComponent = hComponent; + msg->timeout = timeout; + node->data = (value_t)msg; + list_append(mEventSignalQ, node); + DVP_PRINT(DVP_ZONE_CAM, "Registering for Event %d (0x%08x)\n", eEvent,eEvent); + } + else + { + if (node) + free(node); + if (msg) + free(msg); + err = OMX_ErrorInsufficientResources; + } + return err; + +} + +extern "C" int node_compare_vcam_msg(node_t *a, node_t *b) +{ + OMXVCAM_Msg_t *msgA = (OMXVCAM_Msg_t *)a->data; + OMXVCAM_Msg_t *msgB = (OMXVCAM_Msg_t *)b->data; + + DVP_PRINT(DVP_ZONE_CAM, "Comparing Node %p and Node %p\n",msgA, msgB); + + if (msgA->eEvent == msgB->eEvent && + msgA->nData1 == msgB->nData1 && + msgA->nData2 == msgB->nData2 && + msgA->hComponent == msgB->hComponent) + return 0; + else if (msgA->eEvent < msgB->eEvent) + return -1; + else // if (msgA->event > msgB->event) + return 1; +} + +/** OMXVisionCam Event Handler from OMX-CAMERA */ +OMX_ERRORTYPE OMXVisionCam::EventHandler(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, + OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData) +{ + // make a local pointer to the instance class which registered this callback. + OMXVisionCam *pOMXCam = (OMXVisionCam*)pAppData; + size_t len = list_length(pOMXCam->mEventSignalQ); + + pEventData = pEventData; // warnings + DVP_PRINT(DVP_ZONE_CAM, "OMXVisionCam::EventHandler() event=%d arg1=%08x arg2=%08x ptr=%p (len="FMT_SIZE_T")\n", eEvent, (uint32_t)nData1, (uint32_t)nData2, pEventData, len); + // check the queue to see if we were waiting on an event + if (len > 0) + { + OMXVCAM_Msg_t thisMsg = {eEvent, nData1, nData2, NULL, hComponent, -1}; + node_t thisNode = {NULL, NULL, (value_t)&thisMsg}; + + // find the list event which matches this event + node_t * found = list_search(pOMXCam->mEventSignalQ, &thisNode, node_compare_vcam_msg); + if (found) + { + OMXVCAM_Msg_t *msg = (OMXVCAM_Msg_t *)found->data; + DVP_PRINT(DVP_ZONE_CAM, "Found Event in List which matches incoming event!\n"); + if (msg->semaphore) + semaphore_post(msg->semaphore); + + found = list_extract(pOMXCam->mEventSignalQ, found); + free(found); + free(msg); + } + else + { + DVP_PRINT(DVP_ZONE_CAM, "No matching event found in list!\n"); + } + } + + switch( eEvent ) + { + case OMX_EventError: + { + switch( nData1 ) + { + case OMX_ErrorResourcesPreempted: + break; + case OMX_ErrorResourcesLost: + { + DVP_PRINT(DVP_ZONE_WARNING, "OMXVisionCam lost resources!\n"); + pOMXCam->mPreemptionState = VCAM_PREEMPT_SUSPEND; + thread_create( PreemptionThreadLauncher, pOMXCam ); + break; + } + case OMX_ErrorInsufficientResources: + { + DVP_PRINT(DVP_ZONE_ERROR, "OMXVisionCam has insufficient resources!\n"); + pOMXCam->mPreemptionState = VCAM_PREEMPT_SUSPEND; + thread_create( PreemptionThreadLauncher, pOMXCam ); + break; + } + case OMX_ErrorIncorrectStateOperation: + { + break; + } + case OMX_ErrorInvalidState: + { + break; + } + default: + + break; + } + break; + } + case OMX_EventResourcesAcquired: + { + break; + } + case OMX_EventCmdComplete: + { + switch (nData1) + { + case OMX_CommandStateSet: + PrintOMXState((OMX_STATETYPE)nData2); + break; + case OMX_CommandFlush: + case OMX_CommandPortDisable: + case OMX_CommandPortEnable: + break; + } + break; + } + case OMX_EventPortSettingsChanged: + case OMX_EventIndexSettingChanged: + DVP_PRINT(DVP_ZONE_CAM, "*** Port/Index Settings have Changed!\n"); + break; + default: + break; + } + return OMX_ErrorNone; +} + +//GRE Empty buffer done callback +OMX_ERRORTYPE OMXVisionCam::EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffHeader) +{ +// OMXVisionCam *pOMXCam = (OMXVisionCam *)pAppData; + pAppData = pAppData; + hComponent = hComponent; + pBuffHeader = pBuffHeader; + return OMX_ErrorNotImplemented; +} + +//GRE fill buffer done callback +OMX_ERRORTYPE OMXVisionCam::FillBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffHeader) +{ + OMX_ERRORTYPE eError = OMX_ErrorNone; + OMXVisionCam *pOMXCam = (OMXVisionCam *)pAppData; + + hComponent = hComponent; + DVP_PRINT(DVP_ZONE_CAM, "OMX-CAMERA has returned a frame (%p) Offset=%lu!\n", pBuffHeader->pAppPrivate,pBuffHeader->nOffset); + + SimpleMsg_t msg; + msg.event = EFrameReceived; + msg.data = (void*)pBuffHeader; + + if( queue_write(pOMXCam->mFrameMessageQ, true_e, &msg) ) + semaphore_post(&pOMXCam->mFrameSem ); +// else HERE + + return eError; +} + +void OMXVisionCam::frameReceivedSrvc(void *data) +{ + (this->*pFrameReceivedSrvc)(data); +} + +void OMXVisionCam::FirstFrameFunc(void * data) +{ + if( mPendingConfigs ) + { + for( int32_t pend = ePending_Min; pend < ePending_Max; pend++ ) + { + switch( pend ) + { + case ePending_Focus: + VisionCamFocusMode *focData = (VisionCamFocusMode *)mPendingConfigs->getData(pend); + status_e (OMXVisionCam::*fn)(VisionCamFocusMode) = NULL; + fn = (status_e (OMXVisionCam::*)(VisionCamFocusMode))(mPendingConfigs->getFunc(pend)); + if( fn && focData ) + { + (this->*fn)(*focData); + } + break; + } + + } + } + + FrameReceivedFunc(data); + pFrameReceivedSrvc = &OMXVisionCam::FrameReceivedFunc; +} + +void OMXVisionCam::FrameReceivedFunc(void *data) +{ + OMX_BUFFERHEADERTYPE* pBuffHeader = (OMX_BUFFERHEADERTYPE* )data; + VisionCamFrame *cFrame = NULL; + VisionCamPort_e portInd = VCAM_PORT_MAX; + + if( !data ) + { + return; + } + + if( mFlushInProcess ) + { + return; + } + + SOSAL::AutoLock lock( &mFrameBufferLock ); + + switch(pBuffHeader->nOutputPortIndex) + { + case VCAM_CAMERA_PORT_VIDEO_OUT_PREVIEW: + { + portInd = VCAM_PORT_PREVIEW; + break; + } + case VCAM_CAMERA_PORT_VIDEO_OUT_VIDEO: + { + portInd = VCAM_PORT_VIDEO; + break; + } + default: + { + portInd = VCAM_PORT_MAX; + break; + } + } + + if( portInd > VCAM_PORT_ALL && portInd < VCAM_PORT_MAX && mCurGreContext.mCameraPortParams[portInd].mIsActive ) + { + // find the frame descriptor corresponding to received buffer + for( int i = 0; i < mCurGreContext.mCameraPortParams[portInd].mNumBufs; i++ ) + { + if( mFrameDescriptors[portInd][i]->mFrameBuff == pBuffHeader->pAppPrivate ) + { + cFrame = mFrameDescriptors[portInd][i]; + break; + } + } + } + + if( cFrame ) + { + cFrame->mFrameSource = portInd; + cFrame->mLength = pBuffHeader->nFilledLen; + cFrame->mTimestamp = pBuffHeader->nTimeStamp; + cFrame->mWidth = mCurGreContext.mCameraPortParams[portInd].mWidth; + cFrame->mHeight = mCurGreContext.mCameraPortParams[portInd].mHeight; + cFrame->mOffsetY = pBuffHeader->nOffset/mBuffersInUse[portInd].mBuffers[0].y_stride; + cFrame->mOffsetX = pBuffHeader->nOffset%mBuffersInUse[portInd].mBuffers[0].y_stride; + cFrame->mCookie = m_cookie; + cFrame->mContext = this; + + DVP_Image_t *pImage = (DVP_Image_t *)cFrame->mFrameBuff; + pImage->x_start = cFrame->mOffsetX/pImage->x_stride; + pImage->y_start = cFrame->mOffsetY; + + OMX_TI_PLATFORMPRIVATE *platformPrivate = (OMX_TI_PLATFORMPRIVATE *)(pBuffHeader->pPlatformPrivate); + + if( platformPrivate && platformPrivate->pMetaDataBuffer && platformPrivate->nMetaDataSize > 0) + { + OMX_OTHER_EXTRADATATYPE *pExtraData = (OMX_OTHER_EXTRADATATYPE *)platformPrivate->pMetaDataBuffer; + if (pExtraData->eType >= OMX_ExtraDataVendorStartUnused && pExtraData->eType < OMX_ExtraDataMax) + { + DVP_PRINT(DVP_ZONE_CAM, "METADATA: Extra Data Type is TI Specific!\n"); + cFrame->mExtraDataBuf = pExtraData; + cFrame->mExtraDataLength = platformPrivate->nMetaDataSize; // use this to calculate a size limit + + if( mFaceDetectionEnabled & VCAM_FACE_DETECTION_ALL ) + { + getFacesCoordinates( cFrame ); + } + + getMetadataPtrs( cFrame ); + } + else + { + if (pExtraData->eType != OMX_ExtraDataNone) + { + DVP_PRINT(DVP_ZONE_WARNING, "METADATA: Unsupported extra data type from camera (0x%x)\n", pExtraData->eType); + } + platformPrivate = NULL; + } + } + else + { + platformPrivate = NULL; + } + + if (platformPrivate == NULL) + { + cFrame->mMetadata.mAutoWBGains = NULL; + cFrame->mMetadata.mManualWBGains = NULL; + cFrame->mMetadata.mAncillary = NULL; + cFrame->mMetadata.mHistogram2D = NULL; + cFrame->mMetadata.mHistogramL = NULL; + cFrame->mMetadata.mHistogramR = NULL; + cFrame->mMetadata.mGamma2D = NULL; + cFrame->mMetadata.mGammaL = NULL; + cFrame->mMetadata.mGammaR = NULL; + cFrame->mExtraDataBuf = NULL; + cFrame->mExtraDataLength = 0; + cFrame->mDetectedFacesNum = 0; + memset( cFrame->mFaces, 0, MAX_FACES_COUNT * sizeof(VisionCamFaceType) ); + cFrame->mDetectedFacesNumRaw = 0; + memset( cFrame->mFacesRaw, 0, MAX_FACES_COUNT * sizeof(VisionCamFaceType) ); + } + + if( VCAM_PORT_PREVIEW == cFrame->mFrameSource ) + { + m_frameNum++; + } + + if( mUseFramePackaging ) + { + DVP_PRINT(DVP_ZONE_CAM, "Inside the Frame Packing case...\n" ); + if( m_pack_callback != NULL ) + { + DVP_PRINT(DVP_ZONE_CAM, "Non null frame pack callback available...\n" ); + if( mFramePackage.mExpectedFrames[cFrame->mFrameSource] ) + { + if( mFramePackage.mIsEmpty ) + { + mFramePackage.mIsEmpty = false_e; + mFramePackage.mTimestamp = cFrame->mTimestamp; + } + + if( mFramePackage.mTimestamp == cFrame->mTimestamp ) + {/// @todo check if a frame from this port and with this time stamp has already arrived. This would mean a dicati issue + mFramePackage.mFrame[cFrame->mFrameSource] = cFrame; + } + else + { + /// @todo add to queue + DVP_PRINT(DVP_ZONE_CAM, "Loosing a frame here port:%d...\n", cFrame->mFrameSource); + } + } + + bool_e ready = true_e; + for(int32_t i = (VCAM_PORT_ALL + 1); i < VCAM_PORT_MAX; i++) + { + if( !mFramePackage.mFrame[i] && mFramePackage.mExpectedFrames[i] ) + { + ready = false_e; + break; + } + } + DVP_PRINT(DVP_ZONE_CAM, "Waiting to get ready with all frames...\n" ); + if(ready) + { + DVP_PRINT(DVP_ZONE_CAM, "Ready, calling pack callback...\n" ); + m_pack_callback(&mFramePackage); + for(int32_t i = (VCAM_PORT_ALL + 1); i < VCAM_PORT_MAX; i++) + { + mFramePackage.mFrame[i] = NULL; + } + mFramePackage.mIsEmpty = true_e; + } + } + } + else + { + if (m_callback != NULL) + { + m_callback(cFrame); + } + } + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: a frame buffer is received, but there is no matching buffer.\n" ); + } +} +#if GET_SENSOR_CAPS +void OMXVisionCam::getSensorCaps(VCamSensorInfo& s ) +{ + OMX_ERRORTYPE omxError = OMX_ErrorUndefined; + OMX_TI_CAPTYPE *caps = NULL; + OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer; + DataBuffer_t *pBuffer = new DataBuffer_t(sizeof(OMX_TI_CAPTYPE)); + + OMX_STRUCT_INIT(sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER, mLocalVersion); + sharedBuffer.nPortIndex = mCurGreContext.mPortsInUse[VCAM_PORT_ALL]; + sharedBuffer.nSharedBuffSize = pBuffer->getSize(); + sharedBuffer.pSharedBuff = (OMX_U8*)pBuffer->getData(); + + OMX_STRUCT_INIT_PTR(caps, OMX_TI_CAPTYPE, mLocalVersion); + caps = (OMX_TI_CAPTYPE*)pBuffer->getData(); + + // Get capabilities from OMX Camera + omxError = OMX_GetConfig(mCurGreContext.mHandleComp, (OMX_INDEXTYPE) OMX_TI_IndexConfigCamCapabilities, &sharedBuffer); + if ( OMX_ErrorNone == omxError ) + { +// s.supportedModesCnt = caps-> + } +} +#endif // GET_SENSOR_CAPS + +#if TIME_PROFILE +void OMXVisionCam::PopulateTimeProfiler() +{ + mTimeProfiler[ first ] = new VisionCamTimePtofile("first"); + mTimeProfiler[ second ] = new VisionCamTimePtofile(); + mTimeProfiler[ last ] = new VisionCamTimePtofile(); +} + +VisionCamTimePtofile::VisionCamTimePtofile( const char * name ){ + memset( &mStart, 0, sizeof(struct timeval) ); + memset( &mEnd, 0, sizeof(struct timeval) ); + + if( name ) + mName = name; + else + mName = "unknown"; +}; + +VisionCamTimePtofile::~VisionCamTimePtofile(){ + dump(); +}; + +void VisionCamTimePtofile::dump() { + if( mEnd.tv_usec && mStart.tv_usec ) + { + double time = (double)(mEnd.tv_usec = mStart.tv_usec) / (double)1000; + printf("TIME: %s - %g [ms]\n\r", mName, time ); + memset( &mStart, 0, sizeof(struct timeval) ); + memset( &mEnd, 0, sizeof(struct timeval) ); + } +} + +#endif // TIME_PROFILE diff --git a/source/dvp/VisionCam/OMXVisionCam.h b/source/dvp/VisionCam/OMXVisionCam.h new file mode 100644 index 0000000..ce4ecad --- /dev/null +++ b/source/dvp/VisionCam/OMXVisionCam.h @@ -0,0 +1,964 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _OMX_VISIONCAM_H_ +#define _OMX_VISIONCAM_H_ + +#if defined(WIN32) || defined(UNDER_CE) + #include +#else + #include + #include + #include + #include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(EXPORTED_3A) +#include +#endif + +#include "VisionCamUtils.h" + +/** Enables some manual camera contols, like manual white balance color gains and gamma table coeficients. */ +#if defined(ANDROID) && !defined(JELLYBEAN) +#define OMX_CAMERA_SUPPORTS_MANUAL_CONTROLS +#define OMX_CAMERA_SUPPORTS_GESTURES +#if !defined(TUNA) && !defined(MAGURO) && !defined(BLAZE_TABLET) && !defined(BLAZE) +#define OMX_CAMERA_SUPPORTS_MTIS +#define OMX_CAMERA_SUPPORTS_TI_MTIS +#define OMX_CAMERA_SUPPORTS_HMSGAMMA +#endif +#define OMX_CAMERA_SUPPORTS_HISTOGRAM +#endif +#ifndef __QNX__ +#define OMX_CAMERA_SUPPORTS_WHITEBALANCE_OVERWRITE +#endif +#if defined(BLAZE) || defined(BLAZE_TABLET) +#define OMX_CAMERA_SUPPORTS_STEREO_GESTURES +#undef OMX_CAMERA_SUPPORTS_SIMULTANEOUS_SENSOR_GESTURES +//#define OMX_CAMERA_SUPPORTS_HMSGAMMA +#endif +#if !defined(AOSP) && !defined(CPCAM) && !defined(TUNA) && !defined(MAGURO) +#undef OMX_CAMERA_SUPPORTS_FD_RAW +#undef OMX_CAMERA_SUPPORTS_IMAGE_PYRAMID +#endif +#if !defined(AOSP) && !defined(CPCAM) && !defined(JELLYBEAN) && (defined(TUNA) || defined(MAGURO)) +#define OMX_CAMERA_SUPPORTS_CAMERA_VIEW +#endif + +/** Maximum camera output port count, not used. @see VisionCamPort_e */ +const uint32_t USED_PORTS_NUMBER = VCAM_PORT_MAX; + +/** Initial frame width. */ +const uint32_t QVGA_WIDTH = 320; + +/** Initial frame height. */ +const uint32_t QVGA_HEIGHT = 240; + +/** Initial frame rate. */ +const uint32_t INITIAL_FRAMERATE = 30; + +/** Minimum value for manual WB color gain. @see VCAM_PARAM_WB_COLOR_GAINS */ +const uint32_t COLOR_GAIN_MIN = 512; + +/** Maximum value for manual WB color gain. @see VCAM_PARAM_WB_COLOR_GAINS */ +const uint32_t COLOR_GAIN_MAX = 2048; + +/** Maximum white balance delay time. @see VCAM_PARAM_AWB_MIN_DELAY_TIME */ +const uint32_t AWB_Delay_Time_Max = 10000; + +/** Minimum white balance delay time. @see VCAM_PARAM_AWB_MIN_DELAY_TIME */ +const uint32_t AWB_Delay_Time_Min = 0; + +/** Maimum exposure gain delay time. @see VCAM_PARAM_AGC_MIN_DELAY_TIME */ +const uint32_t AE_Delay_Time_Max = 10000; + +/** Minimum exposure gain delay time. @see VCAM_PARAM_AGC_MIN_DELAY_TIME */ +const uint32_t AE_Delay_Time_Min = 0; + +/** Maximum count of face data that could be output bu face detction algotithm. + * In othe words maximum count of face that could be detected. +*/ +const uint32_t VCAM_Max_Gesture_Per_Frame = 35; + +#define ARR_SIZE(arr) ( sizeof(arr)/sizeof(arr[0]) ) + +#if TIME_PROFILE +/** In case ot time profiling this is the start time + * of a certain time measurement target. +*/ +#define TIME_START( time_prof ) {\ + gettimeofday( &time_prof->mStart , NULL);\ +} + +/** In case of time profiling this is the ending time + * of a certain time measurement target. +*/ +#define TIME_END( time_prof ) {\ + gettimeofday( &time_prof->mEnd , NULL);\ +} + +/** @enum TimeProfileTargets + * Defines time profiling targets - the commands for which execution time is measured. + * This is just an indexing of of measured time windows. +*/ +typedef enum _time_profile_targets{ + first, + second, + last, + + VCAM_TIME_TARGET_MAX +}TimeProfileTargets; + +/** @class VisionCamTimeProfile + * Implementation of time profiling. + * Each measured time is an object of this type. + * Measured time is dumped when this object is destroyed. +*/ +class VisionCamTimePtofile{ + public: + /** @fn Constructor + * @param name a string that will be used when measured time of dumped. + */ + VisionCamTimePtofile( const char * name = NULL); + /** @fn Destructor + * Destroys a profiling object and dumps measured time in milliseconds. + */ + ~VisionCamTimePtofile(); + + /** @fn dump() + * Prints the time measured for execution of command corresponding to this object. + * This function, also sets the start and end moment to 0, so it can be used again. + */ + void dump(); + + struct timeval mStart; /** System time at start. */ + struct timeval mEnd; /** System time at end. */ + const char * mName; /** User defined name of the command. Used when results are shown. */ +}; +#endif + +/** @struct OMXVCAM_Msg_t + * Message structure used for event handling for OMX Camera events. +*/ +typedef struct _omxvcam_msg_t { + OMX_EVENTTYPE eEvent; /** Event, defined by OMX IL specification. */ + OMX_U32 nData1; /** A data passed by OMX Camera. */ + OMX_U32 nData2; /** A data passed by OMX Camera. */ + semaphore_t *semaphore; /** Semaphore on which this event will be expected. */ + OMX_HANDLETYPE hComponent; /** OMX Camera component. */ + OMX_U32 timeout; /** Semaphore time out. */ +} OMXVCAM_Msg_t; + +/** @enum FrameEvents_e + * Frame event type. These events are processed by frame processing thread. + * @see FrameThreadFunc() +*/ +typedef enum { + EFrameNone, + EFrameReceived, /** Frame is received from OMX Camera and is ready to be passed to user. */ + EFrameReturned, /** User has released the frame so it can be passed back to camera. */ + + EFrameManagerExit /** No frames are expected, both from user and from camera, so frame managing thread should exit. */ +} FrameEvents_e; + +/** @struct SimpleMsg_t + * A simple message structure used by frame management thread. +*/ +typedef struct _omx_vcam_simple_msg_t{ + FrameEvents_e event; /** The frame event @see FrameEvents_e. */ +// semaphore_t sem; + void *data; /** Frame data. */ +}SimpleMsg_t; + +/** ExtraDataTypeLUT[][] + * A look-up table used to translate VisoinCam extra data type to OMX extra data type. + * For details about OMX defined extra data types, refer to OMX IL specification. + * @see VisionCamExtraDataType_e +*/ +const int ExtraDataTypeLUT[][ 2 ] = +{ + { VCAM_EXTRA_DATA_NONE, OMX_ExtraDataNone }, + // { VCAM_EXIF_ATTRIBUTES , VCAM_ExifAttributes }, + { VCAM_ANCILLARY_DATA , OMX_AncillaryData }, + { VCAM_WHITE_BALANCE , OMX_WhiteBalance }, +#if defined(OMX_CAMERA_SUPPORTS_WHITEBALANCE_OVERWRITE) + { VCAM_MANUAL_WHITE_BALANCE , OMX_TI_WhiteBalanceOverWrite }, +#endif + { VCAM_UNSATURATED_REGIONS , OMX_UnsaturatedRegions }, + { VCAM_FACE_DETECTION , OMX_FaceDetection }, + // { VCAM_BARCODE_DETECTION , OMX_BarcodeDetection }, + // { VCAM_FRONT_OBJECT_DETECTION , OMX_FrontObjectDetection }, + // { VCAM_MOTION_ESTIMATION , OMX_MotionEstimation }, +#if defined(OMX_CAMERA_SUPPORTS_MTIS) + { VCAM_MTIS_TYPE , OMX_MTISType }, +#elif defined(OMX_CAMERA_SUPPORTS_TI_MTIS) + { VCAM_MTIS_TYPE , OMX_TI_MTISType }, +#endif + // { VCAM_DISTANCE_ESTIMATION , OMX_DistanceEstimation }, +#if defined(OMX_CAMERA_SUPPORTS_HISTOGRAM) + { VCAM_HISTOGRAM , OMX_Histogram }, +#endif +#if defined(OMX_CAMERA_SUPPORTS_HMSGAMMA) + { VCAM_HMS_GAMMA , OMX_TI_HMSGamma }, +#endif + { VCAM_FOCUS_REGION , OMX_FocusRegion }, + // { VCAM_EXTRA_DATA_PAN_AND_SCAN , OMX_ExtraDataPanAndScan }, + // { VCAM_RAW_FORMAT , OMX_RawFormat }, +// { VCAM_SENSOR_TYPE , OMX_SensorType }, + // { VCAM_SENSOR_CUSTOM_DATA_LENGTH , OMX_SensorCustomDataLength }, + // { VCAM_SENSOR_CUSTOM_DATA , OMX_SensorCustomData } +#if defined(OMX_CAMERA_SUPPORTS_FD_RAW) + { VCAM_FACE_DETECTION_RAW , OMX_TI_FaceDetectionRaw }, +#endif +#if defined(OMX_CAMERA_SUPPORTS_IMAGE_PYRAMID) + { VCAM_IMAGE_PYRAMID , OMX_TI_ImagePyramid }, +#endif +}; + +/** ColorFormatLUT[][] + * A look-up table, used to translate fourcc_t color formats to OMX defined color formats. + * @note FOURCC_RGB565 and FOURCC_BGR565 are supported only on video output port. + * @see _fourcc +*/ +const int ColorFormatLUT[][ 2 ] = +{ + { FOURCC_UYVY , OMX_COLOR_FormatCbYCrY }, + { FOURCC_NV12 , OMX_COLOR_FormatYUV420SemiPlanar }, + { FOURCC_RGB565 , OMX_COLOR_Format16bitRGB565 }, + { FOURCC_BGR565 , OMX_COLOR_Format16bitBGR565 }, + { OMX_COLOR_FormatMax, OMX_COLOR_FormatMax } +}; + +/** CaptureModeLUT[][] + * A look-up table, used to translate VisionCam operating mode to OMX Camera operating mode. + * @see VisionCamCaptureMode for supported operating modes. +*/ +const int CaptureModeLUT[][ 2 ] = +{ +#if defined(GT_I9100G) + { VCAM_VIDEO_NORMAL , OMX_CaptureVideo }, +#else // all other platforms + { VCAM_VIDEO_NORMAL , OMX_CaptureImageProfileBase }, +#endif +#if defined(GT_I9100G) + { VCAM_VIDEO_HIGH_SPEED , OMX_CaptureImageHighSpeedTemporalBracketing }, +#else // all other platforms + { VCAM_VIDEO_HIGH_SPEED , OMX_CaptureHighSpeedVideo }, +#endif + { VCAM_GESTURE_MODE , OMX_TI_CaptureGestureRecognition }, + { VCAM_STEREO_MODE , OMX_CaptureStereoImageCapture }, +#ifdef OMX_CAMERA_SUPPORTS_STEREO_GESTURES + { VCAM_STEREO_GEST_MODE , OMX_TI_StereoGestureRecognition }, +#endif +#if defined(__QNX__) + { VCAM_VIEWFINDER_MODE , OMX_CaptureVideo }, +#endif +#if defined(OMX_CAMERA_SUPPORTS_SIMULTANEOUS_SENSOR_GESTURES) + { VCAM_GESTURE_DUAL_SENSOR_MODE, OMX_TI_SimultaneousSensorsGesture }, +#endif + { VCAM_CAP_MODE_MAX , OMX_CamOperatingModeMax } +}; + +/** FocusModeLUT[][] + * A look-up table, use to translate focus modes, supported by VisionCam, to OMX defined focus modes. + * @see VisionCamFocusMode for supported focus modes. +*/ +const int FocusModeLUT[][ 2 ] = +{ + { VCAM_FOCUS_CONTROL_ON , OMX_IMAGE_FocusControlOn }, + { VCAM_FOCUS_CONTROL_OFF , OMX_IMAGE_FocusControlOff }, + { VCAM_FOCUS_CONTROL_AUTO , OMX_IMAGE_FocusControlAuto }, + { VCAM_FOCUS_CONTROL_AUTO_LOCK , OMX_IMAGE_FocusControlAutoLock }, +#if !defined(__QNX__) + { VCAM_FOCUS_CONTRO_AUTO_MACRO , OMX_IMAGE_FocusControlAutoMacro }, +#endif + { VCAM_FOCUS_CONTROL_AUTO_INFINITY , OMX_IMAGE_FocusControlAutoInfinity }, +// { VCAM_FOCUS_FACE_PRIORITY_MODE , OMX_IMAGE_FocusFacePriorityMode }, +// { VCAM_FOCUS_REGION_PRIORITY_MODE , OMX_IMAGE_FocusRegionPriorityMode }, + { VCAM_FOCUS_CONTROL_HYPERFOCAL , OMX_IMAGE_FocusControlHyperfocal }, + { VCAM_FOCUS_CONTROL_PORTRAIT , OMX_IMAGE_FocusControlPortrait }, + { VCAM_FOCUS_CONTROL_EXTENDED , OMX_IMAGE_FocusControlExtended }, + { VCAM_FOCUS_CONTROL_CONTINOUS_NORMAL , OMX_IMAGE_FocusControlContinousNormal }, +#if !defined(__QNX__) + { VCAM_FOCUS_CONTROL_CONTINOUS_EXTENDED , OMX_IMAGE_FocusControlContinousExtended }, +#else + { VCAM_FOCUS_CONTROL_CONTINOUS_EXTENDED , OMX_TI_IMAGE_FocusControlContinuousExtended }, +#endif +// { VCAM_FOCUS_FACE_PRIORITY_CONTINOUS_MODE , OMX_IMAGE_FocusFacePriorityContinousMode }, +// { VCAM_FOCUS_REGION_PRIORITY_CONTINOUS_MODE , OMX_IMAGE_FocusRegionPriorityContinousMode }, + { VCAM_FOCUS_CONTROL_MAX , OMX_IMAGE_FocusControlMax } +}; + +/** MirrorTypeLUT[][] + * A look-up table, used to translate VisionCam supported mirroring modes, to OMX mirror modes. + * @see VisionCamMirrorType +*/ +const int MirrorTypeLUT[][ 2 ] = +{ + { VCAM_MIRROR_NONE , OMX_MirrorNone }, + { VCAM_MIRROR_VERTICAL , OMX_MirrorVertical }, + { VCAM_MIRROR_HORIZONTAL , OMX_MirrorHorizontal }, + { VCAM_MIRROR_BOTH , OMX_MirrorBoth }, + { VCAM_MIRROR_MAX , OMX_MirrorMax } +}; + +#if ( defined(DUCATI_1_5) || defined(DUCATI_2_0) ) && defined(OMX_CAMERA_SUPPORTS_GESTURES) +/** GestureTypeLUT[][] + * A look-up table, used to translate VisionCam defined gesture events, to OMX defined gesture events. + * @see VisionCamGestureEvent_e +*/ +const int GestureTypeLUT[][2] = +{ + { VCAM_GESTURE_EVENT_INVALID , OMX_TI_GESTURE_NO_GESTURE }, + { VCAM_GESTURE_EVENT_SWIPE_LEFT , OMX_TI_GESTURE_SWIPE_LEFT }, + { VCAM_GESTURE_EVENT_SWIPE_RIGHT , OMX_TI_GESTURE_SWIPE_RIGHT }, + { VCAM_GESTURE_EVENT_FIST_LEFT , OMX_TI_GESTURE_FIST_LEFT }, + { VCAM_GESTURE_EVENT_FIST_RIGHT , OMX_TI_GESTURE_FIST_RIGHT }, + { VCAM_GESTURE_EVENT_MAX , OMX_TI_GESTURE_MAX } +}; + +/** ObjectTypeLUT[][] + * A look-up table, used to translate VisionCam gesture object type to coresponding OMX gesture object. + * @see VisionCamObjectType +*/ +const int ObjectTypeLUT[][2] = +{ + { VCAM_OBJECT_PALM , OMX_TI_OBJECT_PALM }, + { VCAM_OBJECT_FIST , OMX_TI_OBJECT_FIST }, + { VCAM_OBJECT_FACE , OMX_TI_OBJECT_FACE }, + { VCAM_OBJECT_MAX , OMX_TI_OBJECT_MAX } +}; +#endif + +/** StereoLayoutLUT[][] + * A look-up table, used to translate VisionCam defined stereo layouts to OMX stereo layouts. + * @see VisionCamStereoLayout +*/ +const int StereoLayoutLUT[][2] = +{ + { VCAM_STEREO_LAYOUT_TOPBOTTOM, OMX_TI_StereoFrameLayoutTopBottom }, + { VCAM_STEREO_LAYOUT_LEFTRIGHT, OMX_TI_StereoFrameLayoutLeftRight }, + { VCAM_STEREO_LAYOUT_MAX, OMX_TI_StereoFrameLayoutMax } +}; + +/** OMX index of preview frame output port. */ +const int VCAM_CAMERA_PORT_VIDEO_OUT_PREVIEW = 2; + +/** OMX index of video frame output port. */ +const int VCAM_CAMERA_PORT_VIDEO_OUT_VIDEO = 3; + +/** Needed for priority memagement. Camera Group ID is set DOMX layers. */ +const unsigned int CAMERA_GROUP_ID = 8; + +/** @fn thread_ret_t PreemptionThreadLauncher( void *arg ) + * A thread function that implements preemption mechanism for OMXVisionCam. + * Preemption model used here is defined by OMX standard. + * @param arg The instance of OMXVisionCam that is preempted. +*/ +thread_ret_t PreemptionThreadLauncher( void *arg ); + +/** thread_ret_t FrameThreadFunc(void *arg) + * Thread function that implements frame transmit/receive mechanism between user and OMX camera. + * @param arg Thee instance of OMXVisinCam that this thead serves. +*/ +thread_ret_t FrameThreadFunc(void *arg); + +/** @class OMXVisionCam + * @implements VisionCam + * + * Implements OMX Camera interface. Publicly inherits VisionCam. + * This is the final point before camera specific software inplementaion. +*/ +class OMXVisionCam : public VisionCam +{ +protected: + OMX_HANDLETYPE* mHandle; + +private: // internal data types + + /** @class VCAM_PortParameters + * Keeps all the data needed to control certain camera output port. + */ + class VCAM_PortParameters + { + public: +// OMX_U32 mHostBufaddr[VCAM_NUM_BUFFERS]; /** The address of each buffer assigned to this port. This is only used for tailor buffers. @todo check if last is true (gingerbread, froyo) */ + OMX_BUFFERHEADERTYPE *mBufferHeader[VCAM_NUM_BUFFERS];/** Buffer specific data, generated by OMX camera handle at the time a buffer is registered. */ + OMX_U32 mWidth; /** Image width in pixels of a buffer. @see fourcc_t definitions to check pixel in bytes size for different formats. */ + OMX_U32 mHeight; /** Image height in pixels of a buffer. */ + OMX_U32 mStride; /** Byte distance from one pixel to the next pixel in the y direction. @see DVP_Image_t (DVP_Image_t::y_stride). */ + OMX_U8 mNumBufs; /** Number of buffers assigned to this port. */ + OMX_U32 mBufSize; /** The size of a buffer in bytes. */ + OMX_COLOR_FORMATTYPE mColorFormat; /** The fourcc_t color fomat used to calculate buffer allocation sizes. This must be also the color format applied to OMX camera. */ +// OMX_PARAM_VIDEONOISEFILTERTYPE mVNFMode; /** Video noise filtering mode: on, off or auto. @todo check if used */ +// OMX_PARAM_VIDEOYUVRANGETYPE mYUVRange; /** Frame YUV Range. @todo check if used */ +// OMX_CONFIG_BOOLEANTYPE mVidStabParam; /** Video stabilisation mode: enabled or disabled. @todo check if used and needed at all. */ +// OMX_CONFIG_FRAMESTABTYPE mVidStabConfig; /** Video stabilisation mode: enabled or disabled. @todo check if used and needed at all. */ +// OMX_U32 mCapFrame; /** @todo is it used. */ + OMX_U32 mFrameRate; /** Frame rate. @note Frame rate is applied to all ports. */ + OMX_U32 mRotation; /** Applied rotation. @see VisionCamRotation_e */ + bool_e mIsActive; /** Indicates if this port is currently outputting any data. */ + }; + + /** @class VCAM_ComponentContext + * Holds the current status of OMX camera handle. + */ + class VCAM_ComponentContext + { + public: + OMX_HANDLETYPE mHandleComp; /** The camera handle. */ + OMX_U32 mNumPorts; /** Number of ports that camera could use. */ + /*VisionCamPort_e*/ OMX_U32 mPortsInUse[VCAM_PORT_MAX]; /** Output port indexes, as they are defined in OMX camera. */ + OMX_U32 mExtraDataPortIndex; /** @todo remove me! */ + VCAM_PortParameters mCameraPortParams[VCAM_PORT_MAX]; /** The parameters for each port. */ + }; + + /** @struct BuffersInUse_t + * A structure that packs a buffer array and buffer count. + @todo move to port parameters + * @see DVP_Image_t + */ + typedef struct BuffersInUse_t{ + DVP_Image_t *mBuffers; /** The buffer aray. */ + uint32_t mNumberBuffers; /** Number of buffers. */ + }BuffersInUse_t; + + /** @enum ValueTypeOrigin + * Used to parse look-up tables. + * Marks where exactly the value, for which a match is searched, is defined. + */ + typedef enum + { + VCAM_VALUE_TYPE = 0, /** Value is defined in VisionCam and matching OMX value is searched. */ + OMX_VALUE_TYPE = 1 /** Value is defined in OMX and matching VisionCam value is searched. */ + } ValueTypeOrigin ; + + /** @enum VisionCamPreemptionActivity_e + * Used to define component preemption stage. + */ + enum VisionCamPreemptionActivity_e { + VCAM_PREEMPT_INACTIVE, /** No preemption is started. */ + VCAM_PREEMPT_SUSPEND, /** OMX camera was preempted by a process with a higher priority than VisionCam, so VisionCam has to be suspended. */ + VCAM_PREEMPT_RESUME, /** VisionCam is ready to continue its work, after it has been suspended. */ + VCAM_PREEMPT_WAIT_TO_START /** VisionCam is waiting to get the control over camera. */ + }; + + /** @enum VisionCamFaceDetectionType_t + * Enumaration that defines which type of face detection + */ + typedef enum { + VCAM_FACE_DETECTION_DISABLED = 0, + VCAM_FACE_DETECTION_MIN = 1 << 0, + VCAM_FACE_DETECTION_RAW = 1 << 0, /** */ + VCAM_FACE_DETECTION = 1 << 1, /** */ + + VCAM_FACE_DETECTION_MAX, /** */ + VCAM_FACE_DETECTION_ALL = ( ((VCAM_FACE_DETECTION_MAX -1 ) << 1) -1 ) + } VisionCamFaceDetectionType_t; + + /** @typedef status_e(*serviceFunc)(OMXVisionCam *, void *) + * Pointer to a serving function. + * Serving functions are used in the cases where additional setup must be done + * in order for a certain job to be finished by camera. + */ + typedef status_e(*serviceFunc)(OMXVisionCam *, void *); +// Inherited Methods from VisionCam +public: + /** Constructor. */ + OMXVisionCam(); + /** Destructor. */ + ~OMXVisionCam(); + + /** @fn status_e init(void * cookie) + * Initialises OMXVisionCam, gets a camera handle and gives some default values. + */ + status_e init(void * cookie); + + /** @fn status_e deinit() + * Deinits OMXVisionCam, releases the camera and frees all available resources. + */ + status_e deinit(); + + /** @fn status_e useBuffers( DVP_Image_t *prvBufArr, uint32_t numPrvBuf, VisionCamPort_e port) + * Registers and allocates (internal for OMXVisionCam) frame descriptor for each buffer passed. + * This way, buffers are ready to be passed to OMX camera. Implements VisionCam::useBuffers(). + * @param *prvBufArr array of buffers as thay are allocated. + * @param numPrvBuf number of the buffers in this array. + * @param port the port on which these buffers must be assigned to. + */ + status_e useBuffers( DVP_Image_t *prvBufArr, uint32_t numPrvBuf, VisionCamPort_e port); + + /** @fn status_e releaseBuffers( VisionCamPort_e port ) + * Unregisters (internal for OMXVisionCam) all buffers registered with useBuffers() to OMXVisoinCam + * and frees corresponding frame descriptors. Implements VisionCam::releaseBuffers(). + * @param port the port on which these buffers are assigned. + */ + status_e releaseBuffers( VisionCamPort_e port ); + + /** @fn status_e flushBuffers( VisionCamPort_e port ) + * + */ + status_e flushBuffers( VisionCamPort_e port ); + + /** @fn status_e sendCommand( VisionCamCmd_e cmdId, void *param, uint32_t size, VisionCamPort_e port ) + * Requests camera to execute some additional functionality. Implements VisionCam::sendCommand(). + * @param cmdId the command id that bust be executed. + * @param param pointer to additional data that refers to this command. + * @param size size of data pointed by param. + * @param port the port on which this must be executed. + * @return STATUS_SUCCESS on success and any other error code otherwise. + * @see VisionCamCmd_e for possible commands. + * @see VisionCamPort_e for available ports. + */ + status_e sendCommand( VisionCamCmd_e cmdId, void *param, uint32_t size, VisionCamPort_e port ); + + /** @fn status_e setParameter( VisionCamParam_e paramId, void* param, uint32_t size, VisionCamPort_e port) + * Configure the camera with supplied parameter. Implements VisionCam::setParameter(). + * @param paramId ID of the parameter that has to be applied. + * @param param Pointer to parameter data. + * @param size Size of parameter data. + * @param port Output port for which this parameters will be applied. + * @return STATUS_SUCCESS on success and any other error code otherwise. + * @see VisionCamParam_e for possible parameters. + * @see VisionCamPort_e for available ports. + */ + status_e setParameter( VisionCamParam_e paramId, void* param, uint32_t size, VisionCamPort_e port); + + /** @fn status_e getParameter( VisionCamParam_e paramId, void* param, uint32_t size, VisionCamPort_e port) + * Reads camera configuration parameter. Implements VisionCam::getParameter(). + * @param paramId ID of the parameter that has to be read. + * @param param Pointer to user allocated space, where parameter value will be written. + * @param size Size of parameter data. + * @param port Output port for which this parameters are applied. + * @return STATUS_SUCCESS on success and any other error code otherwise. + * @see VisionCamParam_e for possible parameters. + * @see VisionCamPort_e for available ports. + */ + status_e getParameter( VisionCamParam_e paramId, void* param, uint32_t size, VisionCamPort_e port); + + /** @fn status_e returnFrame( VisionCamFrame *cameraFrame ) + * This must be called after VisionCam client has finished his job with a frame buffer. + * With this, user notifies VisionCam that this frame buffer is ready to be returned back to camera. + * @param cameraFrame The pointer to the frame given to the user which is now completed. + */ + status_e returnFrame( VisionCamFrame *cameraFrame ); + +private: + // OMXVisionCam + /** @fn status_e startPreview( VisionCamPort_e port ) + * Signals the camera to start a streaming a frames on a certain output port. + * @param port the port on which this streaming shold be started. + * @return STATUS_SUCCESS on success and any other error code otherwise. + */ + status_e startPreview( VisionCamPort_e port ); + + /** @fn status_e stopPreview( VisionCamPort_e port ) + * Signals the camera to stop a streaming a frames on a certain output port. + * @param port the port on which this streaming shold be stopped. + * @return STATUS_SUCCESS on success and any other error code otherwise. + */ + status_e stopPreview( VisionCamPort_e port ); + + /** @fn inline OMX_STATETYPE getComponentState() + * Gets current state of OMX camera. + */ + +#if defined(EXPORTED_3A) + /** @fn status_e _3A_ApplyExported() + * Invokes the camera hw to apply all the 3A settings that user has requested. + */ + status_e _3A_ApplyExported(); +#endif // EXPORTED_3A + + inline OMX_STATETYPE getComponentState(); + + /** @fn inline OMX_ERRORTYPE initPortCheck( OMX_PARAM_PORTDEFINITIONTYPE * portCheck , OMX_U32 portIndex ) + * Read and initialises current configuration applied to a certain output port. + * The configuratin structure is passed by a pointer so it can be used later for port reconfiguration. + * @param portCheck configuratin structure pointer that will be filled with appropriate data. + * @param portIndex one of VisionCamPort_e port indexes; this is the port which configuration is requested + * @return OMX_ErrorNone on successful read. + */ + inline OMX_ERRORTYPE initPortCheck( OMX_PARAM_PORTDEFINITIONTYPE * portCheck , OMX_U32 portIndex ); + + /** @fn inline status_e ConvertError(OMX_ERRORTYPE error) + * Converts OMX error codes to VisionCam error codes (status_e) + * @param error one of OMX error codes. + * @return status_e value. + * @see status_e + */ + inline status_e ConvertError(OMX_ERRORTYPE error); + + /** @fn inline int getLutValue( int searchVal, ValueTypeOrigin origin, const int lut[][2], int lutSize) + * Parses VisionCam <-> OMX look-up tables. + * @param searchVal The value for which a match is required. + * @param origin Indicates if searchVal is defined by VisionCam or by OMX. + * Depending on that, returned value is respectively OMX or VisionCam defined. + * @param lut[][2] The look-up table to be parsed. + * @param lutSize Number of couples in this table. + * @return The value corresponding to searchVal. + */ + inline int getLutValue( int searchVal, ValueTypeOrigin origin, const int lut[][2], int lutSize); + + + /** @fn void GetDucatiVersion() + * Gets currnet domx version. + */ + void GetDucatiVersion(); + + /** @fn OMX_ERRORTYPE RegisterForEvent(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, + OMX_IN OMX_U32 nData2, + OMX_IN semaphore_t *semaphore, + OMX_IN OMX_U32 timeout) + * Creates an event message and adds it to the list of events that are expected to occur at OMX side. + */ + OMX_ERRORTYPE RegisterForEvent(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, + OMX_IN OMX_U32 nData2, + OMX_IN semaphore_t *semaphore, + OMX_IN OMX_U32 timeout); + + /** @fn static OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, + OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData); + * + * OMX event handler. This is a callback function, registerd in OMX component, by the time of its initialization. + * It is invoked every time an event is generated by camera. + * The events handled are not only internal camera events, + * but also a results ot some external processes that deal with camera. + */ + static OMX_ERRORTYPE EventHandler(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, + OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData); + + /** @fn static OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); + * A callback notifing that OMX camera has unregistered a buffer and has freed its buffer header. + */ + static OMX_ERRORTYPE EmptyBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); + + /** @fn static OMX_ERRORTYPE FillBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffHeader); + * + * A callback notifing that OMX camera has wrote a frame buffer and it is ready to be passed to user. + */ + static OMX_ERRORTYPE FillBufferDone(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffHeader); + +// /** status_e frameReceiveService(OMX_IN OMX_BUFFERHEADERTYPE* pBuffHeader) +// * +// */ +// status_e frameReceiveService(OMX_IN OMX_BUFFERHEADERTYPE* pBuffHeader); + + /** @fn OMX_ERRORTYPE setPortDef( int portIndex ) + * Configures a port. Sets the data that port needs to get ready for image processing. + * @param portIndex VisionCam defined index of the port. + * @see VisionCamPort_e + * @return OMX_ErrorNone on success. + */ + OMX_ERRORTYPE setPortDef( int32_t portIndex/*, VCAM_PortParameters * portData*/); + + /** @fn status_e startAutoFocus( VisionCamFocusMode focusMode ) + * Starts auto focus in a certain mode. Starts a thread that will wait for focus event. + * @param focusMode mode in which auto focus must start. + * @see VisionCamFocusMode + * @return STATUS_SUCCESS on success and any other error code otherwise. + */ + status_e startAutoFocus( VisionCamFocusMode focusMode ); + + /** @fn status_e enableFaceDetect(VisionCamPort_e port) + * This will configure the component to start/stop face detection. + * Will also start/stop face detection extra data + * faces coordinates will be written into camera frame received in preview callback. + * @see VisionCamFaceType + * @see VisionCamFrame::mFaces + * @return STATUS_SUCCESS on success and any other error code otherwise. + */ + status_e enableFaceDetect(VisionCamPort_e port, VisionCamFaceDetectionType_t fdType ); + + /** @fn void getFacesCoordinates( VisionCamFrame *frame) + * Fill the face coordinates field in camera frame, + * which will be received by OMXVisionCam client at each frame. + * @param frame a frame descripror. + */ + void getFacesCoordinates( VisionCamFrame *frame); + + /** @fn void getMetadataPtrs( VisionCamFrame *frame) + * Parse through the extra data type structure to find the pointer to the relevent + * data type. This is to abstract the port number, version, and packet structure from the client. + * @param frame pointer to a frame descripror. + */ + void getMetadataPtrs( VisionCamFrame *frame); + + /** @fn OMX_ERRORTYPE getFocusStatus(OMX_FOCUSSTATUSTYPE *status) + * Gest current status of focus command execution. + * @param *status points to the variable, where focus status will be written. + * @return OMX_ErrorNone on success. + */ + OMX_ERRORTYPE getFocusStatus(OMX_FOCUSSTATUSTYPE *status); + + /** @fn status_e transitToState(OMX_STATETYPE targetState, serviceFunc transitionService = NULL, void * data = NULL) + * Sets OMX camera in a certain state. Camera state represent camera behaviour and configuration status. + * @param targetState the state that must be reached. Refer to OMX_STATETYPE in OMX IL specification. + * @param transitionService in some cases, OMXVisionCam must do additional steps in order for camera to reach requested state. + * transitionService must point to the function that does this steps. + * @param data any data (like buffers for example), that may be needed for this transition to finish. + * @return STATUS_SUCCESS on success and any other error code otherwise. + * @see serviceFunc + */ + status_e transitToState(OMX_STATETYPE targetState, serviceFunc transitionService = NULL, void * data = NULL); + + /** @fn status_e portEnableDisable( OMX_COMMANDTYPE enCmd, serviceFunc enablementService, VisionCamPort_e port ) + * Enables and disables a port. Enabled port transfers frames only if camera is in OMX_StateExecuting. + * @param enCmd shows whether to enable the port or to disable it. + * @param enablementService pointer to a function that will do the additinal steps that may be needed for this port to execute this enablement command. + * @param port Index of the port that has to be enabled/disabled. + * @return STATUS_SUCCESS on success and any other error code otherwise. + */ + status_e portEnableDisable( OMX_COMMANDTYPE enCmd, serviceFunc enablementService, VisionCamPort_e port ); + + /** @fn status_e PreemptionService() + * Handle preemption events. Takes care of all the steps needed in order preempt camera without bothering its normal work. + * @return STATUS_SUCCESS on success and any other error code otherwise. + */ + status_e PreemptionService(); + + /** @fn friend thread_ret_t PreemptionThreadLauncher( void *arg ) + * Started by OMXVisionCam::EventHandler(), this thread function, call preemption service. + */ + friend thread_ret_t PreemptionThreadLauncher( void *arg ); + + /** @fn status_e populatePort( VisionCamPort_e port ) + * Registers all buffers, that user has passed to OMXVisionCam, to OMX camera. + * @param port specifies tha port on which these buffers must be supplied. + * @return STATUS_SUCCESS on success and any other error code otherwise. + */ + status_e populatePort( VisionCamPort_e port ); + + /** @fn static inline status_e populatePortSrvc( OMXVisionCam *inst, void *in ) + * Function that may be called during camera state transitions or port eneblement. + * @return STATUS_SUCCESS on success and any other error code otherwise. + */ + static inline status_e populatePortSrvc( OMXVisionCam *inst, void *in ) + { + VisionCamPort_e whichPort = *(VisionCamPort_e*)in; + return inst->populatePort( whichPort ); + } + + /** @fn status_e fillPortBuffers( VisionCamPort_e port ) + * Requests the camera to start wrtiting into buffers suppiled on a port. + * This is needed in some state transitions and sometimes during port enable command, depending on camera state. + * Basically this is needed when preview is started. + * @param port the port on which buffers are supplied. + * @return STATUS_SUCCESS on success and any other error code otherwise. + */ + status_e fillPortBuffers( VisionCamPort_e port ); + + /** @fn static inline status_e populatePortSrvc( OMXVisionCam *inst, void *in ) + * Function that may be called during camera state transitions or port eneblement. + * @return STATUS_SUCCESS on success and any other error code otherwise. + */ + static inline status_e fillPortBuffersSrvc( OMXVisionCam *inst, void *in ) + { + VisionCamPort_e whichPort = *(VisionCamPort_e*)in; + return inst->fillPortBuffers( whichPort ); + } + + /** @fn status_e freePortBuffers( VisionCamPort_e port ) + * Request the camera to unregister all buffers supplied to a port. + * Internally, the camera will free its buffer headers. + * Basically this is done by the time preview is stopped. + * @param port the port for which buffers must be released. + * @return STATUS_SUCCESS on success and any other error code otherwise. + */ + status_e freePortBuffers( VisionCamPort_e port ); + + /** @fn static inline status_e freePortBuffersSrvc( OMXVisionCam *inst, void *in ) + * Function that may be called during camera state transitions or port eneblement. + * @return STATUS_SUCCESS on success and any other error code otherwise. + */ + static inline status_e freePortBuffersSrvc( OMXVisionCam *inst, void *in ) + { + VisionCamPort_e whichPort = *((VisionCamPort_e*)in); + return inst->freePortBuffers( whichPort ); + } + + status_e setColorSpace(void *param, size_t size, VisionCamPort_e port); + status_e setBrightness(void *param, size_t size, VisionCamPort_e port); + status_e setContrast(void *param, size_t size, VisionCamPort_e port); + status_e setSharpness(void *param, size_t size, VisionCamPort_e port); + status_e setSaturation(void *param, size_t size, VisionCamPort_e port); + status_e setFrameRate_Fixed(void *param, size_t size, VisionCamPort_e port); + status_e setFrameRate_Variable(void *param, size_t size, VisionCamPort_e port); + status_e setFlicker(void *param, size_t size, VisionCamPort_e port); + status_e setCrop(void *param, size_t size, VisionCamPort_e port); + status_e setStereoInfo(void *param, size_t size, VisionCamPort_e port); + status_e setCameraOperatingMode(void *param, size_t size, VisionCamPort_e port ); + status_e setSensor(void *param, size_t size, VisionCamPort_e port); + status_e setExposureCompensation(void * param, size_t size, VisionCamPort_e port ); + status_e setResolution (void *param, size_t size, VisionCamPort_e port); + status_e setManualExporureTime(void *param, size_t size, VisionCamPort_e port); + status_e setISO(void *param, size_t size, VisionCamPort_e port); + status_e setWhiteBalanceMode(void *param, size_t size, VisionCamPort_e port); + status_e setColorTemp(void *param, size_t size, VisionCamPort_e port); + status_e setMirror(void *param, size_t size, VisionCamPort_e port); + status_e setImagePyramid(void *param, size_t size, VisionCamPort_e port); + status_e getImagePyramid(void *param, size_t size, VisionCamPort_e port); + +#if ( defined(DUCATI_1_5) || defined(DUCATI_2_0) ) && defined(OMX_CAMERA_SUPPORTS_MANUAL_CONTROLS) + status_e setAWBminDelayTime(void *param, size_t size, VisionCamPort_e port); + status_e setGestureInfo(void *param, size_t size, VisionCamPort_e port); + status_e setAGC_MinimumDelay(void *param, size_t size, VisionCamPort_e port); + status_e setAGC_LowThreshold(void *param, size_t size, VisionCamPort_e port); + status_e setAGC_HighThreshold(void *param, size_t size, VisionCamPort_e port); +#endif // ((DUCATI_1_5) || defined(DUCATI_2_0) ) && (OMX_CAMERA_SUPPORTS_MANUAL_CONTROLS) + +public: + /** @fn status_e waitForFocus() + * Waits for focus reached event. + * @return STATUS_SUCCESS on success and any other error code otherwise. + */ + status_e waitForFocus(); + + /** @fn void frameReceivedSrvc(void *data) + * Called inside frame thread, when a frame arrives, + * this function pareses the frame data and sends it to user via preview callback. + * @note In cases when a frame packing option is enabled and more then one output ports are running, + * then the frames from different ports are put into a packet and are sent to user only when all the ports have sent a frame. + * @see thread_t mFrameThread + * @see queue_t *mFrameMessageQ + */ + void frameReceivedSrvc(void *data); + + /** @var thread_t mFrameThread + * The thread that waits for frame event. + * This thead is responsible for packing a frames, if needed, and sending them to VisionCam client. + * + * @see void frameReceivedSrvc(void *data) + * @see queue_t *mFrameMessageQ + */ + thread_t mFrameThread; + + /** @var queue_t *mFrameMessageQ + * + */ + queue_t *mFrameMessageQ; +// SimpleMsg_t mFrameMessage; + semaphore_t mFrameSem; +private: + bool_e mFlushInProcess; + VisionCamPreemptionActivity_e mPreemptionState; + + OMX_PRIORITYMGMTTYPE mVisionCamPriority; + VisionCamFrame ** mFrameDescriptors[VCAM_PORT_MAX]; + VCAM_ComponentContext mCurGreContext; + OMX_VERSIONTYPE *mLocalVersion; + OMX_CALLBACKTYPE mGreCallbacks; + + BuffersInUse_t mBuffersInUse[VCAM_PORT_MAX]; + + mutex_t mFrameBufferLock; + mutex_t mUserRequestLock; + + semaphore_t mGreLocalSem; + semaphore_t mGreFocusSem; + semaphore_t mFrameReceivedSem; + + list_t *mEventSignalQ; + + uint32_t mManualFocusDistance; + + int32_t mFaceDetectionEnabled; + bool_e mReturnToExecuting; + + VisionCamClientNotifier mClientNotifier; + + VisionCamFramePack mFramePackage; + bool_e mUseFramePackaging; + +#if defined(EXPORTED_3A) + VisionCam_3A_Export m3A_Export; +#endif + /** @var mSensorsAvailable[VCAM_Max_Supported_Sensor_Count] + * Stores the indexes of all supported sensors attached to the device. + */ + VCamSensorAvailable mDetectedSensors; + int32_t getAvailableSensors( VCamSensorAvailable& s ); + +#define sen_dump +#ifdef sen_dump + void dumpDetectedSensors(); +#endif //sen_dump + +#define GET_SENSOR_CAPS 0 +#if GET_SENSOR_CAPS + void getSensorCaps(VCamSensorInfo& s ); +#endif // GET_SENSOR_CAPS + void (OMXVisionCam::*pFrameReceivedSrvc)(void *); + + enum { + ePending_Min, + ePending_Focus = ePending_Min, + ePending_Max + }; + VisionCamExecutionService *mPendingConfigs; + + void FirstFrameFunc(void * data); + + void FrameReceivedFunc(void * data); + +#ifndef EXPORTED_3A +#ifdef _USE_GAMMA_RESET_HC_ + bool_e mGammaResetPolulated; +#endif /// _USE_GAMMA_RESET_HC_ +#endif // EXPORTED_3A + +#if TIME_PROFILE + VisionCamTimePtofile * mTimeProfiler[ VCAM_TIME_TARGET_MAX ]; + void PopulateTimeProfiler(); +#endif +}; + +#endif diff --git a/source/dvp/VisionCam/OMXVisionCam_3A_Export.cpp b/source/dvp/VisionCam/OMXVisionCam_3A_Export.cpp new file mode 100644 index 0000000..bbff6eb --- /dev/null +++ b/source/dvp/VisionCam/OMXVisionCam_3A_Export.cpp @@ -0,0 +1,1183 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +/// @def HERE - debug print: shows function and line number +#define HERE { printf("\n%s:%d\n", __func__, __LINE__); fflush(stdout); } +//#define return HERE return + +/// We have 4 bytes reserved for sensor ID inside configuration data buffer, for each parameter. +#define PTR_OFFSET_32bit(mem) (sizeof(int32_t)/sizeof(mem[0])) + +#define ALLOC_LIST_NODE(var, omxType) \ + omxType *var = NULL; \ + var = (omxType*)malloc( sizeof(size_t) + sizeof(OMX_TI_3ASKIP_TI_3ASKIPINDEXTYPE) + sizeof(omxType) ); + +/// Constructs the buffer data needed by OMX interface +#define CONSTRUCT_DATA(data, ind, sen, par, omx_type) \ +{ \ + ret = sensorUsed( (int32_t*)((uint32_t)data + sizeof(size_t) ) , sen, ind ); \ + if( STATUS_SUCCESS == ret ) \ + { \ + if( sizeof(par) == sizeof(omx_type) ) \ + { /** */ \ + void *dst = (void*)( (uint32_t)data + sizeof(size_t) + sizeof(ind) ); \ + memcpy( dst, &par, sizeof(omx_type )); \ + } \ + else \ + { \ + DVP_PRINT(DVP_ZONE_ERROR, "VisionCam and OMX structures doesn't match.\n"); \ + ret = STATUS_NO_MAPPING; /** Need to be copied manually */ \ + } \ + } \ +} + + +#define ADD_TO_3A_LIST(list, data, list_size ) { \ + list_size += addToList( list, (void*)data, sizeof(*data) + sizeof(OMX_TI_3ASKIP_TI_3ASKIPINDEXTYPE) ); \ + DVP_PRINT(DVP_ZONE_CAM, "Total size of 3A list data: %d bytes. \n", list_size); \ +} + + +/** Mask allpied to 3a_skip_index, to mark left/tight sensor + * where: + * right_sensor = index | cSensorMask + * left_sensor = index & (~cSensorMask) +*/ +const int32_t VisionCam_3A_Export::cSensorMask = 0x01000000; + +/** +*/ +VisionCam_3A_Export::VisionCam_3A_Export() +{ + nAllocatinSize = 0; + bSettingsHeld = false_e; + d3A_Buffer = NULL; + mutex_init(&mLock); + mSettingList = list_create(); + + execSRVC = new VisionCamExecutionService(this); + + execSRVC->Register( VCAM_3A_Lsc2D , &VisionCam_3A_Export::Set_3A_Lsc2D , sizeof(OMX_TI_3ASKIP_ISIF_2DLSC_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Clamp , &VisionCam_3A_Export::Set_3A_Clamp , sizeof(OMX_TI_3ASKIP_ISIF_CLAMP_CFGTYPE) ); + execSRVC->Register( VCAM_3A_GainOffset , &VisionCam_3A_Export::Set_3A_GainOffset , sizeof(OMX_TI_3ASKIP_ISIF_GAINOFFSET_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Vldc , &VisionCam_3A_Export::Set_3A_Vlcd , sizeof(OMX_TI_3ASKIP_ISIF_VLDC_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Nf1 , &VisionCam_3A_Export::Set_3A_Nf1 , sizeof(OMX_TI_3ASKIP_IPIPE_NOISE_FILTER_CFGTYPE)); + execSRVC->Register( VCAM_3A_Nf2 , &VisionCam_3A_Export::Set_3A_Nf2 , sizeof(OMX_TI_3ASKIP_IPIPE_NOISE_FILTER_CFGTYPE)); + execSRVC->Register( VCAM_3A_GIC , &VisionCam_3A_Export::Set_3A_GIC , sizeof(OMX_TI_3ASKIP_IPIPE_GIC_CFGTYPE) ); + execSRVC->Register( VCAM_3A_WB , &VisionCam_3A_Export::Set_3A_WB , sizeof(OMX_TI_3ASKIP_IPIPE_WB_CFGTYPE) ); + execSRVC->Register( VCAM_3A_CFA , &VisionCam_3A_Export::Set_3A_CFA , sizeof(OMX_TI_3ASKIP_IPIPE_CFA_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Gamma , &VisionCam_3A_Export::Set_3A_Gamma , sizeof(OMX_TI_3ASKIP_IPIPE_GAMMA_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Rgb2Rgb1 , &VisionCam_3A_Export::Set_3A_Rgb2Rgb1 , sizeof(OMX_TI_3ASKIP_IPIPE_RGBRGB_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Rgb2Rgb2 , &VisionCam_3A_Export::Set_3A_Rgb2Rgb2 , sizeof(OMX_TI_3ASKIP_IPIPE_RGBRGB_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Rgb2Yuv , &VisionCam_3A_Export::Set_3A_Rgb2Yuv , sizeof(OMX_TI_3ASKIP_IPIPE_RGBYUV_CFGTYPE) ); + execSRVC->Register( VCAM_3A_GBCE , &VisionCam_3A_Export::Set_3A_GBCE , sizeof(OMX_TI_3ASKIP_IPIPE_GBCE_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Yuv2Yuv , &VisionCam_3A_Export::Set_3A_Yuv2Yuv , sizeof(OMX_TI_3ASKIP_IPIPE_YUV444YUV422_CFGTYPE)); + execSRVC->Register( VCAM_3A_Ee , &VisionCam_3A_Export::Set_3A_Ee , sizeof(OMX_TI_3ASKIP_IPIPE_EE_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Car , &VisionCam_3A_Export::Set_3A_Car , sizeof(OMX_TI_3ASKIP_IPIPE_CAR_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Lsc , &VisionCam_3A_Export::Set_3A_Lsc , sizeof(OMX_TI_3ASKIP_IPIPE_LSC_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Histogram , &VisionCam_3A_Export::Set_3A_Histogram , sizeof(OMX_TI_3ASKIP_IPIPE_HIST_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Boxcar , &VisionCam_3A_Export::Set_3A_Boxcar , sizeof(OMX_TI_3ASKIP_IPIPE_BOXCAR_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Bsc , &VisionCam_3A_Export::Set_3A_Bsc , sizeof(OMX_TI_3ASKIP_IPIPE_BSC_CFGTYPE) ); + execSRVC->Register( VCAM_3A_3Dcc , &VisionCam_3A_Export::Set_3A_3Dcc , sizeof(OMX_TI_3ASKIP_IPIPE_3DCC_CFGTYPE) ); + execSRVC->Register( VCAM_3A_DpcOtf , &VisionCam_3A_Export::Set_3A_DpcOtf , sizeof(OMX_TI_3ASKIP_IPIPE_DPCOTF_CFGTYPE) ); + execSRVC->Register( VCAM_3A_DpcLut , &VisionCam_3A_Export::Set_3A_DpcLut , sizeof(OMX_TI_3ASKIP_IPIPE_DPCLUT_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Cgs , &VisionCam_3A_Export::Set_3A_Cgs , sizeof(OMX_TI_3ASKIP_IPIPE_CGS_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Dfs , &VisionCam_3A_Export::Set_3A_Dfs , sizeof(OMX_TI_3ASKIP_IPIPEIF_DFS_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Dpc1 , &VisionCam_3A_Export::Set_3A_Dpc1 , sizeof(OMX_TI_3ASKIP_IPIPEIF_DPC_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Dpc2 , &VisionCam_3A_Export::Set_3A_Dpc2 , sizeof(OMX_TI_3ASKIP_IPIPEIF_DPC_CFGTYPE) ); + execSRVC->Register( VCAM_3A_Dpcm , &VisionCam_3A_Export::Set_3A_Dpcm , sizeof(VCAM_3ASKIP_IPIPEIF_DPCM_CFGTYPE) ); + execSRVC->Register( VCAM_3A_HLpf , &VisionCam_3A_Export::Set_3A_HLpf , sizeof(OMX_TI_3ASKIP_RSZ_LPF_CFGTYPE) ); + execSRVC->Register( VCAM_3A_VLpf , &VisionCam_3A_Export::Set_3A_VLpf , sizeof(OMX_TI_3ASKIP_RSZ_LPF_CFGTYPE) ); + execSRVC->Register( VCAM_3A_H3aAewbParams , &VisionCam_3A_Export::Set_3A_H3aAewbParams , sizeof(OMX_TI_3ASKIP_H3A_AEWB_PARAMTYPE) ); + execSRVC->Register( VCAM_3A_H3aAfParams , &VisionCam_3A_Export::Set_3A_H3aAfParams , sizeof(OMX_TI_3ASKIP_H3A_AF_PARAMTYPE) ); + execSRVC->Register( VCAM_3A_H3aCommonParams , &VisionCam_3A_Export::Set_3A_H3aCommonParams , sizeof(OMX_TI_3ASKIP_H3A_COMMON_CFGTYPE) ); + execSRVC->Register( VCAM_3A_CamControlExpGain , &VisionCam_3A_Export::Set_3A_CamControlExpGain, sizeof(OMX_TI_3ASKIP_CAM_CONTROL_EXPGAINTYPE) ); +} + +VisionCam_3A_Export::~VisionCam_3A_Export() +{ + nAllocatinSize = 0; + bSettingsHeld = false_e; + mutex_deinit(&mLock); + list_destroy( mSettingList ); + delete execSRVC; +} + +size_t VisionCam_3A_Export::addToList(list_t *list, void *data, size_t size) +{ + node_t *node = (node_t*)calloc(1, sizeof(node_t)); + + ((size_t*)(data))[0] = size; + DVP_PRINT(DVP_ZONE_CAM, "Appending %d bytes to List\n", (((size_t*)(data))[0])); + node->data = (value_t)(data); + + list_append(list, node); + + return size; +} + +status_e VisionCam_3A_Export::sensorUsed( int32_t *data, int32_t sen, OMX_TI_3ASKIP_TI_3ASKIPINDEXTYPE omxIndex ) +{ + status_e ret = STATUS_SUCCESS; + + /// we depend on the requirement that the very first four bytes in any manual 3A configuration, + /// are used to save OMX index of the configuration and the sensor id ( left or right ) + if( OMX_PrimarySensor == (OMX_SENSORSELECT)sen ) + { + data[0] = (int32_t)omxIndex & (~cSensorMask); + } + else if( OMX_SecondarySensor == (OMX_SENSORSELECT)sen ) + { + data[0] = (int32_t)omxIndex | cSensorMask; + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Requested stereo sensors configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::hold_3A() +{ + status_e ret = STATUS_SUCCESS; + + SOSAL::AutoLock lock( &mLock); + + if( bSettingsHeld ) + { + ret = STATUS_INVALID_STATE; + DVP_PRINT(DVP_ZONE_CAM, "Requested Hold on 3A manual settins, but they are already held."); + DVP_PRINT(DVP_ZONE_CAM, "Returning STATUS_INVALID_STATE"); + } + else + { + if( d3A_Buffer ) + { + delete d3A_Buffer; + d3A_Buffer = NULL; + } + + bSettingsHeld = true_e; + } + + return ret; +} + +status_e VisionCam_3A_Export::release_3A() +{ + status_e ret = STATUS_SUCCESS; + + SOSAL::AutoLock lock( &mLock); + + if( bSettingsHeld ) + { + bSettingsHeld = false_e; + + if ( create3Abuffer() ) + { + collect3AbufferData(); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_ERROR, "Couldn't create 3A data buffer.\n"); + } + } + else + { + ret = STATUS_INVALID_STATE; + DVP_PRINT(DVP_ZONE_ERROR, "Requested Unhold on 3A manual settins, but they are not held.\n"); + DVP_PRINT(DVP_ZONE_ERROR, "Returning STATUS_INVALID_STATE\n"); + } + + return ret; +} + +bool_e VisionCam_3A_Export::create3Abuffer() +{ + bool_e ret = false_e; + + if( false_e == bSettingsHeld ) + { + if( d3A_Buffer ) + { + DVP_PRINT(DVP_ZONE_CAM, "Found old 3A Data Buffer.\n Freeing it!\n"); + delete d3A_Buffer; + DVP_PRINT(DVP_ZONE_CAM, "Old 3A Data Buffer freed.\n"); + d3A_Buffer = NULL; + } + + if( nAllocatinSize > 0 ) + { + d3A_Buffer = new DataBuffer_t(nAllocatinSize); + + if( d3A_Buffer && d3A_Buffer->getData() ) + { + DVP_PRINT(DVP_ZONE_CAM, "New 3A Data Buffer allocated with size %d.\n", nAllocatinSize); + nAllocatinSize = 0; + ret = true_e; + } + else + { + if( d3A_Buffer ) + { + DVP_PRINT(DVP_ZONE_CAM, "3A Data Buffer culdn't be allocated.\n"); + delete d3A_Buffer; + } + } + + } + else + { + DVP_PRINT( DVP_ZONE_CAM, "3A data buffer could not be allocated: improper size calculated !!!\n" ); + } + } + else + { + ret = false_e; + } + + return ret; +} + +/// @todo void VisionCam_3A_Export::collect3AbufferData(): Make me non-void !!!!!! +void VisionCam_3A_Export::collect3AbufferData() +{ + node_t *node = NULL; + size_t curSize = 0; + + if( false_e == bSettingsHeld ) + { + node = list_pop( mSettingList ); + + while( node ) + { + curSize += ((size_t*)(node->data))[0]; + DVP_PRINT(DVP_ZONE_CAM, "Copying %d bytes into 3A data buffer.\n",((size_t*)(node->data))[0]); + DVP_PRINT(DVP_ZONE_CAM, "Buffer size is %d \n", nAllocatinSize); + + // d3A_Buffer->push((void*)( (uint32_t)(node->data) + sizeof(size_t) ), ((size_t*)(node->data))[0] ); + d3A_Buffer->push((void*) &( ((size_t*)(node->data))[1]), ((size_t*)(node->data))[0] ); + free( (void*)(node->data) ); + free(node); + node = NULL; + node = list_pop( mSettingList ); + } + + if( curSize != nAllocatinSize ) + { + DVP_PRINT(DVP_ZONE_ERROR, "Copied %d bytes into 3A data buffer; buffer size is %d \n",curSize, nAllocatinSize); + } + } +} + +status_e VisionCam_3A_Export::set( SettingType_e paramType, void* paramValue, size_t size __attribute__ ((unused)) ) +{ + status_e ret = STATUS_SUCCESS; + + SOSAL::AutoLock lock( &mLock); + + if( VCAM_3A_Start <= paramType && paramType < e3A_ManualSetting_MAX ) + { + VisionCamExecutionService::execFuncPrt_t fun = execSRVC->getFunc(paramType); + if( fun ) + { + ret = (this->*(fun))(paramValue); + } + else + { + // This case should never appear. + // If this happens anyway, possibly you have missed to add an execution functin against this param ID. + // Use execSRVC->Register() to add it. + DVP_PRINT(DVP_ZONE_ERROR, "%s : requested parameter with ID %d", __func__, paramType ); + DVP_PRINT(DVP_ZONE_ERROR, "Such parameter doesn't have implemented api. Or is not registered.\n" ); + ret = STATUS_NO_MAPPING; + } + } + else + { + DVP_PRINT(DVP_ZONE_CAM, "3A user export set(): received invalid parameter.\n" ); + DVP_PRINT(DVP_ZONE_CAM, "Requested parameter with index %d ( 0x%x ); possible are between %d ( 0x%x ) and %d ( 0x%x )\n", + paramType, paramType, + VCAM_3A_Start, VCAM_3A_Start, + (e3A_ManualSetting_ALL - 1), (e3A_ManualSetting_ALL - 1) ); + + ret = STATUS_INVALID_PARAMETER; + } + + if ( STATUS_SUCCESS == ret && !bSettingsHeld ) + { + bool_e bufferCreated = create3Abuffer(); + + if( bufferCreated ) + collect3AbufferData(); + } + + if( STATUS_SUCCESS == ret ) + { + DVP_PRINT(DVP_ZONE_CAM, "3A configuration wtritten successfully to queue.\n"); + } + else + { + DVP_PRINT(DVP_ZONE_CAM, "Error Writing 3A configuratin to queue. Returning err code : %d ( 0x%x )", ret, ret ); + } + + return ret; +} + +status_e VisionCam_3A_Export::reset( SettingType_e param ) +{ + status_e ret = STATUS_BASE; + + SOSAL::AutoLock lock( &mLock); + DVP_PRINT(DVP_ZONE_CAM, "%s is not implemented; returning error.\n", __func__); + + int32_t start = ( param == e3A_ManualSetting_ALL ? VCAM_3A_Start : param ); + int32_t end = ( param == e3A_ManualSetting_ALL ? e3A_ManualSetting_ALL : param + 1); + + for( int32_t i = start; i < end ; i++) + { + void* data = calloc(1, execSRVC->getDataSize(i)); + ret = (this->*(execSRVC->getFunc(i)))(data); + + free(data); + if( ret != STATUS_SUCCESS ) + { + /// @todo set some debug prints in case of error, but don't leave the loop !! + } + } + + return ret; +} + +status_e VisionCam_3A_Export::get( SettingType_e sett __attribute__ ((unused)) , void *data __attribute__ ((unused))) +{ + status_e ret = STATUS_NOT_IMPLEMENTED; + + SOSAL::AutoLock lock( &mLock); + DVP_PRINT(DVP_ZONE_CAM, "%s is not implemented; returning error.\n", __func__); + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Lsc2D( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_2D_LscConfig_t *vcamParam = (VisionCam_3A_2D_LscConfig_t*)param; + + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_ISIF_2DLSC_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexL_Lsc2D, vcamParam->eSensor, vcamParam->m2D_LscConfig, OMX_TI_3ASKIP_ISIF_2DLSC_CFGTYPE ); + + if( STATUS_SUCCESS == ret ) + { + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Clamp( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_Clamp_t *vcamParam = (VisionCam_3A_Clamp_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_ISIF_CLAMP_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexL_Clamp, vcamParam->eSensor, vcamParam->mClamp, OMX_TI_3ASKIP_ISIF_CLAMP_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + { + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_GainOffset( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_GainOffset_t *vcamParam = (VisionCam_3A_GainOffset_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_ISIF_GAINOFFSET_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexL_GainOffset, vcamParam->eSensor, vcamParam->mGainOffset, OMX_TI_3ASKIP_ISIF_GAINOFFSET_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + { + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Vlcd( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_VDLC_t *vcamParam = (VisionCam_3A_VDLC_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_ISIF_VLDC_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_Vlcd, vcamParam->eSensor, vcamParam->mVLDC, OMX_TI_3ASKIP_ISIF_VLDC_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + { + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Nf1( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_NoiseFilterConfig_t *vcamParam = (VisionCam_3A_NoiseFilterConfig_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_NOISE_FILTER_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexL_Nf1, vcamParam->eSensor, vcamParam->eNoiseFilterConfig, OMX_TI_3ASKIP_IPIPE_NOISE_FILTER_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + { + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Nf2( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_NoiseFilterConfig_t *vcamParam = (VisionCam_3A_NoiseFilterConfig_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_NOISE_FILTER_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexL_Nf2, vcamParam->eSensor, vcamParam->eNoiseFilterConfig, OMX_TI_3ASKIP_IPIPE_NOISE_FILTER_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + { + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_GIC( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_GIC_Config_t *vcamParam = (VisionCam_3A_GIC_Config_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_GIC_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexL_GIC, vcamParam->eSensor, vcamParam->mGIC_config, OMX_TI_3ASKIP_IPIPE_GIC_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + { + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_WB( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_WB_Config_t *vcamParam = (VisionCam_3A_WB_Config_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_WB_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexL_WB , vcamParam->eSensor, vcamParam->eWB_config, OMX_TI_3ASKIP_IPIPE_WB_CFGTYPE ); + + if( STATUS_SUCCESS == ret ) + { + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_CFA( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_CFA_Config_t *vcamParam = (VisionCam_3A_CFA_Config_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_CFA_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexL_CFA, vcamParam->eSensor, vcamParam->mCFA_config, OMX_TI_3ASKIP_IPIPE_CFA_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + { + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Gamma( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_GammaTableConfig_t *vcamParam = (VisionCam_3A_GammaTableConfig_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_GAMMA_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexL_Gamma, vcamParam->eSensor, vcamParam->mGammaTable, OMX_TI_3ASKIP_IPIPE_GAMMA_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + { + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Rgb2Rgb1( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_RGB2RGB_t *vcamParam = (VisionCam_3A_RGB2RGB_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_RGBRGB_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexL_Rgb2Rgb1, vcamParam->eSensor, vcamParam->mRGB_config, OMX_TI_3ASKIP_IPIPE_RGBRGB_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + { + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Rgb2Rgb2( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_RGB2RGB_t *vcamParam = (VisionCam_3A_RGB2RGB_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_RGBRGB_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexL_Rgb2Rgb2, vcamParam->eSensor, vcamParam->mRGB_config, OMX_TI_3ASKIP_IPIPE_RGBRGB_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + { + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Rgb2Yuv( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_RGB2YUV_t *vcamParam = (VisionCam_3A_RGB2YUV_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_RGBYUV_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexL_Rgb2Yuv, vcamParam->eSensor, vcamParam->mRGB2YUV, OMX_TI_3ASKIP_IPIPE_RGBYUV_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_GBCE( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_GBCE_Config_t *vcamParam = (VisionCam_3A_GBCE_Config_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_GBCE_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexL_GBCE, vcamParam->eSensor, vcamParam->mGBCE_config, OMX_TI_3ASKIP_IPIPE_GBCE_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Yuv2Yuv( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_Yuv444_toYuv422_Config_t *vcamParam = (VisionCam_3A_Yuv444_toYuv422_Config_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_YUV444YUV422_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_Yuv2Yuv, vcamParam->eSensor, vcamParam->mYuvToYuv_config, OMX_TI_3ASKIP_IPIPE_YUV444YUV422_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Ee( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_EdgeEnhancement_config_t *vcamParam = (VisionCam_3A_EdgeEnhancement_config_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_EE_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_Ee, vcamParam->eSensor, vcamParam->eEdgeEnhConfig, OMX_TI_3ASKIP_IPIPE_EE_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Car( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_CAR_config_t *vcamParam = (VisionCam_3A_CAR_config_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_CAR_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_Car, vcamParam->eSensor, vcamParam->mCar, OMX_TI_3ASKIP_IPIPE_CAR_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Lsc( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_LscConfig_t *vcamParam = (VisionCam_3A_LscConfig_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_LSC_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_Lsc, vcamParam->eSensor, vcamParam->mLsc, OMX_TI_3ASKIP_IPIPE_LSC_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Histogram( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_HistogramConfig_t *vcamParam = (VisionCam_3A_HistogramConfig_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_HIST_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_Histogram, vcamParam->eSensor, vcamParam->mHistogramConfig, OMX_TI_3ASKIP_IPIPE_HIST_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Boxcar( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_BoxCarConfig_t *vcamParam = (VisionCam_3A_BoxCarConfig_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_BOXCAR_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_Boxcar, vcamParam->eSensor, vcamParam->eBoxCarConfig, OMX_TI_3ASKIP_IPIPE_BOXCAR_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Bsc( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_BscConfig_t *vcamParam = (VisionCam_3A_BscConfig_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_BSC_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_Bsc, vcamParam->eSensor, vcamParam->mBscConfig, OMX_TI_3ASKIP_IPIPE_BSC_CFGTYPE ); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_3Dcc( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_3DCC_config_t *vcamParam = (VisionCam_3A_3DCC_config_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_3DCC_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_3Dcc, vcamParam->eSensor, vcamParam->m3dccConfig, OMX_TI_3ASKIP_IPIPE_3DCC_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_DpcOtf( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_DpcOtfConfig_t *vcamParam = (VisionCam_3A_DpcOtfConfig_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_DPCOTF_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_DpcOtf, vcamParam->eSensor, vcamParam->mDPC, OMX_TI_3ASKIP_IPIPE_DPCOTF_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_DpcLut( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_DPC_Lut_t *vcamParam = (VisionCam_3A_DPC_Lut_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_DPCLUT_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_DpcLut, vcamParam->eSensor, vcamParam->mDPC_lut, OMX_TI_3ASKIP_IPIPE_DPCLUT_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Cgs( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_CGS_Config_t *vcamParam = (VisionCam_3A_CGS_Config_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPE_CGS_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_Cgs, vcamParam->eSensor, vcamParam->mCgs, OMX_TI_3ASKIP_IPIPE_CGS_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Dfs( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_DfsConfig_t* vcamParam = (VisionCam_3A_DfsConfig_t*)param; + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPEIF_DFS_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_Dfs, vcamParam->eSensor, vcamParam->mDfsConfig, OMX_TI_3ASKIP_IPIPEIF_DFS_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Dpc1( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_DpcConfig_t *vcamParam = (VisionCam_3A_DpcConfig_t*)param; + + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPEIF_DPC_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_Dpc1, vcamParam->eSensor, vcamParam->mDpcConfig, OMX_TI_3ASKIP_IPIPEIF_DPC_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Dpc2( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_DpcConfig_t *vcamParam = (VisionCam_3A_DpcConfig_t*)param; + + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_IPIPEIF_DPC_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_Dpc2, vcamParam->eSensor, vcamParam->mDpcConfig, OMX_TI_3ASKIP_IPIPEIF_DPC_CFGTYPE ); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_Dpcm( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_DPCM_Config_t *vcamParam = (VisionCam_3A_DPCM_Config_t*)param; + + ALLOC_LIST_NODE(data, VCAM_3ASKIP_IPIPEIF_DPCM_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_Dpcm, vcamParam->eSensor, vcamParam->mDPCM, VCAM_3ASKIP_IPIPEIF_DPCM_CFGTYPE ); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_HLpf( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_ResizerLowPassFilter_t *vcamParam = (VisionCam_3A_ResizerLowPassFilter_t *)param; + + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_RSZ_LPF_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_HLpf, vcamParam->eSensor, vcamParam->mRszLpfConfig, OMX_TI_3ASKIP_RSZ_LPF_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_VLpf( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_ResizerLowPassFilter_t *vcamParam = (VisionCam_3A_ResizerLowPassFilter_t *)param; + + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_RSZ_LPF_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexR_VLpf, vcamParam->eSensor, vcamParam->mRszLpfConfig, OMX_TI_3ASKIP_RSZ_LPF_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_H3aAewbParams( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_AEWB_config_t *vcamParam = (VisionCam_3A_AEWB_config_t*)param; + + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_H3A_AEWB_PARAMTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexL_H3aAewbParams, vcamParam->eSensor, vcamParam->mAEWB_config, OMX_TI_3ASKIP_H3A_AEWB_PARAMTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_H3aAfParams( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_H3A_AutoFocusParam_t *vcamParam = (VisionCam_3A_H3A_AutoFocusParam_t *)param; + + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_H3A_AF_PARAMTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexL_H3aAfParams, vcamParam->eSensor, vcamParam->mH3A_AutoFocusParam, OMX_TI_3ASKIP_H3A_AF_PARAMTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_H3aCommonParams( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_H3A_CommonConfig_t *vcamParam = (VisionCam_3A_H3A_CommonConfig_t *)param; + + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_H3A_COMMON_CFGTYPE); + + if( data ) + { + CONSTRUCT_DATA( data, OMX_TI_3aSkipIndexL_H3aCommonParams, vcamParam->eSensor, vcamParam->mH3A_CommonConfig, OMX_TI_3ASKIP_H3A_COMMON_CFGTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} + +status_e VisionCam_3A_Export::Set_3A_CamControlExpGain( void *param ) +{ + status_e ret = STATUS_SUCCESS; + VisionCam_3A_ExpGainControl_t *vcamParam = (VisionCam_3A_ExpGainControl_t *)param; + + ALLOC_LIST_NODE(data, OMX_TI_3ASKIP_CAM_CONTROL_EXPGAINTYPE); + + if( data ) + { + CONSTRUCT_DATA(data, OMX_TI_3aSkipIndexL_CamControlExpGain, vcamParam->eSensor, vcamParam->mExpGainControl, OMX_TI_3ASKIP_CAM_CONTROL_EXPGAINTYPE); + + if( STATUS_SUCCESS == ret ) + ADD_TO_3A_LIST(mSettingList, data, nAllocatinSize); + } + else + { + ret = STATUS_NOT_ENOUGH_MEMORY; + DVP_PRINT(DVP_ZONE_CAM, "Not enough memory to write this configuration."); + } + + return ret; +} diff --git a/source/dvp/VisionCam/OMXVisionCam_3A_Export.h b/source/dvp/VisionCam/OMXVisionCam_3A_Export.h new file mode 100644 index 0000000..a6eb888 --- /dev/null +++ b/source/dvp/VisionCam/OMXVisionCam_3A_Export.h @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _VISION_CAM_3A_MANUAL_H_ +#define _VISION_CAM_3A_MANUAL_H_ + +#include +#include +#include +#include +#include + +/** @fn int nodeCompare(node_t *a, node_t *b) + * used by getExecNode(), this function provides a comparasion method for ... +*/ +int nodeCompare(node_t *a, node_t *b); + +/** @class + * +*/ +class VisionCam_3A_Export { +public: + VisionCam_3A_Export(); + ~VisionCam_3A_Export(); + + /** @fn hold_3A() + * Starts collecting 3A settings. + * Use this option if various 3A setting must be applied. + * Calling this method notifies VisionCam_3A_Export to start collecting 3A data. + * + * @see set() , unhold_3A() + */ + status_e hold_3A(); + + /** @fn release_3A() + * Stops collecting 3A settings. + * Calling this method notifies VisionCam_3A_Export to stop collecting 3A data + * and to prepare the shared memory buffer. + * + * @see release_3A() , set() + */ + status_e release_3A(); + + /** @fn bool_e isHeld() + * Tells the VisionCam_3A_Export usera whether 3A settings are currently held. + * + * @see hold_3A() , unhold_3A() + */ + bool_e isHeld() { return bSettingsHeld; } + + /** @fn set() + * Calls the apropriate seter function. + * + * @see hold_3A() , unhold_3A() + */ + status_e set( SettingType_e, void*, size_t ); + + /** Calls the apropriate getter function. + */ + status_e get( SettingType_e, void* ); /// gets from hardware + + /** @fn status_e reset( SettingType_e param = e3A_ManualSetting_ALL) + * Reset a given 3A configuration. By default, if 3A configuration type is not specified, + * this will reset all 3A configurations. + */ + status_e reset( SettingType_e param = e3A_ManualSetting_ALL); + + /** Keeps 3A parameters in hardware acceptable format. + */ + DataBuffer_t *d3A_Buffer; + +/** + * Inner functions. +*/ +private: + /** @brief Constant, used to mark the proper sensor on which new 3A are going to be applied. + */ + static const int32_t cSensorMask;// = 0x01000000; + + /** Dynamicaly allocated list of configurations to be applied. + * + */ + list_t *mSettingList; + + /** Marks if 3A settings will be sent in a single shot or on by one. + * Raised by hold_3A() and cleared bu unhold_3A(), this flag indicates the state of 3A patameters collecting. + * No settings will be provided to 3A framwork until this flag has been cleared. + */ + bool_e bSettingsHeld; + + /** Keeps the size of all setting requested between hold_3A() and unhold_3A(). + * This size is the actual buffer allocatin size for DataBuffer_t::pData . + */ + size_t nAllocatinSize; + + /** Locks public APIs. + */ + mutex_t mLock; + + /** @fn status_e addToList(list_t *list, void *node, size_t size) + * Adds any new configuration to a list of configuration settings. + * + * @param list_t *list - points to the list, used for internal data storage + * @param void *data - the data to be added + * @param size_t size - as named, this is the size in bytes of 'data' + * + * @see list_t + * @see mSettingList + */ + size_t addToList(list_t *list, void *data, size_t size); + + /** @fn bool_e VisionCam_3A_Export::create3Abuffer() + * Create the 3A data buffer according to the size needed. + * This memory must be mapped so that it could be read/written both by Camera HW and client code. + * + * @return true_e if buffer created successfuly, false_e otherwise. + */ + bool_e create3Abuffer(); + + /** @fn void collect3AbufferData() + * @brief Copies the list of requested settings to a buffer which could be passed to HW specific layers. + */ + void collect3AbufferData(); + + /** @fn inline status_e VisionCam_3A_Export::sensorUsed( int32_t *data, VisionCamSensorSelection sen) + * Checks the sensor for which a configuratin data should be applied. + * This method is mostly written for convenience reasons during port. + */ + inline status_e sensorUsed( int32_t *data, int32_t sen, OMX_TI_3ASKIP_TI_3ASKIPINDEXTYPE omxIndex ); + + /** Each of these functions, adds the requested parameter to settings list. + */ + status_e Set_3A_Lsc2D( void *); + status_e Set_3A_Clamp( void *); + status_e Set_3A_GainOffset( void *); + status_e Set_3A_Vlcd( void *); + status_e Set_3A_Nf1( void *); + status_e Set_3A_Nf2( void *); + status_e Set_3A_GIC( void *); + status_e Set_3A_WB( void *); + status_e Set_3A_CFA( void *); + status_e Set_3A_Gamma( void *); + status_e Set_3A_Rgb2Rgb1( void *); + status_e Set_3A_Rgb2Rgb2( void *); + status_e Set_3A_Rgb2Yuv( void *); + status_e Set_3A_GBCE( void *); + status_e Set_3A_Yuv2Yuv( void *); + status_e Set_3A_Ee( void *); + status_e Set_3A_Car( void *); + status_e Set_3A_Lsc( void *); + status_e Set_3A_Histogram( void *); + status_e Set_3A_Boxcar( void *); + status_e Set_3A_Bsc( void *); + status_e Set_3A_3Dcc( void *); + status_e Set_3A_DpcOtf( void *); + status_e Set_3A_DpcLut( void *); + status_e Set_3A_Cgs( void *); + status_e Set_3A_Dfs( void *); + status_e Set_3A_Dpc1( void *); + status_e Set_3A_Dpc2( void *); + status_e Set_3A_Dpcm( void *); + status_e Set_3A_HLpf( void *); + status_e Set_3A_VLpf( void *); + status_e Set_3A_H3aAewbParams( void *); + status_e Set_3A_H3aAfParams( void *); + status_e Set_3A_H3aCommonParams( void *); + status_e Set_3A_CamControlExpGain( void *); + + VisionCamExecutionService *execSRVC; + +#if 0 + /** + */ + status_e Get_3A_ColorPattern( void *); + status_e Get_3A_MsbPos( void *); + status_e Get_3A_VpDevice( void *); + status_e Get_3A_Lsc2D( void *); + status_e Get_3A_Clamp( void *); + status_e Get_3A_Flash( void *); + status_e Get_3A_GainOffset( void *); + status_e Get_3A_Vlcd( void *); + status_e Get_3A_Nf1( void *); + status_e Get_3A_Nf2( void *); + status_e Get_3A_GIC( void *); + status_e Get_3A_WB( void *); + status_e Get_3A_CFA( void *); + status_e Get_3A_Gamma( void *); + status_e Get_3A_Rgb2Rgb1( void *); + status_e Get_3A_Rgb2Rgb2( void *); + status_e Get_3A_Rgb2Yuv( void *); + status_e Get_3A_GBCE( void *); + status_e Get_3A_Yuv2Yuv( void *); + status_e Get_3A_Ee( void *); + status_e Get_3A_Car( void *); + status_e Get_3A_Lsc( void *); + status_e Get_3A_Histogram( void *); + status_e Get_3A_Boxcar( void *); + status_e Get_3A_Bsc( void *); + status_e Get_3A_3Dcc( void *); + status_e Get_3A_DpcOtf( void *); + status_e Get_3A_DpcLut( void *); + status_e Get_3A_Cgs( void *); + status_e Get_3A_Dfs( void *); + status_e Get_3A_Dpc1( void *); + status_e Get_3A_Dpc2( void *); + status_e Get_3A_Dpcm( void *); + status_e Get_3A_HLpf( void *); + status_e Get_3A_VLpf( void *); + status_e Get_3A_H3aAewbParams( void *); + status_e Get_3A_H3aAfParams( void *); + status_e Get_3A_H3aCommonParams( void *); + status_e Get_3A_CamControlExpGain( void *); +#endif +}; +#endif // _VISION_CAM_3A_MANUAL_H_ diff --git a/source/dvp/VisionCam/OMXVisionCam_Gamma_Tbl.h b/source/dvp/VisionCam/OMXVisionCam_Gamma_Tbl.h new file mode 100644 index 0000000..9a0fdca --- /dev/null +++ b/source/dvp/VisionCam/OMXVisionCam_Gamma_Tbl.h @@ -0,0 +1,852 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _gamma_tables_ +#define _gamma_tables_ + +const uint8_t mGammaTablesBuf[] = { + 0x0E, 0x00, 0x00, 0x00, /// ID -> 4 bytes + + 0x03, /// eGammaTblSize -> 1 byte + 0x00, /// nTbl -> 1 byte + 0x00, /// eBypassB -> 1 byte + 0x00, /// eBypassG -> 1 byte + 0x00, /// eBypassR -> 1 byte + 0x00, 0x00, 0x00, 0x04, /// *pnRedTable + 0x00, 0x00, 0x00, 0x04, /// *pnBlueTable + 0x08, 0x00, 0x00, 0x04, /// *pnGreenTable + + 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02,0x00, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x06, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x02, 0x00, + 0x0e, 0x00, 0x02, 0x00, 0x10, 0x00, 0x02, 0x00, 0x12, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, + 0x16, 0x00, 0x02, 0x00, 0x18, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x02, 0x00, 0x1c, 0x00, 0x02, 0x00, + 0x1e, 0x00, 0x02, 0x00, 0x20, 0x00, 0x02, 0x00, 0x22, 0x00, 0x02, 0x00, 0x24, 0x00, 0x02, 0x00, + 0x26, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x2a, 0x00, 0x02, 0x00, 0x2c, 0x00, 0x02, 0x00, + 0x2e, 0x00, 0x02, 0x00, 0x30, 0x00, 0x02, 0x00, 0x32, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, + 0x36, 0x00, 0x02, 0x00, 0x38, 0x00, 0x02, 0x00, 0x3a, 0x00, 0x02, 0x00, 0x3c, 0x00, 0x02, 0x00, + 0x3e, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x42, 0x00, 0x02, 0x00, 0x44, 0x00, 0x02, 0x00, + 0x46, 0x00, 0x02, 0x00, 0x48, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x02, 0x00, 0x4c, 0x00, 0x02, 0x00, + 0x4e, 0x00, 0x02, 0x00, 0x50, 0x00, 0x02, 0x00, 0x52, 0x00, 0x02, 0x00, 0x54, 0x00, 0x02, 0x00, + 0x56, 0x00, 0x02, 0x00, 0x58, 0x00, 0x02, 0x00, 0x5a, 0x00, 0x02, 0x00, 0x5c, 0x00, 0x02, 0x00, + 0x5e, 0x00, 0x02, 0x00, 0x60, 0x00, 0x02, 0x00, 0x62, 0x00, 0x02, 0x00, 0x64, 0x00, 0x02, 0x00, + 0x66, 0x00, 0x02, 0x00, 0x68, 0x00, 0x02, 0x00, 0x6a, 0x00, 0x02, 0x00, 0x6c, 0x00, 0x02, 0x00, + 0x6e, 0x00, 0x02, 0x00, 0x70, 0x00, 0x02, 0x00, 0x72, 0x00, 0x02, 0x00, 0x74, 0x00, 0x02, 0x00, + 0x76, 0x00, 0x02, 0x00, 0x78, 0x00, 0x02, 0x00, 0x7a, 0x00, 0x02, 0x00, 0x7c, 0x00, 0x02, 0x00, + 0x7e, 0x00, 0x02, 0x00, 0x80, 0x00, 0x02, 0x00, 0x82, 0x00, 0x02, 0x00, 0x84, 0x00, 0x02, 0x00, + 0x86, 0x00, 0x02, 0x00, 0x88, 0x00, 0x02, 0x00, 0x8a, 0x00, 0x02, 0x00, 0x8c, 0x00, 0x02, 0x00, + 0x8e, 0x00, 0x02, 0x00, 0x90, 0x00, 0x02, 0x00, 0x92, 0x00, 0x02, 0x00, 0x94, 0x00, 0x02, 0x00, + 0x96, 0x00, 0x02, 0x00, 0x98, 0x00, 0x02, 0x00, 0x9a, 0x00, 0x02, 0x00, 0x9c, 0x00, 0x02, 0x00, + 0x9e, 0x00, 0x02, 0x00, 0xa0, 0x00, 0x02, 0x00, 0xa2, 0x00, 0x02, 0x00, 0xa4, 0x00, 0x02, 0x00, + 0xa6, 0x00, 0x02, 0x00, 0xa8, 0x00, 0x02, 0x00, 0xaa, 0x00, 0x02, 0x00, 0xac, 0x00, 0x02, 0x00, + 0xae, 0x00, 0x02, 0x00, 0xb0, 0x00, 0x02, 0x00, 0xb2, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x02, 0x00, + 0xb6, 0x00, 0x02, 0x00, 0xb8, 0x00, 0x02, 0x00, 0xba, 0x00, 0x02, 0x00, 0xbc, 0x00, 0x02, 0x00, + 0xbe, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x02, 0x00, 0xc2, 0x00, 0x02, 0x00, 0xc4, 0x00, 0x02, 0x00, + 0xc6, 0x00, 0x02, 0x00, 0xc8, 0x00, 0x02, 0x00, 0xca, 0x00, 0x02, 0x00, 0xcc, 0x00, 0x02, 0x00, + 0xce, 0x00, 0x02, 0x00, 0xd0, 0x00, 0x02, 0x00, 0xd2, 0x00, 0x02, 0x00, 0xd4, 0x00, 0x02, 0x00, + 0xd6, 0x00, 0x02, 0x00, 0xd8, 0x00, 0x02, 0x00, 0xda, 0x00, 0x02, 0x00, 0xdc, 0x00, 0x02, 0x00, + 0xde, 0x00, 0x02, 0x00, 0xe0, 0x00, 0x02, 0x00, 0xe2, 0x00, 0x02, 0x00, 0xe4, 0x00, 0x02, 0x00, + 0xe6, 0x00, 0x02, 0x00, 0xe8, 0x00, 0x02, 0x00, 0xea, 0x00, 0x02, 0x00, 0xec, 0x00, 0x02, 0x00, + 0xee, 0x00, 0x02, 0x00, 0xf0, 0x00, 0x02, 0x00, 0xf2, 0x00, 0x02, 0x00, 0xf4, 0x00, 0x02, 0x00, + + 0xf6, 0x00, 0x02, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xfa, 0x00, 0x02, 0x00, 0xfc, 0x00, 0x02, 0x00, + 0xfe, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x02, 0x01, 0x02, 0x00, 0x04, 0x01, 0x02, 0x00, + 0x06, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x0a, 0x01, 0x02, 0x00, 0x0c, 0x01, 0x02, 0x00, + 0x0e, 0x01, 0x02, 0x00, 0x10, 0x01, 0x02, 0x00, 0x12, 0x01, 0x02, 0x00, 0x14, 0x01, 0x02, 0x00, + 0x16, 0x01, 0x02, 0x00, 0x18, 0x01, 0x02, 0x00, 0x1a, 0x01, 0x02, 0x00, 0x1c, 0x01, 0x02, 0x00, + 0x1e, 0x01, 0x02, 0x00, 0x20, 0x01, 0x02, 0x00, 0x22, 0x01, 0x02, 0x00, 0x24, 0x01, 0x02, 0x00, + 0x26, 0x01, 0x02, 0x00, 0x28, 0x01, 0x02, 0x00, 0x2a, 0x01, 0x02, 0x00, 0x2c, 0x01, 0x02, 0x00, + 0x2e, 0x01, 0x02, 0x00, 0x30, 0x01, 0x02, 0x00, 0x32, 0x01, 0x02, 0x00, 0x34, 0x01, 0x02, 0x00, + 0x36, 0x01, 0x02, 0x00, 0x38, 0x01, 0x02, 0x00, 0x3a, 0x01, 0x02, 0x00, 0x3c, 0x01, 0x02, 0x00, + 0x3e, 0x01, 0x02, 0x00, 0x40, 0x01, 0x02, 0x00, 0x42, 0x01, 0x02, 0x00, 0x44, 0x01, 0x02, 0x00, + 0x46, 0x01, 0x02, 0x00, 0x48, 0x01, 0x02, 0x00, 0x4a, 0x01, 0x02, 0x00, 0x4c, 0x01, 0x02, 0x00, + 0x4e, 0x01, 0x02, 0x00, 0x50, 0x01, 0x02, 0x00, 0x52, 0x01, 0x02, 0x00, 0x54, 0x01, 0x02, 0x00, + 0x56, 0x01, 0x02, 0x00, 0x58, 0x01, 0x02, 0x00, 0x5a, 0x01, 0x02, 0x00, 0x5c, 0x01, 0x02, 0x00, + 0x5e, 0x01, 0x02, 0x00, 0x60, 0x01, 0x02, 0x00, 0x62, 0x01, 0x02, 0x00, 0x64, 0x01, 0x02, 0x00, + 0x66, 0x01, 0x02, 0x00, 0x68, 0x01, 0x02, 0x00, 0x6a, 0x01, 0x02, 0x00, 0x6c, 0x01, 0x02, 0x00, + 0x6e, 0x01, 0x02, 0x00, 0x70, 0x01, 0x02, 0x00, 0x72, 0x01, 0x02, 0x00, 0x74, 0x01, 0x02, 0x00, + 0x76, 0x01, 0x02, 0x00, 0x78, 0x01, 0x02, 0x00, 0x7a, 0x01, 0x02, 0x00, 0x7c, 0x01, 0x02, 0x00, + 0x7e, 0x01, 0x02, 0x00, 0x80, 0x01, 0x02, 0x00, 0x82, 0x01, 0x02, 0x00, 0x84, 0x01, 0x02, 0x00, + 0x86, 0x01, 0x02, 0x00, 0x88, 0x01, 0x02, 0x00, 0x8a, 0x01, 0x02, 0x00, 0x8c, 0x01, 0x02, 0x00, + 0x8e, 0x01, 0x02, 0x00, 0x90, 0x01, 0x02, 0x00, 0x92, 0x01, 0x02, 0x00, 0x94, 0x01, 0x02, 0x00, + 0x96, 0x01, 0x02, 0x00, 0x98, 0x01, 0x02, 0x00, 0x9a, 0x01, 0x02, 0x00, 0x9c, 0x01, 0x02, 0x00, + 0x9e, 0x01, 0x02, 0x00, 0xa0, 0x01, 0x02, 0x00, 0xa2, 0x01, 0x02, 0x00, 0xa4, 0x01, 0x02, 0x00, + 0xa6, 0x01, 0x02, 0x00, 0xa8, 0x01, 0x02, 0x00, 0xaa, 0x01, 0x02, 0x00, 0xac, 0x01, 0x02, 0x00, + 0xae, 0x01, 0x02, 0x00, 0xb0, 0x01, 0x02, 0x00, 0xb2, 0x01, 0x02, 0x00, 0xb4, 0x01, 0x02, 0x00, + 0xb6, 0x01, 0x02, 0x00, 0xb8, 0x01, 0x02, 0x00, 0xba, 0x01, 0x02, 0x00, 0xbc, 0x01, 0x02, 0x00, + 0xbe, 0x01, 0x02, 0x00, 0xc0, 0x01, 0x02, 0x00, 0xc2, 0x01, 0x02, 0x00, 0xc4, 0x01, 0x02, 0x00, + 0xc6, 0x01, 0x02, 0x00, 0xc8, 0x01, 0x02, 0x00, 0xca, 0x01, 0x02, 0x00, 0xcc, 0x01, 0x02, 0x00, + 0xce, 0x01, 0x02, 0x00, 0xd0, 0x01, 0x02, 0x00, 0xd2, 0x01, 0x02, 0x00, 0xd4, 0x01, 0x02, 0x00, + 0xd6, 0x01, 0x02, 0x00, 0xd8, 0x01, 0x02, 0x00, 0xda, 0x01, 0x02, 0x00, 0xdc, 0x01, 0x02, 0x00, + 0xde, 0x01, 0x02, 0x00, 0xe0, 0x01, 0x02, 0x00, 0xe2, 0x01, 0x02, 0x00, 0xe4, 0x01, 0x02, 0x00, + 0xe6, 0x01, 0x02, 0x00, 0xe8, 0x01, 0x02, 0x00, 0xea, 0x01, 0x02, 0x00, 0xec, 0x01, 0x02, 0x00, + 0xee, 0x01, 0x02, 0x00, 0xf0, 0x01, 0x02, 0x00, 0xf2, 0x01, 0x02, 0x00, 0xf4, 0x01, 0x02, 0x00, + + 0xf6, 0x01, 0x02, 0x00, 0xf8, 0x01, 0x02, 0x00, 0xfa, 0x01, 0x02, 0x00, 0xfc, 0x01, 0x02, 0x00, + 0xfe, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x04, 0x02, 0x02, 0x00, + 0x06, 0x02, 0x02, 0x00, 0x08, 0x02, 0x02, 0x00, 0x0a, 0x02, 0x02, 0x00, 0x0c, 0x02, 0x02, 0x00, + 0x0e, 0x02, 0x02, 0x00, 0x10, 0x02, 0x02, 0x00, 0x12, 0x02, 0x02, 0x00, 0x14, 0x02, 0x02, 0x00, + 0x16, 0x02, 0x02, 0x00, 0x18, 0x02, 0x02, 0x00, 0x1a, 0x02, 0x02, 0x00, 0x1c, 0x02, 0x02, 0x00, + 0x1e, 0x02, 0x02, 0x00, 0x20, 0x02, 0x02, 0x00, 0x22, 0x02, 0x02, 0x00, 0x24, 0x02, 0x02, 0x00, + 0x26, 0x02, 0x02, 0x00, 0x28, 0x02, 0x02, 0x00, 0x2a, 0x02, 0x02, 0x00, 0x2c, 0x02, 0x02, 0x00, + 0x2e, 0x02, 0x02, 0x00, 0x30, 0x02, 0x02, 0x00, 0x32, 0x02, 0x02, 0x00, 0x34, 0x02, 0x02, 0x00, + 0x36, 0x02, 0x02, 0x00, 0x38, 0x02, 0x02, 0x00, 0x3a, 0x02, 0x02, 0x00, 0x3c, 0x02, 0x02, 0x00, + 0x3e, 0x02, 0x02, 0x00, 0x40, 0x02, 0x02, 0x00, 0x42, 0x02, 0x02, 0x00, 0x44, 0x02, 0x02, 0x00, + 0x46, 0x02, 0x02, 0x00, 0x48, 0x02, 0x02, 0x00, 0x4a, 0x02, 0x02, 0x00, 0x4c, 0x02, 0x02, 0x00, + 0x4e, 0x02, 0x02, 0x00, 0x50, 0x02, 0x02, 0x00, 0x52, 0x02, 0x02, 0x00, 0x54, 0x02, 0x02, 0x00, + 0x56, 0x02, 0x02, 0x00, 0x58, 0x02, 0x02, 0x00, 0x5a, 0x02, 0x02, 0x00, 0x5c, 0x02, 0x02, 0x00, + 0x5e, 0x02, 0x02, 0x00, 0x60, 0x02, 0x02, 0x00, 0x62, 0x02, 0x02, 0x00, 0x64, 0x02, 0x02, 0x00, + 0x66, 0x02, 0x02, 0x00, 0x68, 0x02, 0x02, 0x00, 0x6a, 0x02, 0x02, 0x00, 0x6c, 0x02, 0x02, 0x00, + 0x6e, 0x02, 0x02, 0x00, 0x70, 0x02, 0x02, 0x00, 0x72, 0x02, 0x02, 0x00, 0x74, 0x02, 0x02, 0x00, + 0x76, 0x02, 0x02, 0x00, 0x78, 0x02, 0x02, 0x00, 0x7a, 0x02, 0x02, 0x00, 0x7c, 0x02, 0x02, 0x00, + 0x7e, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x00, 0x82, 0x02, 0x02, 0x00, 0x84, 0x02, 0x02, 0x00, + 0x86, 0x02, 0x02, 0x00, 0x88, 0x02, 0x02, 0x00, 0x8a, 0x02, 0x02, 0x00, 0x8c, 0x02, 0x02, 0x00, + 0x8e, 0x02, 0x02, 0x00, 0x90, 0x02, 0x02, 0x00, 0x92, 0x02, 0x02, 0x00, 0x94, 0x02, 0x02, 0x00, + 0x96, 0x02, 0x02, 0x00, 0x98, 0x02, 0x02, 0x00, 0x9a, 0x02, 0x02, 0x00, 0x9c, 0x02, 0x02, 0x00, + 0x9e, 0x02, 0x02, 0x00, 0xa0, 0x02, 0x02, 0x00, 0xa2, 0x02, 0x02, 0x00, 0xa4, 0x02, 0x02, 0x00, + 0xa6, 0x02, 0x02, 0x00, 0xa8, 0x02, 0x02, 0x00, 0xaa, 0x02, 0x02, 0x00, 0xac, 0x02, 0x02, 0x00, + 0xae, 0x02, 0x02, 0x00, 0xb0, 0x02, 0x02, 0x00, 0xb2, 0x02, 0x02, 0x00, 0xb4, 0x02, 0x02, 0x00, + 0xb6, 0x02, 0x02, 0x00, 0xb8, 0x02, 0x02, 0x00, 0xba, 0x02, 0x02, 0x00, 0xbc, 0x02, 0x02, 0x00, + 0xbe, 0x02, 0x02, 0x00, 0xc0, 0x02, 0x02, 0x00, 0xc2, 0x02, 0x02, 0x00, 0xc4, 0x02, 0x02, 0x00, + 0xc6, 0x02, 0x02, 0x00, 0xc8, 0x02, 0x02, 0x00, 0xca, 0x02, 0x02, 0x00, 0xcc, 0x02, 0x02, 0x00, + 0xce, 0x02, 0x02, 0x00, 0xd0, 0x02, 0x02, 0x00, 0xd2, 0x02, 0x02, 0x00, 0xd4, 0x02, 0x02, 0x00, + 0xd6, 0x02, 0x02, 0x00, 0xd8, 0x02, 0x02, 0x00, 0xda, 0x02, 0x02, 0x00, 0xdc, 0x02, 0x02, 0x00, + 0xde, 0x02, 0x02, 0x00, 0xe0, 0x02, 0x02, 0x00, 0xe2, 0x02, 0x02, 0x00, 0xe4, 0x02, 0x02, 0x00, + 0xe6, 0x02, 0x02, 0x00, 0xe8, 0x02, 0x02, 0x00, 0xea, 0x02, 0x02, 0x00, 0xec, 0x02, 0x02, 0x00, + 0xee, 0x02, 0x02, 0x00, 0xf0, 0x02, 0x02, 0x00, 0xf2, 0x02, 0x02, 0x00, 0xf4, 0x02, 0x02, 0x00, + + 0xf6, 0x02, 0x02, 0x00, 0xf8, 0x02, 0x02, 0x00, 0xfa, 0x02, 0x02, 0x00, 0xfc, 0x02, 0x02, 0x00, + 0xfe, 0x02, 0x02, 0x00, 0x00, 0x03, 0x02, 0x00, 0x02, 0x03, 0x02, 0x00, 0x04, 0x03, 0x02, 0x00, + 0x06, 0x03, 0x02, 0x00, 0x08, 0x03, 0x02, 0x00, 0x0a, 0x03, 0x02, 0x00, 0x0c, 0x03, 0x02, 0x00, + 0x0e, 0x03, 0x02, 0x00, 0x10, 0x03, 0x02, 0x00, 0x12, 0x03, 0x02, 0x00, 0x14, 0x03, 0x02, 0x00, + 0x16, 0x03, 0x02, 0x00, 0x18, 0x03, 0x02, 0x00, 0x1a, 0x03, 0x02, 0x00, 0x1c, 0x03, 0x02, 0x00, + 0x1e, 0x03, 0x02, 0x00, 0x20, 0x03, 0x02, 0x00, 0x22, 0x03, 0x02, 0x00, 0x24, 0x03, 0x02, 0x00, + 0x26, 0x03, 0x02, 0x00, 0x28, 0x03, 0x02, 0x00, 0x2a, 0x03, 0x02, 0x00, 0x2c, 0x03, 0x02, 0x00, + 0x2e, 0x03, 0x02, 0x00, 0x30, 0x03, 0x02, 0x00, 0x32, 0x03, 0x02, 0x00, 0x34, 0x03, 0x02, 0x00, + 0x36, 0x03, 0x02, 0x00, 0x38, 0x03, 0x02, 0x00, 0x3a, 0x03, 0x02, 0x00, 0x3c, 0x03, 0x02, 0x00, + 0x3e, 0x03, 0x02, 0x00, 0x40, 0x03, 0x02, 0x00, 0x42, 0x03, 0x02, 0x00, 0x44, 0x03, 0x02, 0x00, + 0x46, 0x03, 0x02, 0x00, 0x48, 0x03, 0x02, 0x00, 0x4a, 0x03, 0x02, 0x00, 0x4c, 0x03, 0x02, 0x00, + 0x4e, 0x03, 0x02, 0x00, 0x50, 0x03, 0x02, 0x00, 0x52, 0x03, 0x02, 0x00, 0x54, 0x03, 0x02, 0x00, + 0x56, 0x03, 0x02, 0x00, 0x58, 0x03, 0x02, 0x00, 0x5a, 0x03, 0x02, 0x00, 0x5c, 0x03, 0x02, 0x00, + 0x5e, 0x03, 0x02, 0x00, 0x60, 0x03, 0x02, 0x00, 0x62, 0x03, 0x02, 0x00, 0x64, 0x03, 0x02, 0x00, + 0x66, 0x03, 0x02, 0x00, 0x68, 0x03, 0x02, 0x00, 0x6a, 0x03, 0x02, 0x00, 0x6c, 0x03, 0x02, 0x00, + 0x6e, 0x03, 0x02, 0x00, 0x70, 0x03, 0x02, 0x00, 0x72, 0x03, 0x02, 0x00, 0x74, 0x03, 0x02, 0x00, + 0x76, 0x03, 0x02, 0x00, 0x78, 0x03, 0x02, 0x00, 0x7a, 0x03, 0x02, 0x00, 0x7c, 0x03, 0x02, 0x00, + 0x7e, 0x03, 0x02, 0x00, 0x80, 0x03, 0x02, 0x00, 0x82, 0x03, 0x02, 0x00, 0x84, 0x03, 0x02, 0x00, + 0x86, 0x03, 0x02, 0x00, 0x88, 0x03, 0x02, 0x00, 0x8a, 0x03, 0x02, 0x00, 0x8c, 0x03, 0x02, 0x00, + 0x8e, 0x03, 0x02, 0x00, 0x90, 0x03, 0x02, 0x00, 0x92, 0x03, 0x02, 0x00, 0x94, 0x03, 0x02, 0x00, + 0x96, 0x03, 0x02, 0x00, 0x98, 0x03, 0x02, 0x00, 0x9a, 0x03, 0x02, 0x00, 0x9c, 0x03, 0x02, 0x00, + 0x9e, 0x03, 0x02, 0x00, 0xa0, 0x03, 0x02, 0x00, 0xa2, 0x03, 0x02, 0x00, 0xa4, 0x03, 0x02, 0x00, + 0xa6, 0x03, 0x02, 0x00, 0xa8, 0x03, 0x02, 0x00, 0xaa, 0x03, 0x02, 0x00, 0xac, 0x03, 0x02, 0x00, + 0xae, 0x03, 0x02, 0x00, 0xb0, 0x03, 0x02, 0x00, 0xb2, 0x03, 0x02, 0x00, 0xb4, 0x03, 0x02, 0x00, + 0xb6, 0x03, 0x02, 0x00, 0xb8, 0x03, 0x02, 0x00, 0xba, 0x03, 0x02, 0x00, 0xbc, 0x03, 0x02, 0x00, + 0xbe, 0x03, 0x02, 0x00, 0xc0, 0x03, 0x02, 0x00, 0xc2, 0x03, 0x02, 0x00, 0xc4, 0x03, 0x02, 0x00, + 0xc6, 0x03, 0x02, 0x00, 0xc8, 0x03, 0x02, 0x00, 0xca, 0x03, 0x02, 0x00, 0xcc, 0x03, 0x02, 0x00, + 0xce, 0x03, 0x02, 0x00, 0xd0, 0x03, 0x02, 0x00, 0xd2, 0x03, 0x02, 0x00, 0xd4, 0x03, 0x02, 0x00, + 0xd6, 0x03, 0x02, 0x00, 0xd8, 0x03, 0x02, 0x00, 0xda, 0x03, 0x02, 0x00, 0xdc, 0x03, 0x02, 0x00, + 0xde, 0x03, 0x02, 0x00, 0xe0, 0x03, 0x02, 0x00, 0xe2, 0x03, 0x02, 0x00, 0xe4, 0x03, 0x02, 0x00, + 0xe6, 0x03, 0x02, 0x00, 0xe8, 0x03, 0x02, 0x00, 0xea, 0x03, 0x02, 0x00, 0xec, 0x03, 0x02, 0x00, + 0xee, 0x03, 0x02, 0x00, 0xf0, 0x03, 0x02, 0x00, 0xf2, 0x03, 0x02, 0x00, 0xf4, 0x03, 0x02, 0x00, + + 0xf6, 0x03, 0x02, 0x00, 0xf8, 0x03, 0x02, 0x00, 0xfa, 0x03, 0x02, 0x00, 0xfc, 0x03, 0x02, 0x00, + 0xfe, 0x03, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x06, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x02, 0x00, + 0x0e, 0x00, 0x02, 0x00, 0x10, 0x00, 0x02, 0x00, 0x12, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, + 0x16, 0x00, 0x02, 0x00, 0x18, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x02, 0x00, 0x1c, 0x00, 0x02, 0x00, + 0x1e, 0x00, 0x02, 0x00, 0x20, 0x00, 0x02, 0x00, 0x22, 0x00, 0x02, 0x00, 0x24, 0x00, 0x02, 0x00, + 0x26, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x2a, 0x00, 0x02, 0x00, 0x2c, 0x00, 0x02, 0x00, + 0x2e, 0x00, 0x02, 0x00, 0x30, 0x00, 0x02, 0x00, 0x32, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, + 0x36, 0x00, 0x02, 0x00, 0x38, 0x00, 0x02, 0x00, 0x3a, 0x00, 0x02, 0x00, 0x3c, 0x00, 0x02, 0x00, + 0x3e, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x42, 0x00, 0x02, 0x00, 0x44, 0x00, 0x02, 0x00, + 0x46, 0x00, 0x02, 0x00, 0x48, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x02, 0x00, 0x4c, 0x00, 0x02, 0x00, + 0x4e, 0x00, 0x02, 0x00, 0x50, 0x00, 0x02, 0x00, 0x52, 0x00, 0x02, 0x00, 0x54, 0x00, 0x02, 0x00, + 0x56, 0x00, 0x02, 0x00, 0x58, 0x00, 0x02, 0x00, 0x5a, 0x00, 0x02, 0x00, 0x5c, 0x00, 0x02, 0x00, + 0x5e, 0x00, 0x02, 0x00, 0x60, 0x00, 0x02, 0x00, 0x62, 0x00, 0x02, 0x00, 0x64, 0x00, 0x02, 0x00, + 0x66, 0x00, 0x02, 0x00, 0x68, 0x00, 0x02, 0x00, 0x6a, 0x00, 0x02, 0x00, 0x6c, 0x00, 0x02, 0x00, + 0x6e, 0x00, 0x02, 0x00, 0x70, 0x00, 0x02, 0x00, 0x72, 0x00, 0x02, 0x00, 0x74, 0x00, 0x02, 0x00, + 0x76, 0x00, 0x02, 0x00, 0x78, 0x00, 0x02, 0x00, 0x7a, 0x00, 0x02, 0x00, 0x7c, 0x00, 0x02, 0x00, + 0x7e, 0x00, 0x02, 0x00, 0x80, 0x00, 0x02, 0x00, 0x82, 0x00, 0x02, 0x00, 0x84, 0x00, 0x02, 0x00, + 0x86, 0x00, 0x02, 0x00, 0x88, 0x00, 0x02, 0x00, 0x8a, 0x00, 0x02, 0x00, 0x8c, 0x00, 0x02, 0x00, + 0x8e, 0x00, 0x02, 0x00, 0x90, 0x00, 0x02, 0x00, 0x92, 0x00, 0x02, 0x00, 0x94, 0x00, 0x02, 0x00, + 0x96, 0x00, 0x02, 0x00, 0x98, 0x00, 0x02, 0x00, 0x9a, 0x00, 0x02, 0x00, 0x9c, 0x00, 0x02, 0x00, + 0x9e, 0x00, 0x02, 0x00, 0xa0, 0x00, 0x02, 0x00, 0xa2, 0x00, 0x02, 0x00, 0xa4, 0x00, 0x02, 0x00, + 0xa6, 0x00, 0x02, 0x00, 0xa8, 0x00, 0x02, 0x00, 0xaa, 0x00, 0x02, 0x00, 0xac, 0x00, 0x02, 0x00, + 0xae, 0x00, 0x02, 0x00, 0xb0, 0x00, 0x02, 0x00, 0xb2, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x02, 0x00, + 0xb6, 0x00, 0x02, 0x00, 0xb8, 0x00, 0x02, 0x00, 0xba, 0x00, 0x02, 0x00, 0xbc, 0x00, 0x02, 0x00, + 0xbe, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x02, 0x00, 0xc2, 0x00, 0x02, 0x00, 0xc4, 0x00, 0x02, 0x00, + 0xc6, 0x00, 0x02, 0x00, 0xc8, 0x00, 0x02, 0x00, 0xca, 0x00, 0x02, 0x00, 0xcc, 0x00, 0x02, 0x00, + 0xce, 0x00, 0x02, 0x00, 0xd0, 0x00, 0x02, 0x00, 0xd2, 0x00, 0x02, 0x00, 0xd4, 0x00, 0x02, 0x00, + 0xd6, 0x00, 0x02, 0x00, 0xd8, 0x00, 0x02, 0x00, 0xda, 0x00, 0x02, 0x00, 0xdc, 0x00, 0x02, 0x00, + 0xde, 0x00, 0x02, 0x00, 0xe0, 0x00, 0x02, 0x00, 0xe2, 0x00, 0x02, 0x00, 0xe4, 0x00, 0x02, 0x00, + 0xe6, 0x00, 0x02, 0x00, 0xe8, 0x00, 0x02, 0x00, 0xea, 0x00, 0x02, 0x00, 0xec, 0x00, 0x02, 0x00, + 0xee, 0x00, 0x02, 0x00, 0xf0, 0x00, 0x02, 0x00, 0xf2, 0x00, 0x02, 0x00, 0xf4, 0x00, 0x02, 0x00, + + 0xf6, 0x00, 0x02, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xfa, 0x00, 0x02, 0x00, 0xfc, 0x00, 0x02, 0x00, + 0xfe, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x02, 0x01, 0x02, 0x00, 0x04, 0x01, 0x02, 0x00, + 0x06, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x0a, 0x01, 0x02, 0x00, 0x0c, 0x01, 0x02, 0x00, + 0x0e, 0x01, 0x02, 0x00, 0x10, 0x01, 0x02, 0x00, 0x12, 0x01, 0x02, 0x00, 0x14, 0x01, 0x02, 0x00, + 0x16, 0x01, 0x02, 0x00, 0x18, 0x01, 0x02, 0x00, 0x1a, 0x01, 0x02, 0x00, 0x1c, 0x01, 0x02, 0x00, + 0x1e, 0x01, 0x02, 0x00, 0x20, 0x01, 0x02, 0x00, 0x22, 0x01, 0x02, 0x00, 0x24, 0x01, 0x02, 0x00, + 0x26, 0x01, 0x02, 0x00, 0x28, 0x01, 0x02, 0x00, 0x2a, 0x01, 0x02, 0x00, 0x2c, 0x01, 0x02, 0x00, + 0x2e, 0x01, 0x02, 0x00, 0x30, 0x01, 0x02, 0x00, 0x32, 0x01, 0x02, 0x00, 0x34, 0x01, 0x02, 0x00, + 0x36, 0x01, 0x02, 0x00, 0x38, 0x01, 0x02, 0x00, 0x3a, 0x01, 0x02, 0x00, 0x3c, 0x01, 0x02, 0x00, + 0x3e, 0x01, 0x02, 0x00, 0x40, 0x01, 0x02, 0x00, 0x42, 0x01, 0x02, 0x00, 0x44, 0x01, 0x02, 0x00, + 0x46, 0x01, 0x02, 0x00, 0x48, 0x01, 0x02, 0x00, 0x4a, 0x01, 0x02, 0x00, 0x4c, 0x01, 0x02, 0x00, + 0x4e, 0x01, 0x02, 0x00, 0x50, 0x01, 0x02, 0x00, 0x52, 0x01, 0x02, 0x00, 0x54, 0x01, 0x02, 0x00, + 0x56, 0x01, 0x02, 0x00, 0x58, 0x01, 0x02, 0x00, 0x5a, 0x01, 0x02, 0x00, 0x5c, 0x01, 0x02, 0x00, + 0x5e, 0x01, 0x02, 0x00, 0x60, 0x01, 0x02, 0x00, 0x62, 0x01, 0x02, 0x00, 0x64, 0x01, 0x02, 0x00, + 0x66, 0x01, 0x02, 0x00, 0x68, 0x01, 0x02, 0x00, 0x6a, 0x01, 0x02, 0x00, 0x6c, 0x01, 0x02, 0x00, + 0x6e, 0x01, 0x02, 0x00, 0x70, 0x01, 0x02, 0x00, 0x72, 0x01, 0x02, 0x00, 0x74, 0x01, 0x02, 0x00, + 0x76, 0x01, 0x02, 0x00, 0x78, 0x01, 0x02, 0x00, 0x7a, 0x01, 0x02, 0x00, 0x7c, 0x01, 0x02, 0x00, + 0x7e, 0x01, 0x02, 0x00, 0x80, 0x01, 0x02, 0x00, 0x82, 0x01, 0x02, 0x00, 0x84, 0x01, 0x02, 0x00, + 0x86, 0x01, 0x02, 0x00, 0x88, 0x01, 0x02, 0x00, 0x8a, 0x01, 0x02, 0x00, 0x8c, 0x01, 0x02, 0x00, + 0x8e, 0x01, 0x02, 0x00, 0x90, 0x01, 0x02, 0x00, 0x92, 0x01, 0x02, 0x00, 0x94, 0x01, 0x02, 0x00, + 0x96, 0x01, 0x02, 0x00, 0x98, 0x01, 0x02, 0x00, 0x9a, 0x01, 0x02, 0x00, 0x9c, 0x01, 0x02, 0x00, + 0x9e, 0x01, 0x02, 0x00, 0xa0, 0x01, 0x02, 0x00, 0xa2, 0x01, 0x02, 0x00, 0xa4, 0x01, 0x02, 0x00, + 0xa6, 0x01, 0x02, 0x00, 0xa8, 0x01, 0x02, 0x00, 0xaa, 0x01, 0x02, 0x00, 0xac, 0x01, 0x02, 0x00, + 0xae, 0x01, 0x02, 0x00, 0xb0, 0x01, 0x02, 0x00, 0xb2, 0x01, 0x02, 0x00, 0xb4, 0x01, 0x02, 0x00, + 0xb6, 0x01, 0x02, 0x00, 0xb8, 0x01, 0x02, 0x00, 0xba, 0x01, 0x02, 0x00, 0xbc, 0x01, 0x02, 0x00, + 0xbe, 0x01, 0x02, 0x00, 0xc0, 0x01, 0x02, 0x00, 0xc2, 0x01, 0x02, 0x00, 0xc4, 0x01, 0x02, 0x00, + 0xc6, 0x01, 0x02, 0x00, 0xc8, 0x01, 0x02, 0x00, 0xca, 0x01, 0x02, 0x00, 0xcc, 0x01, 0x02, 0x00, + 0xce, 0x01, 0x02, 0x00, 0xd0, 0x01, 0x02, 0x00, 0xd2, 0x01, 0x02, 0x00, 0xd4, 0x01, 0x02, 0x00, + 0xd6, 0x01, 0x02, 0x00, 0xd8, 0x01, 0x02, 0x00, 0xda, 0x01, 0x02, 0x00, 0xdc, 0x01, 0x02, 0x00, + 0xde, 0x01, 0x02, 0x00, 0xe0, 0x01, 0x02, 0x00, 0xe2, 0x01, 0x02, 0x00, 0xe4, 0x01, 0x02, 0x00, + 0xe6, 0x01, 0x02, 0x00, 0xe8, 0x01, 0x02, 0x00, 0xea, 0x01, 0x02, 0x00, 0xec, 0x01, 0x02, 0x00, + 0xee, 0x01, 0x02, 0x00, 0xf0, 0x01, 0x02, 0x00, 0xf2, 0x01, 0x02, 0x00, 0xf4, 0x01, 0x02, 0x00, + + 0xf6, 0x01, 0x02, 0x00, 0xf8, 0x01, 0x02, 0x00, 0xfa, 0x01, 0x02, 0x00, 0xfc, 0x01, 0x02, 0x00, + 0xfe, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x04, 0x02, 0x02, 0x00, + 0x06, 0x02, 0x02, 0x00, 0x08, 0x02, 0x02, 0x00, 0x0a, 0x02, 0x02, 0x00, 0x0c, 0x02, 0x02, 0x00, + 0x0e, 0x02, 0x02, 0x00, 0x10, 0x02, 0x02, 0x00, 0x12, 0x02, 0x02, 0x00, 0x14, 0x02, 0x02, 0x00, + 0x16, 0x02, 0x02, 0x00, 0x18, 0x02, 0x02, 0x00, 0x1a, 0x02, 0x02, 0x00, 0x1c, 0x02, 0x02, 0x00, + 0x1e, 0x02, 0x02, 0x00, 0x20, 0x02, 0x02, 0x00, 0x22, 0x02, 0x02, 0x00, 0x24, 0x02, 0x02, 0x00, + 0x26, 0x02, 0x02, 0x00, 0x28, 0x02, 0x02, 0x00, 0x2a, 0x02, 0x02, 0x00, 0x2c, 0x02, 0x02, 0x00, + 0x2e, 0x02, 0x02, 0x00, 0x30, 0x02, 0x02, 0x00, 0x32, 0x02, 0x02, 0x00, 0x34, 0x02, 0x02, 0x00, + 0x36, 0x02, 0x02, 0x00, 0x38, 0x02, 0x02, 0x00, 0x3a, 0x02, 0x02, 0x00, 0x3c, 0x02, 0x02, 0x00, + 0x3e, 0x02, 0x02, 0x00, 0x40, 0x02, 0x02, 0x00, 0x42, 0x02, 0x02, 0x00, 0x44, 0x02, 0x02, 0x00, + 0x46, 0x02, 0x02, 0x00, 0x48, 0x02, 0x02, 0x00, 0x4a, 0x02, 0x02, 0x00, 0x4c, 0x02, 0x02, 0x00, + 0x4e, 0x02, 0x02, 0x00, 0x50, 0x02, 0x02, 0x00, 0x52, 0x02, 0x02, 0x00, 0x54, 0x02, 0x02, 0x00, + 0x56, 0x02, 0x02, 0x00, 0x58, 0x02, 0x02, 0x00, 0x5a, 0x02, 0x02, 0x00, 0x5c, 0x02, 0x02, 0x00, + 0x5e, 0x02, 0x02, 0x00, 0x60, 0x02, 0x02, 0x00, 0x62, 0x02, 0x02, 0x00, 0x64, 0x02, 0x02, 0x00, + 0x66, 0x02, 0x02, 0x00, 0x68, 0x02, 0x02, 0x00, 0x6a, 0x02, 0x02, 0x00, 0x6c, 0x02, 0x02, 0x00, + 0x6e, 0x02, 0x02, 0x00, 0x70, 0x02, 0x02, 0x00, 0x72, 0x02, 0x02, 0x00, 0x74, 0x02, 0x02, 0x00, + 0x76, 0x02, 0x02, 0x00, 0x78, 0x02, 0x02, 0x00, 0x7a, 0x02, 0x02, 0x00, 0x7c, 0x02, 0x02, 0x00, + 0x7e, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x00, 0x82, 0x02, 0x02, 0x00, 0x84, 0x02, 0x02, 0x00, + 0x86, 0x02, 0x02, 0x00, 0x88, 0x02, 0x02, 0x00, 0x8a, 0x02, 0x02, 0x00, 0x8c, 0x02, 0x02, 0x00, + 0x8e, 0x02, 0x02, 0x00, 0x90, 0x02, 0x02, 0x00, 0x92, 0x02, 0x02, 0x00, 0x94, 0x02, 0x02, 0x00, + 0x96, 0x02, 0x02, 0x00, 0x98, 0x02, 0x02, 0x00, 0x9a, 0x02, 0x02, 0x00, 0x9c, 0x02, 0x02, 0x00, + 0x9e, 0x02, 0x02, 0x00, 0xa0, 0x02, 0x02, 0x00, 0xa2, 0x02, 0x02, 0x00, 0xa4, 0x02, 0x02, 0x00, + 0xa6, 0x02, 0x02, 0x00, 0xa8, 0x02, 0x02, 0x00, 0xaa, 0x02, 0x02, 0x00, 0xac, 0x02, 0x02, 0x00, + 0xae, 0x02, 0x02, 0x00, 0xb0, 0x02, 0x02, 0x00, 0xb2, 0x02, 0x02, 0x00, 0xb4, 0x02, 0x02, 0x00, + 0xb6, 0x02, 0x02, 0x00, 0xb8, 0x02, 0x02, 0x00, 0xba, 0x02, 0x02, 0x00, 0xbc, 0x02, 0x02, 0x00, + 0xbe, 0x02, 0x02, 0x00, 0xc0, 0x02, 0x02, 0x00, 0xc2, 0x02, 0x02, 0x00, 0xc4, 0x02, 0x02, 0x00, + 0xc6, 0x02, 0x02, 0x00, 0xc8, 0x02, 0x02, 0x00, 0xca, 0x02, 0x02, 0x00, 0xcc, 0x02, 0x02, 0x00, + 0xce, 0x02, 0x02, 0x00, 0xd0, 0x02, 0x02, 0x00, 0xd2, 0x02, 0x02, 0x00, 0xd4, 0x02, 0x02, 0x00, + 0xd6, 0x02, 0x02, 0x00, 0xd8, 0x02, 0x02, 0x00, 0xda, 0x02, 0x02, 0x00, 0xdc, 0x02, 0x02, 0x00, + 0xde, 0x02, 0x02, 0x00, 0xe0, 0x02, 0x02, 0x00, 0xe2, 0x02, 0x02, 0x00, 0xe4, 0x02, 0x02, 0x00, + 0xe6, 0x02, 0x02, 0x00, 0xe8, 0x02, 0x02, 0x00, 0xea, 0x02, 0x02, 0x00, 0xec, 0x02, 0x02, 0x00, + 0xee, 0x02, 0x02, 0x00, 0xf0, 0x02, 0x02, 0x00, 0xf2, 0x02, 0x02, 0x00, 0xf4, 0x02, 0x02, 0x00, + + 0xf6, 0x02, 0x02, 0x00, 0xf8, 0x02, 0x02, 0x00, 0xfa, 0x02, 0x02, 0x00, 0xfc, 0x02, 0x02, 0x00, + 0xfe, 0x02, 0x02, 0x00, 0x00, 0x03, 0x02, 0x00, 0x02, 0x03, 0x02, 0x00, 0x04, 0x03, 0x02, 0x00, + 0x06, 0x03, 0x02, 0x00, 0x08, 0x03, 0x02, 0x00, 0x0a, 0x03, 0x02, 0x00, 0x0c, 0x03, 0x02, 0x00, + 0x0e, 0x03, 0x02, 0x00, 0x10, 0x03, 0x02, 0x00, 0x12, 0x03, 0x02, 0x00, 0x14, 0x03, 0x02, 0x00, + 0x16, 0x03, 0x02, 0x00, 0x18, 0x03, 0x02, 0x00, 0x1a, 0x03, 0x02, 0x00, 0x1c, 0x03, 0x02, 0x00, + 0x1e, 0x03, 0x02, 0x00, 0x20, 0x03, 0x02, 0x00, 0x22, 0x03, 0x02, 0x00, 0x24, 0x03, 0x02, 0x00, + 0x26, 0x03, 0x02, 0x00, 0x28, 0x03, 0x02, 0x00, 0x2a, 0x03, 0x02, 0x00, 0x2c, 0x03, 0x02, 0x00, + 0x2e, 0x03, 0x02, 0x00, 0x30, 0x03, 0x02, 0x00, 0x32, 0x03, 0x02, 0x00, 0x34, 0x03, 0x02, 0x00, + 0x36, 0x03, 0x02, 0x00, 0x38, 0x03, 0x02, 0x00, 0x3a, 0x03, 0x02, 0x00, 0x3c, 0x03, 0x02, 0x00, + 0x3e, 0x03, 0x02, 0x00, 0x40, 0x03, 0x02, 0x00, 0x42, 0x03, 0x02, 0x00, 0x44, 0x03, 0x02, 0x00, + 0x46, 0x03, 0x02, 0x00, 0x48, 0x03, 0x02, 0x00, 0x4a, 0x03, 0x02, 0x00, 0x4c, 0x03, 0x02, 0x00, + 0x4e, 0x03, 0x02, 0x00, 0x50, 0x03, 0x02, 0x00, 0x52, 0x03, 0x02, 0x00, 0x54, 0x03, 0x02, 0x00, + 0x56, 0x03, 0x02, 0x00, 0x58, 0x03, 0x02, 0x00, 0x5a, 0x03, 0x02, 0x00, 0x5c, 0x03, 0x02, 0x00, + 0x5e, 0x03, 0x02, 0x00, 0x60, 0x03, 0x02, 0x00, 0x62, 0x03, 0x02, 0x00, 0x64, 0x03, 0x02, 0x00, + 0x66, 0x03, 0x02, 0x00, 0x68, 0x03, 0x02, 0x00, 0x6a, 0x03, 0x02, 0x00, 0x6c, 0x03, 0x02, 0x00, + 0x6e, 0x03, 0x02, 0x00, 0x70, 0x03, 0x02, 0x00, 0x72, 0x03, 0x02, 0x00, 0x74, 0x03, 0x02, 0x00, + 0x76, 0x03, 0x02, 0x00, 0x78, 0x03, 0x02, 0x00, 0x7a, 0x03, 0x02, 0x00, 0x7c, 0x03, 0x02, 0x00, + 0x7e, 0x03, 0x02, 0x00, 0x80, 0x03, 0x02, 0x00, 0x82, 0x03, 0x02, 0x00, 0x84, 0x03, 0x02, 0x00, + 0x86, 0x03, 0x02, 0x00, 0x88, 0x03, 0x02, 0x00, 0x8a, 0x03, 0x02, 0x00, 0x8c, 0x03, 0x02, 0x00, + 0x8e, 0x03, 0x02, 0x00, 0x90, 0x03, 0x02, 0x00, 0x92, 0x03, 0x02, 0x00, 0x94, 0x03, 0x02, 0x00, + 0x96, 0x03, 0x02, 0x00, 0x98, 0x03, 0x02, 0x00, 0x9a, 0x03, 0x02, 0x00, 0x9c, 0x03, 0x02, 0x00, + 0x9e, 0x03, 0x02, 0x00, 0xa0, 0x03, 0x02, 0x00, 0xa2, 0x03, 0x02, 0x00, 0xa4, 0x03, 0x02, 0x00, + 0xa6, 0x03, 0x02, 0x00, 0xa8, 0x03, 0x02, 0x00, 0xaa, 0x03, 0x02, 0x00, 0xac, 0x03, 0x02, 0x00, + 0xae, 0x03, 0x02, 0x00, 0xb0, 0x03, 0x02, 0x00, 0xb2, 0x03, 0x02, 0x00, 0xb4, 0x03, 0x02, 0x00, + 0xb6, 0x03, 0x02, 0x00, 0xb8, 0x03, 0x02, 0x00, 0xba, 0x03, 0x02, 0x00, 0xbc, 0x03, 0x02, 0x00, + 0xbe, 0x03, 0x02, 0x00, 0xc0, 0x03, 0x02, 0x00, 0xc2, 0x03, 0x02, 0x00, 0xc4, 0x03, 0x02, 0x00, + 0xc6, 0x03, 0x02, 0x00, 0xc8, 0x03, 0x02, 0x00, 0xca, 0x03, 0x02, 0x00, 0xcc, 0x03, 0x02, 0x00, + 0xce, 0x03, 0x02, 0x00, 0xd0, 0x03, 0x02, 0x00, 0xd2, 0x03, 0x02, 0x00, 0xd4, 0x03, 0x02, 0x00, + 0xd6, 0x03, 0x02, 0x00, 0xd8, 0x03, 0x02, 0x00, 0xda, 0x03, 0x02, 0x00, 0xdc, 0x03, 0x02, 0x00, + 0xde, 0x03, 0x02, 0x00, 0xe0, 0x03, 0x02, 0x00, 0xe2, 0x03, 0x02, 0x00, 0xe4, 0x03, 0x02, 0x00, + 0xe6, 0x03, 0x02, 0x00, 0xe8, 0x03, 0x02, 0x00, 0xea, 0x03, 0x02, 0x00, 0xec, 0x03, 0x02, 0x00, + 0xee, 0x03, 0x02, 0x00, 0xf0, 0x03, 0x02, 0x00, 0xf2, 0x03, 0x02, 0x00, 0xf4, 0x03, 0x02, 0x00, + + 0xf6, 0x03, 0x02, 0x00, 0xf8, 0x03, 0x02, 0x00, 0xfa, 0x03, 0x02, 0x00, 0xfc, 0x03, 0x02, 0x00, + 0xfe, 0x03, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x06, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x02, 0x00, + 0x0e, 0x00, 0x02, 0x00, 0x10, 0x00, 0x02, 0x00, 0x12, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, + 0x16, 0x00, 0x02, 0x00, 0x18, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x02, 0x00, 0x1c, 0x00, 0x02, 0x00, + 0x1e, 0x00, 0x02, 0x00, 0x20, 0x00, 0x02, 0x00, 0x22, 0x00, 0x02, 0x00, 0x24, 0x00, 0x02, 0x00, + 0x26, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x2a, 0x00, 0x02, 0x00, 0x2c, 0x00, 0x02, 0x00, + 0x2e, 0x00, 0x02, 0x00, 0x30, 0x00, 0x02, 0x00, 0x32, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, + 0x36, 0x00, 0x02, 0x00, 0x38, 0x00, 0x02, 0x00, 0x3a, 0x00, 0x02, 0x00, 0x3c, 0x00, 0x02, 0x00, + 0x3e, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x42, 0x00, 0x02, 0x00, 0x44, 0x00, 0x02, 0x00, + 0x46, 0x00, 0x02, 0x00, 0x48, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x02, 0x00, 0x4c, 0x00, 0x02, 0x00, + 0x4e, 0x00, 0x02, 0x00, 0x50, 0x00, 0x02, 0x00, 0x52, 0x00, 0x02, 0x00, 0x54, 0x00, 0x02, 0x00, + 0x56, 0x00, 0x02, 0x00, 0x58, 0x00, 0x02, 0x00, 0x5a, 0x00, 0x02, 0x00, 0x5c, 0x00, 0x02, 0x00, + 0x5e, 0x00, 0x02, 0x00, 0x60, 0x00, 0x02, 0x00, 0x62, 0x00, 0x02, 0x00, 0x64, 0x00, 0x02, 0x00, + 0x66, 0x00, 0x02, 0x00, 0x68, 0x00, 0x02, 0x00, 0x6a, 0x00, 0x02, 0x00, 0x6c, 0x00, 0x02, 0x00, + 0x6e, 0x00, 0x02, 0x00, 0x70, 0x00, 0x02, 0x00, 0x72, 0x00, 0x02, 0x00, 0x74, 0x00, 0x02, 0x00, + 0x76, 0x00, 0x02, 0x00, 0x78, 0x00, 0x02, 0x00, 0x7a, 0x00, 0x02, 0x00, 0x7c, 0x00, 0x02, 0x00, + 0x7e, 0x00, 0x02, 0x00, 0x80, 0x00, 0x02, 0x00, 0x82, 0x00, 0x02, 0x00, 0x84, 0x00, 0x02, 0x00, + 0x86, 0x00, 0x02, 0x00, 0x88, 0x00, 0x02, 0x00, 0x8a, 0x00, 0x02, 0x00, 0x8c, 0x00, 0x02, 0x00, + 0x8e, 0x00, 0x02, 0x00, 0x90, 0x00, 0x02, 0x00, 0x92, 0x00, 0x02, 0x00, 0x94, 0x00, 0x02, 0x00, + 0x96, 0x00, 0x02, 0x00, 0x98, 0x00, 0x02, 0x00, 0x9a, 0x00, 0x02, 0x00, 0x9c, 0x00, 0x02, 0x00, + 0x9e, 0x00, 0x02, 0x00, 0xa0, 0x00, 0x02, 0x00, 0xa2, 0x00, 0x02, 0x00, 0xa4, 0x00, 0x02, 0x00, + 0xa6, 0x00, 0x02, 0x00, 0xa8, 0x00, 0x02, 0x00, 0xaa, 0x00, 0x02, 0x00, 0xac, 0x00, 0x02, 0x00, + 0xae, 0x00, 0x02, 0x00, 0xb0, 0x00, 0x02, 0x00, 0xb2, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x02, 0x00, + 0xb6, 0x00, 0x02, 0x00, 0xb8, 0x00, 0x02, 0x00, 0xba, 0x00, 0x02, 0x00, 0xbc, 0x00, 0x02, 0x00, + 0xbe, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x02, 0x00, 0xc2, 0x00, 0x02, 0x00, 0xc4, 0x00, 0x02, 0x00, + 0xc6, 0x00, 0x02, 0x00, 0xc8, 0x00, 0x02, 0x00, 0xca, 0x00, 0x02, 0x00, 0xcc, 0x00, 0x02, 0x00, + 0xce, 0x00, 0x02, 0x00, 0xd0, 0x00, 0x02, 0x00, 0xd2, 0x00, 0x02, 0x00, 0xd4, 0x00, 0x02, 0x00, + 0xd6, 0x00, 0x02, 0x00, 0xd8, 0x00, 0x02, 0x00, 0xda, 0x00, 0x02, 0x00, 0xdc, 0x00, 0x02, 0x00, + 0xde, 0x00, 0x02, 0x00, 0xe0, 0x00, 0x02, 0x00, 0xe2, 0x00, 0x02, 0x00, 0xe4, 0x00, 0x02, 0x00, + 0xe6, 0x00, 0x02, 0x00, 0xe8, 0x00, 0x02, 0x00, 0xea, 0x00, 0x02, 0x00, 0xec, 0x00, 0x02, 0x00, + 0xee, 0x00, 0x02, 0x00, 0xf0, 0x00, 0x02, 0x00, 0xf2, 0x00, 0x02, 0x00, 0xf4, 0x00, 0x02, 0x00, + + 0xf6, 0x00, 0x02, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xfa, 0x00, 0x02, 0x00, 0xfc, 0x00, 0x02, 0x00, + 0xfe, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x02, 0x01, 0x02, 0x00, 0x04, 0x01, 0x02, 0x00, + 0x06, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x0a, 0x01, 0x02, 0x00, 0x0c, 0x01, 0x02, 0x00, + 0x0e, 0x01, 0x02, 0x00, 0x10, 0x01, 0x02, 0x00, 0x12, 0x01, 0x02, 0x00, 0x14, 0x01, 0x02, 0x00, + 0x16, 0x01, 0x02, 0x00, 0x18, 0x01, 0x02, 0x00, 0x1a, 0x01, 0x02, 0x00, 0x1c, 0x01, 0x02, 0x00, + 0x1e, 0x01, 0x02, 0x00, 0x20, 0x01, 0x02, 0x00, 0x22, 0x01, 0x02, 0x00, 0x24, 0x01, 0x02, 0x00, + 0x26, 0x01, 0x02, 0x00, 0x28, 0x01, 0x02, 0x00, 0x2a, 0x01, 0x02, 0x00, 0x2c, 0x01, 0x02, 0x00, + 0x2e, 0x01, 0x02, 0x00, 0x30, 0x01, 0x02, 0x00, 0x32, 0x01, 0x02, 0x00, 0x34, 0x01, 0x02, 0x00, + 0x36, 0x01, 0x02, 0x00, 0x38, 0x01, 0x02, 0x00, 0x3a, 0x01, 0x02, 0x00, 0x3c, 0x01, 0x02, 0x00, + 0x3e, 0x01, 0x02, 0x00, 0x40, 0x01, 0x02, 0x00, 0x42, 0x01, 0x02, 0x00, 0x44, 0x01, 0x02, 0x00, + 0x46, 0x01, 0x02, 0x00, 0x48, 0x01, 0x02, 0x00, 0x4a, 0x01, 0x02, 0x00, 0x4c, 0x01, 0x02, 0x00, + 0x4e, 0x01, 0x02, 0x00, 0x50, 0x01, 0x02, 0x00, 0x52, 0x01, 0x02, 0x00, 0x54, 0x01, 0x02, 0x00, + 0x56, 0x01, 0x02, 0x00, 0x58, 0x01, 0x02, 0x00, 0x5a, 0x01, 0x02, 0x00, 0x5c, 0x01, 0x02, 0x00, + 0x5e, 0x01, 0x02, 0x00, 0x60, 0x01, 0x02, 0x00, 0x62, 0x01, 0x02, 0x00, 0x64, 0x01, 0x02, 0x00, + 0x66, 0x01, 0x02, 0x00, 0x68, 0x01, 0x02, 0x00, 0x6a, 0x01, 0x02, 0x00, 0x6c, 0x01, 0x02, 0x00, + 0x6e, 0x01, 0x02, 0x00, 0x70, 0x01, 0x02, 0x00, 0x72, 0x01, 0x02, 0x00, 0x74, 0x01, 0x02, 0x00, + 0x76, 0x01, 0x02, 0x00, 0x78, 0x01, 0x02, 0x00, 0x7a, 0x01, 0x02, 0x00, 0x7c, 0x01, 0x02, 0x00, + 0x7e, 0x01, 0x02, 0x00, 0x80, 0x01, 0x02, 0x00, 0x82, 0x01, 0x02, 0x00, 0x84, 0x01, 0x02, 0x00, + 0x86, 0x01, 0x02, 0x00, 0x88, 0x01, 0x02, 0x00, 0x8a, 0x01, 0x02, 0x00, 0x8c, 0x01, 0x02, 0x00, + 0x8e, 0x01, 0x02, 0x00, 0x90, 0x01, 0x02, 0x00, 0x92, 0x01, 0x02, 0x00, 0x94, 0x01, 0x02, 0x00, + 0x96, 0x01, 0x02, 0x00, 0x98, 0x01, 0x02, 0x00, 0x9a, 0x01, 0x02, 0x00, 0x9c, 0x01, 0x02, 0x00, + 0x9e, 0x01, 0x02, 0x00, 0xa0, 0x01, 0x02, 0x00, 0xa2, 0x01, 0x02, 0x00, 0xa4, 0x01, 0x02, 0x00, + 0xa6, 0x01, 0x02, 0x00, 0xa8, 0x01, 0x02, 0x00, 0xaa, 0x01, 0x02, 0x00, 0xac, 0x01, 0x02, 0x00, + 0xae, 0x01, 0x02, 0x00, 0xb0, 0x01, 0x02, 0x00, 0xb2, 0x01, 0x02, 0x00, 0xb4, 0x01, 0x02, 0x00, + 0xb6, 0x01, 0x02, 0x00, 0xb8, 0x01, 0x02, 0x00, 0xba, 0x01, 0x02, 0x00, 0xbc, 0x01, 0x02, 0x00, + 0xbe, 0x01, 0x02, 0x00, 0xc0, 0x01, 0x02, 0x00, 0xc2, 0x01, 0x02, 0x00, 0xc4, 0x01, 0x02, 0x00, + 0xc6, 0x01, 0x02, 0x00, 0xc8, 0x01, 0x02, 0x00, 0xca, 0x01, 0x02, 0x00, 0xcc, 0x01, 0x02, 0x00, + 0xce, 0x01, 0x02, 0x00, 0xd0, 0x01, 0x02, 0x00, 0xd2, 0x01, 0x02, 0x00, 0xd4, 0x01, 0x02, 0x00, + 0xd6, 0x01, 0x02, 0x00, 0xd8, 0x01, 0x02, 0x00, 0xda, 0x01, 0x02, 0x00, 0xdc, 0x01, 0x02, 0x00, + 0xde, 0x01, 0x02, 0x00, 0xe0, 0x01, 0x02, 0x00, 0xe2, 0x01, 0x02, 0x00, 0xe4, 0x01, 0x02, 0x00, + 0xe6, 0x01, 0x02, 0x00, 0xe8, 0x01, 0x02, 0x00, 0xea, 0x01, 0x02, 0x00, 0xec, 0x01, 0x02, 0x00, + 0xee, 0x01, 0x02, 0x00, 0xf0, 0x01, 0x02, 0x00, 0xf2, 0x01, 0x02, 0x00, 0xf4, 0x01, 0x02, 0x00, + + 0xf6, 0x01, 0x02, 0x00, 0xf8, 0x01, 0x02, 0x00, 0xfa, 0x01, 0x02, 0x00, 0xfc, 0x01, 0x02, 0x00, + 0xfe, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x04, 0x02, 0x02, 0x00, + 0x06, 0x02, 0x02, 0x00, 0x08, 0x02, 0x02, 0x00, 0x0a, 0x02, 0x02, 0x00, 0x0c, 0x02, 0x02, 0x00, + 0x0e, 0x02, 0x02, 0x00, 0x10, 0x02, 0x02, 0x00, 0x12, 0x02, 0x02, 0x00, 0x14, 0x02, 0x02, 0x00, + 0x16, 0x02, 0x02, 0x00, 0x18, 0x02, 0x02, 0x00, 0x1a, 0x02, 0x02, 0x00, 0x1c, 0x02, 0x02, 0x00, + 0x1e, 0x02, 0x02, 0x00, 0x20, 0x02, 0x02, 0x00, 0x22, 0x02, 0x02, 0x00, 0x24, 0x02, 0x02, 0x00, + 0x26, 0x02, 0x02, 0x00, 0x28, 0x02, 0x02, 0x00, 0x2a, 0x02, 0x02, 0x00, 0x2c, 0x02, 0x02, 0x00, + 0x2e, 0x02, 0x02, 0x00, 0x30, 0x02, 0x02, 0x00, 0x32, 0x02, 0x02, 0x00, 0x34, 0x02, 0x02, 0x00, + 0x36, 0x02, 0x02, 0x00, 0x38, 0x02, 0x02, 0x00, 0x3a, 0x02, 0x02, 0x00, 0x3c, 0x02, 0x02, 0x00, + 0x3e, 0x02, 0x02, 0x00, 0x40, 0x02, 0x02, 0x00, 0x42, 0x02, 0x02, 0x00, 0x44, 0x02, 0x02, 0x00, + 0x46, 0x02, 0x02, 0x00, 0x48, 0x02, 0x02, 0x00, 0x4a, 0x02, 0x02, 0x00, 0x4c, 0x02, 0x02, 0x00, + 0x4e, 0x02, 0x02, 0x00, 0x50, 0x02, 0x02, 0x00, 0x52, 0x02, 0x02, 0x00, 0x54, 0x02, 0x02, 0x00, + 0x56, 0x02, 0x02, 0x00, 0x58, 0x02, 0x02, 0x00, 0x5a, 0x02, 0x02, 0x00, 0x5c, 0x02, 0x02, 0x00, + 0x5e, 0x02, 0x02, 0x00, 0x60, 0x02, 0x02, 0x00, 0x62, 0x02, 0x02, 0x00, 0x64, 0x02, 0x02, 0x00, + 0x66, 0x02, 0x02, 0x00, 0x68, 0x02, 0x02, 0x00, 0x6a, 0x02, 0x02, 0x00, 0x6c, 0x02, 0x02, 0x00, + 0x6e, 0x02, 0x02, 0x00, 0x70, 0x02, 0x02, 0x00, 0x72, 0x02, 0x02, 0x00, 0x74, 0x02, 0x02, 0x00, + 0x76, 0x02, 0x02, 0x00, 0x78, 0x02, 0x02, 0x00, 0x7a, 0x02, 0x02, 0x00, 0x7c, 0x02, 0x02, 0x00, + 0x7e, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x00, 0x82, 0x02, 0x02, 0x00, 0x84, 0x02, 0x02, 0x00, + 0x86, 0x02, 0x02, 0x00, 0x88, 0x02, 0x02, 0x00, 0x8a, 0x02, 0x02, 0x00, 0x8c, 0x02, 0x02, 0x00, + 0x8e, 0x02, 0x02, 0x00, 0x90, 0x02, 0x02, 0x00, 0x92, 0x02, 0x02, 0x00, 0x94, 0x02, 0x02, 0x00, + 0x96, 0x02, 0x02, 0x00, 0x98, 0x02, 0x02, 0x00, 0x9a, 0x02, 0x02, 0x00, 0x9c, 0x02, 0x02, 0x00, + 0x9e, 0x02, 0x02, 0x00, 0xa0, 0x02, 0x02, 0x00, 0xa2, 0x02, 0x02, 0x00, 0xa4, 0x02, 0x02, 0x00, + 0xa6, 0x02, 0x02, 0x00, 0xa8, 0x02, 0x02, 0x00, 0xaa, 0x02, 0x02, 0x00, 0xac, 0x02, 0x02, 0x00, + 0xae, 0x02, 0x02, 0x00, 0xb0, 0x02, 0x02, 0x00, 0xb2, 0x02, 0x02, 0x00, 0xb4, 0x02, 0x02, 0x00, + 0xb6, 0x02, 0x02, 0x00, 0xb8, 0x02, 0x02, 0x00, 0xba, 0x02, 0x02, 0x00, 0xbc, 0x02, 0x02, 0x00, + 0xbe, 0x02, 0x02, 0x00, 0xc0, 0x02, 0x02, 0x00, 0xc2, 0x02, 0x02, 0x00, 0xc4, 0x02, 0x02, 0x00, + 0xc6, 0x02, 0x02, 0x00, 0xc8, 0x02, 0x02, 0x00, 0xca, 0x02, 0x02, 0x00, 0xcc, 0x02, 0x02, 0x00, + 0xce, 0x02, 0x02, 0x00, 0xd0, 0x02, 0x02, 0x00, 0xd2, 0x02, 0x02, 0x00, 0xd4, 0x02, 0x02, 0x00, + 0xd6, 0x02, 0x02, 0x00, 0xd8, 0x02, 0x02, 0x00, 0xda, 0x02, 0x02, 0x00, 0xdc, 0x02, 0x02, 0x00, + 0xde, 0x02, 0x02, 0x00, 0xe0, 0x02, 0x02, 0x00, 0xe2, 0x02, 0x02, 0x00, 0xe4, 0x02, 0x02, 0x00, + 0xe6, 0x02, 0x02, 0x00, 0xe8, 0x02, 0x02, 0x00, 0xea, 0x02, 0x02, 0x00, 0xec, 0x02, 0x02, 0x00, + 0xee, 0x02, 0x02, 0x00, 0xf0, 0x02, 0x02, 0x00, 0xf2, 0x02, 0x02, 0x00, 0xf4, 0x02, 0x02, 0x00, + + 0xf6, 0x02, 0x02, 0x00, 0xf8, 0x02, 0x02, 0x00, 0xfa, 0x02, 0x02, 0x00, 0xfc, 0x02, 0x02, 0x00, + 0xfe, 0x02, 0x02, 0x00, 0x00, 0x03, 0x02, 0x00, 0x02, 0x03, 0x02, 0x00, 0x04, 0x03, 0x02, 0x00, + 0x06, 0x03, 0x02, 0x00, 0x08, 0x03, 0x02, 0x00, 0x0a, 0x03, 0x02, 0x00, 0x0c, 0x03, 0x02, 0x00, + 0x0e, 0x03, 0x02, 0x00, 0x10, 0x03, 0x02, 0x00, 0x12, 0x03, 0x02, 0x00, 0x14, 0x03, 0x02, 0x00, + 0x16, 0x03, 0x02, 0x00, 0x18, 0x03, 0x02, 0x00, 0x1a, 0x03, 0x02, 0x00, 0x1c, 0x03, 0x02, 0x00, + 0x1e, 0x03, 0x02, 0x00, 0x20, 0x03, 0x02, 0x00, 0x22, 0x03, 0x02, 0x00, 0x24, 0x03, 0x02, 0x00, + 0x26, 0x03, 0x02, 0x00, 0x28, 0x03, 0x02, 0x00, 0x2a, 0x03, 0x02, 0x00, 0x2c, 0x03, 0x02, 0x00, + 0x2e, 0x03, 0x02, 0x00, 0x30, 0x03, 0x02, 0x00, 0x32, 0x03, 0x02, 0x00, 0x34, 0x03, 0x02, 0x00, + 0x36, 0x03, 0x02, 0x00, 0x38, 0x03, 0x02, 0x00, 0x3a, 0x03, 0x02, 0x00, 0x3c, 0x03, 0x02, 0x00, + 0x3e, 0x03, 0x02, 0x00, 0x40, 0x03, 0x02, 0x00, 0x42, 0x03, 0x02, 0x00, 0x44, 0x03, 0x02, 0x00, + 0x46, 0x03, 0x02, 0x00, 0x48, 0x03, 0x02, 0x00, 0x4a, 0x03, 0x02, 0x00, 0x4c, 0x03, 0x02, 0x00, + 0x4e, 0x03, 0x02, 0x00, 0x50, 0x03, 0x02, 0x00, 0x52, 0x03, 0x02, 0x00, 0x54, 0x03, 0x02, 0x00, + 0x56, 0x03, 0x02, 0x00, 0x58, 0x03, 0x02, 0x00, 0x5a, 0x03, 0x02, 0x00, 0x5c, 0x03, 0x02, 0x00, + 0x5e, 0x03, 0x02, 0x00, 0x60, 0x03, 0x02, 0x00, 0x62, 0x03, 0x02, 0x00, 0x64, 0x03, 0x02, 0x00, + 0x66, 0x03, 0x02, 0x00, 0x68, 0x03, 0x02, 0x00, 0x6a, 0x03, 0x02, 0x00, 0x6c, 0x03, 0x02, 0x00, + 0x6e, 0x03, 0x02, 0x00, 0x70, 0x03, 0x02, 0x00, 0x72, 0x03, 0x02, 0x00, 0x74, 0x03, 0x02, 0x00, + 0x76, 0x03, 0x02, 0x00, 0x78, 0x03, 0x02, 0x00, 0x7a, 0x03, 0x02, 0x00, 0x7c, 0x03, 0x02, 0x00, + 0x7e, 0x03, 0x02, 0x00, 0x80, 0x03, 0x02, 0x00, 0x82, 0x03, 0x02, 0x00, 0x84, 0x03, 0x02, 0x00, + 0x86, 0x03, 0x02, 0x00, 0x88, 0x03, 0x02, 0x00, 0x8a, 0x03, 0x02, 0x00, 0x8c, 0x03, 0x02, 0x00, + 0x8e, 0x03, 0x02, 0x00, 0x90, 0x03, 0x02, 0x00, 0x92, 0x03, 0x02, 0x00, 0x94, 0x03, 0x02, 0x00, + 0x96, 0x03, 0x02, 0x00, 0x98, 0x03, 0x02, 0x00, 0x9a, 0x03, 0x02, 0x00, 0x9c, 0x03, 0x02, 0x00, + 0x9e, 0x03, 0x02, 0x00, 0xa0, 0x03, 0x02, 0x00, 0xa2, 0x03, 0x02, 0x00, 0xa4, 0x03, 0x02, 0x00, + 0xa6, 0x03, 0x02, 0x00, 0xa8, 0x03, 0x02, 0x00, 0xaa, 0x03, 0x02, 0x00, 0xac, 0x03, 0x02, 0x00, + 0xae, 0x03, 0x02, 0x00, 0xb0, 0x03, 0x02, 0x00, 0xb2, 0x03, 0x02, 0x00, 0xb4, 0x03, 0x02, 0x00, + 0xb6, 0x03, 0x02, 0x00, 0xb8, 0x03, 0x02, 0x00, 0xba, 0x03, 0x02, 0x00, 0xbc, 0x03, 0x02, 0x00, + 0xbe, 0x03, 0x02, 0x00, 0xc0, 0x03, 0x02, 0x00, 0xc2, 0x03, 0x02, 0x00, 0xc4, 0x03, 0x02, 0x00, + 0xc6, 0x03, 0x02, 0x00, 0xc8, 0x03, 0x02, 0x00, 0xca, 0x03, 0x02, 0x00, 0xcc, 0x03, 0x02, 0x00, + 0xce, 0x03, 0x02, 0x00, 0xd0, 0x03, 0x02, 0x00, 0xd2, 0x03, 0x02, 0x00, 0xd4, 0x03, 0x02, 0x00, + 0xd6, 0x03, 0x02, 0x00, 0xd8, 0x03, 0x02, 0x00, 0xda, 0x03, 0x02, 0x00, 0xdc, 0x03, 0x02, 0x00, + 0xde, 0x03, 0x02, 0x00, 0xe0, 0x03, 0x02, 0x00, 0xe2, 0x03, 0x02, 0x00, 0xe4, 0x03, 0x02, 0x00, + 0xe6, 0x03, 0x02, 0x00, 0xe8, 0x03, 0x02, 0x00, 0xea, 0x03, 0x02, 0x00, 0xec, 0x03, 0x02, 0x00, + 0xee, 0x03, 0x02, 0x00, 0xf0, 0x03, 0x02, 0x00, 0xf2, 0x03, 0x02, 0x00, 0xf4, 0x03, 0x02, 0x00, + + 0xf6, 0x03, 0x02, 0x00, 0xf8, 0x03, 0x02, 0x00, 0xfa, 0x03, 0x02, 0x00, 0xfc, 0x03, 0x02, 0x00, + 0xfe, 0x03, 0x02, 0x00 +}; + +#ifdef _USE_GAMMA_RESET_HC_ +const uint8_t mGammaResetTablesBuf[] = { + 0x0E, 0x00, 0x00, 0x00, /// ID -> 4 bytes + + 0x03, /// eGammaTblSize -> 1 byte + 0x00, /// nTbl -> 1 byte + 0x00, /// eBypassB -> 1 byte + 0x00, /// eBypassG -> 1 byte + 0x00, /// eBypassR -> 1 byte + 0x00, 0x00, 0x00, 0x04, /// *pnRedTable + 0x00, 0x00, 0x00, 0x04, /// *pnBlueTable + 0x08, 0x00, 0x00, 0x04, /// *pnGreenTable + + 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02,0x00, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x06, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x02, 0x00, + 0x0e, 0x00, 0x02, 0x00, 0x10, 0x00, 0x02, 0x00, 0x12, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, + 0x16, 0x00, 0x02, 0x00, 0x18, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x02, 0x00, 0x1c, 0x00, 0x02, 0x00, + 0x1e, 0x00, 0x02, 0x00, 0x20, 0x00, 0x02, 0x00, 0x22, 0x00, 0x02, 0x00, 0x24, 0x00, 0x02, 0x00, + 0x26, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x2a, 0x00, 0x02, 0x00, 0x2c, 0x00, 0x02, 0x00, + 0x2e, 0x00, 0x02, 0x00, 0x30, 0x00, 0x02, 0x00, 0x32, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, + 0x36, 0x00, 0x02, 0x00, 0x38, 0x00, 0x02, 0x00, 0x3a, 0x00, 0x02, 0x00, 0x3c, 0x00, 0x02, 0x00, + 0x3e, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x42, 0x00, 0x02, 0x00, 0x44, 0x00, 0x02, 0x00, + 0x46, 0x00, 0x02, 0x00, 0x48, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x02, 0x00, 0x4c, 0x00, 0x02, 0x00, + 0x4e, 0x00, 0x02, 0x00, 0x50, 0x00, 0x02, 0x00, 0x52, 0x00, 0x02, 0x00, 0x54, 0x00, 0x02, 0x00, + 0x56, 0x00, 0x02, 0x00, 0x58, 0x00, 0x02, 0x00, 0x5a, 0x00, 0x02, 0x00, 0x5c, 0x00, 0x02, 0x00, + 0x5e, 0x00, 0x02, 0x00, 0x60, 0x00, 0x02, 0x00, 0x62, 0x00, 0x02, 0x00, 0x64, 0x00, 0x02, 0x00, + 0x66, 0x00, 0x02, 0x00, 0x68, 0x00, 0x02, 0x00, 0x6a, 0x00, 0x02, 0x00, 0x6c, 0x00, 0x02, 0x00, + 0x6e, 0x00, 0x02, 0x00, 0x70, 0x00, 0x02, 0x00, 0x72, 0x00, 0x02, 0x00, 0x74, 0x00, 0x02, 0x00, + 0x76, 0x00, 0x02, 0x00, 0x78, 0x00, 0x02, 0x00, 0x7a, 0x00, 0x02, 0x00, 0x7c, 0x00, 0x02, 0x00, + 0x7e, 0x00, 0x02, 0x00, 0x80, 0x00, 0x02, 0x00, 0x82, 0x00, 0x02, 0x00, 0x84, 0x00, 0x02, 0x00, + 0x86, 0x00, 0x02, 0x00, 0x88, 0x00, 0x02, 0x00, 0x8a, 0x00, 0x02, 0x00, 0x8c, 0x00, 0x02, 0x00, + 0x8e, 0x00, 0x02, 0x00, 0x90, 0x00, 0x02, 0x00, 0x92, 0x00, 0x02, 0x00, 0x94, 0x00, 0x02, 0x00, + 0x96, 0x00, 0x02, 0x00, 0x98, 0x00, 0x02, 0x00, 0x9a, 0x00, 0x02, 0x00, 0x9c, 0x00, 0x02, 0x00, + 0x9e, 0x00, 0x02, 0x00, 0xa0, 0x00, 0x02, 0x00, 0xa2, 0x00, 0x02, 0x00, 0xa4, 0x00, 0x02, 0x00, + 0xa6, 0x00, 0x02, 0x00, 0xa8, 0x00, 0x02, 0x00, 0xaa, 0x00, 0x02, 0x00, 0xac, 0x00, 0x02, 0x00, + 0xae, 0x00, 0x02, 0x00, 0xb0, 0x00, 0x02, 0x00, 0xb2, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x02, 0x00, + 0xb6, 0x00, 0x02, 0x00, 0xb8, 0x00, 0x02, 0x00, 0xba, 0x00, 0x02, 0x00, 0xbc, 0x00, 0x02, 0x00, + 0xbe, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x02, 0x00, 0xc2, 0x00, 0x02, 0x00, 0xc4, 0x00, 0x02, 0x00, + 0xc6, 0x00, 0x02, 0x00, 0xc8, 0x00, 0x02, 0x00, 0xca, 0x00, 0x02, 0x00, 0xcc, 0x00, 0x02, 0x00, + 0xce, 0x00, 0x02, 0x00, 0xd0, 0x00, 0x02, 0x00, 0xd2, 0x00, 0x02, 0x00, 0xd4, 0x00, 0x02, 0x00, + 0xd6, 0x00, 0x02, 0x00, 0xd8, 0x00, 0x02, 0x00, 0xda, 0x00, 0x02, 0x00, 0xdc, 0x00, 0x02, 0x00, + 0xde, 0x00, 0x02, 0x00, 0xe0, 0x00, 0x02, 0x00, 0xe2, 0x00, 0x02, 0x00, 0xe4, 0x00, 0x02, 0x00, + 0xe6, 0x00, 0x02, 0x00, 0xe8, 0x00, 0x02, 0x00, 0xea, 0x00, 0x02, 0x00, 0xec, 0x00, 0x02, 0x00, + 0xee, 0x00, 0x02, 0x00, 0xf0, 0x00, 0x02, 0x00, 0xf2, 0x00, 0x02, 0x00, 0xf4, 0x00, 0x02, 0x00, + + 0xf6, 0x00, 0x02, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xfa, 0x00, 0x02, 0x00, 0xfc, 0x00, 0x02, 0x00, + 0xfe, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x02, 0x01, 0x02, 0x00, 0x04, 0x01, 0x02, 0x00, + 0x06, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x0a, 0x01, 0x02, 0x00, 0x0c, 0x01, 0x02, 0x00, + 0x0e, 0x01, 0x02, 0x00, 0x10, 0x01, 0x02, 0x00, 0x12, 0x01, 0x02, 0x00, 0x14, 0x01, 0x02, 0x00, + 0x16, 0x01, 0x02, 0x00, 0x18, 0x01, 0x02, 0x00, 0x1a, 0x01, 0x02, 0x00, 0x1c, 0x01, 0x02, 0x00, + 0x1e, 0x01, 0x02, 0x00, 0x20, 0x01, 0x02, 0x00, 0x22, 0x01, 0x02, 0x00, 0x24, 0x01, 0x02, 0x00, + 0x26, 0x01, 0x02, 0x00, 0x28, 0x01, 0x02, 0x00, 0x2a, 0x01, 0x02, 0x00, 0x2c, 0x01, 0x02, 0x00, + 0x2e, 0x01, 0x02, 0x00, 0x30, 0x01, 0x02, 0x00, 0x32, 0x01, 0x02, 0x00, 0x34, 0x01, 0x02, 0x00, + 0x36, 0x01, 0x02, 0x00, 0x38, 0x01, 0x02, 0x00, 0x3a, 0x01, 0x02, 0x00, 0x3c, 0x01, 0x02, 0x00, + 0x3e, 0x01, 0x02, 0x00, 0x40, 0x01, 0x02, 0x00, 0x42, 0x01, 0x02, 0x00, 0x44, 0x01, 0x02, 0x00, + 0x46, 0x01, 0x02, 0x00, 0x48, 0x01, 0x02, 0x00, 0x4a, 0x01, 0x02, 0x00, 0x4c, 0x01, 0x02, 0x00, + 0x4e, 0x01, 0x02, 0x00, 0x50, 0x01, 0x02, 0x00, 0x52, 0x01, 0x02, 0x00, 0x54, 0x01, 0x02, 0x00, + 0x56, 0x01, 0x02, 0x00, 0x58, 0x01, 0x02, 0x00, 0x5a, 0x01, 0x02, 0x00, 0x5c, 0x01, 0x02, 0x00, + 0x5e, 0x01, 0x02, 0x00, 0x60, 0x01, 0x02, 0x00, 0x62, 0x01, 0x02, 0x00, 0x64, 0x01, 0x02, 0x00, + 0x66, 0x01, 0x02, 0x00, 0x68, 0x01, 0x02, 0x00, 0x6a, 0x01, 0x02, 0x00, 0x6c, 0x01, 0x02, 0x00, + 0x6e, 0x01, 0x02, 0x00, 0x70, 0x01, 0x02, 0x00, 0x72, 0x01, 0x02, 0x00, 0x74, 0x01, 0x02, 0x00, + 0x76, 0x01, 0x02, 0x00, 0x78, 0x01, 0x02, 0x00, 0x7a, 0x01, 0x02, 0x00, 0x7c, 0x01, 0x02, 0x00, + 0x7e, 0x01, 0x02, 0x00, 0x80, 0x01, 0x02, 0x00, 0x82, 0x01, 0x02, 0x00, 0x84, 0x01, 0x02, 0x00, + 0x86, 0x01, 0x02, 0x00, 0x88, 0x01, 0x02, 0x00, 0x8a, 0x01, 0x02, 0x00, 0x8c, 0x01, 0x02, 0x00, + 0x8e, 0x01, 0x02, 0x00, 0x90, 0x01, 0x02, 0x00, 0x92, 0x01, 0x02, 0x00, 0x94, 0x01, 0x02, 0x00, + 0x96, 0x01, 0x02, 0x00, 0x98, 0x01, 0x02, 0x00, 0x9a, 0x01, 0x02, 0x00, 0x9c, 0x01, 0x02, 0x00, + 0x9e, 0x01, 0x02, 0x00, 0xa0, 0x01, 0x02, 0x00, 0xa2, 0x01, 0x02, 0x00, 0xa4, 0x01, 0x02, 0x00, + 0xa6, 0x01, 0x02, 0x00, 0xa8, 0x01, 0x02, 0x00, 0xaa, 0x01, 0x02, 0x00, 0xac, 0x01, 0x02, 0x00, + 0xae, 0x01, 0x02, 0x00, 0xb0, 0x01, 0x02, 0x00, 0xb2, 0x01, 0x02, 0x00, 0xb4, 0x01, 0x02, 0x00, + 0xb6, 0x01, 0x02, 0x00, 0xb8, 0x01, 0x02, 0x00, 0xba, 0x01, 0x02, 0x00, 0xbc, 0x01, 0x02, 0x00, + 0xbe, 0x01, 0x02, 0x00, 0xc0, 0x01, 0x02, 0x00, 0xc2, 0x01, 0x02, 0x00, 0xc4, 0x01, 0x02, 0x00, + 0xc6, 0x01, 0x02, 0x00, 0xc8, 0x01, 0x02, 0x00, 0xca, 0x01, 0x02, 0x00, 0xcc, 0x01, 0x02, 0x00, + 0xce, 0x01, 0x02, 0x00, 0xd0, 0x01, 0x02, 0x00, 0xd2, 0x01, 0x02, 0x00, 0xd4, 0x01, 0x02, 0x00, + 0xd6, 0x01, 0x02, 0x00, 0xd8, 0x01, 0x02, 0x00, 0xda, 0x01, 0x02, 0x00, 0xdc, 0x01, 0x02, 0x00, + 0xde, 0x01, 0x02, 0x00, 0xe0, 0x01, 0x02, 0x00, 0xe2, 0x01, 0x02, 0x00, 0xe4, 0x01, 0x02, 0x00, + 0xe6, 0x01, 0x02, 0x00, 0xe8, 0x01, 0x02, 0x00, 0xea, 0x01, 0x02, 0x00, 0xec, 0x01, 0x02, 0x00, + 0xee, 0x01, 0x02, 0x00, 0xf0, 0x01, 0x02, 0x00, 0xf2, 0x01, 0x02, 0x00, 0xf4, 0x01, 0x02, 0x00, + + 0xf6, 0x01, 0x02, 0x00, 0xf8, 0x01, 0x02, 0x00, 0xfa, 0x01, 0x02, 0x00, 0xfc, 0x01, 0x02, 0x00, + 0xfe, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x04, 0x02, 0x02, 0x00, + 0x06, 0x02, 0x02, 0x00, 0x08, 0x02, 0x02, 0x00, 0x0a, 0x02, 0x02, 0x00, 0x0c, 0x02, 0x02, 0x00, + 0x0e, 0x02, 0x02, 0x00, 0x10, 0x02, 0x02, 0x00, 0x12, 0x02, 0x02, 0x00, 0x14, 0x02, 0x02, 0x00, + 0x16, 0x02, 0x02, 0x00, 0x18, 0x02, 0x02, 0x00, 0x1a, 0x02, 0x02, 0x00, 0x1c, 0x02, 0x02, 0x00, + 0x1e, 0x02, 0x02, 0x00, 0x20, 0x02, 0x02, 0x00, 0x22, 0x02, 0x02, 0x00, 0x24, 0x02, 0x02, 0x00, + 0x26, 0x02, 0x02, 0x00, 0x28, 0x02, 0x02, 0x00, 0x2a, 0x02, 0x02, 0x00, 0x2c, 0x02, 0x02, 0x00, + 0x2e, 0x02, 0x02, 0x00, 0x30, 0x02, 0x02, 0x00, 0x32, 0x02, 0x02, 0x00, 0x34, 0x02, 0x02, 0x00, + 0x36, 0x02, 0x02, 0x00, 0x38, 0x02, 0x02, 0x00, 0x3a, 0x02, 0x02, 0x00, 0x3c, 0x02, 0x02, 0x00, + 0x3e, 0x02, 0x02, 0x00, 0x40, 0x02, 0x02, 0x00, 0x42, 0x02, 0x02, 0x00, 0x44, 0x02, 0x02, 0x00, + 0x46, 0x02, 0x02, 0x00, 0x48, 0x02, 0x02, 0x00, 0x4a, 0x02, 0x02, 0x00, 0x4c, 0x02, 0x02, 0x00, + 0x4e, 0x02, 0x02, 0x00, 0x50, 0x02, 0x02, 0x00, 0x52, 0x02, 0x02, 0x00, 0x54, 0x02, 0x02, 0x00, + 0x56, 0x02, 0x02, 0x00, 0x58, 0x02, 0x02, 0x00, 0x5a, 0x02, 0x02, 0x00, 0x5c, 0x02, 0x02, 0x00, + 0x5e, 0x02, 0x02, 0x00, 0x60, 0x02, 0x02, 0x00, 0x62, 0x02, 0x02, 0x00, 0x64, 0x02, 0x02, 0x00, + 0x66, 0x02, 0x02, 0x00, 0x68, 0x02, 0x02, 0x00, 0x6a, 0x02, 0x02, 0x00, 0x6c, 0x02, 0x02, 0x00, + 0x6e, 0x02, 0x02, 0x00, 0x70, 0x02, 0x02, 0x00, 0x72, 0x02, 0x02, 0x00, 0x74, 0x02, 0x02, 0x00, + 0x76, 0x02, 0x02, 0x00, 0x78, 0x02, 0x02, 0x00, 0x7a, 0x02, 0x02, 0x00, 0x7c, 0x02, 0x02, 0x00, + 0x7e, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x00, 0x82, 0x02, 0x02, 0x00, 0x84, 0x02, 0x02, 0x00, + 0x86, 0x02, 0x02, 0x00, 0x88, 0x02, 0x02, 0x00, 0x8a, 0x02, 0x02, 0x00, 0x8c, 0x02, 0x02, 0x00, + 0x8e, 0x02, 0x02, 0x00, 0x90, 0x02, 0x02, 0x00, 0x92, 0x02, 0x02, 0x00, 0x94, 0x02, 0x02, 0x00, + 0x96, 0x02, 0x02, 0x00, 0x98, 0x02, 0x02, 0x00, 0x9a, 0x02, 0x02, 0x00, 0x9c, 0x02, 0x02, 0x00, + 0x9e, 0x02, 0x02, 0x00, 0xa0, 0x02, 0x02, 0x00, 0xa2, 0x02, 0x02, 0x00, 0xa4, 0x02, 0x02, 0x00, + 0xa6, 0x02, 0x02, 0x00, 0xa8, 0x02, 0x02, 0x00, 0xaa, 0x02, 0x02, 0x00, 0xac, 0x02, 0x02, 0x00, + 0xae, 0x02, 0x02, 0x00, 0xb0, 0x02, 0x02, 0x00, 0xb2, 0x02, 0x02, 0x00, 0xb4, 0x02, 0x02, 0x00, + 0xb6, 0x02, 0x02, 0x00, 0xb8, 0x02, 0x02, 0x00, 0xba, 0x02, 0x02, 0x00, 0xbc, 0x02, 0x02, 0x00, + 0xbe, 0x02, 0x02, 0x00, 0xc0, 0x02, 0x02, 0x00, 0xc2, 0x02, 0x02, 0x00, 0xc4, 0x02, 0x02, 0x00, + 0xc6, 0x02, 0x02, 0x00, 0xc8, 0x02, 0x02, 0x00, 0xca, 0x02, 0x02, 0x00, 0xcc, 0x02, 0x02, 0x00, + 0xce, 0x02, 0x02, 0x00, 0xd0, 0x02, 0x02, 0x00, 0xd2, 0x02, 0x02, 0x00, 0xd4, 0x02, 0x02, 0x00, + 0xd6, 0x02, 0x02, 0x00, 0xd8, 0x02, 0x02, 0x00, 0xda, 0x02, 0x02, 0x00, 0xdc, 0x02, 0x02, 0x00, + 0xde, 0x02, 0x02, 0x00, 0xe0, 0x02, 0x02, 0x00, 0xe2, 0x02, 0x02, 0x00, 0xe4, 0x02, 0x02, 0x00, + 0xe6, 0x02, 0x02, 0x00, 0xe8, 0x02, 0x02, 0x00, 0xea, 0x02, 0x02, 0x00, 0xec, 0x02, 0x02, 0x00, + 0xee, 0x02, 0x02, 0x00, 0xf0, 0x02, 0x02, 0x00, 0xf2, 0x02, 0x02, 0x00, 0xf4, 0x02, 0x02, 0x00, + + 0xf6, 0x02, 0x02, 0x00, 0xf8, 0x02, 0x02, 0x00, 0xfa, 0x02, 0x02, 0x00, 0xfc, 0x02, 0x02, 0x00, + 0xfe, 0x02, 0x02, 0x00, 0x00, 0x03, 0x02, 0x00, 0x02, 0x03, 0x02, 0x00, 0x04, 0x03, 0x02, 0x00, + 0x06, 0x03, 0x02, 0x00, 0x08, 0x03, 0x02, 0x00, 0x0a, 0x03, 0x02, 0x00, 0x0c, 0x03, 0x02, 0x00, + 0x0e, 0x03, 0x02, 0x00, 0x10, 0x03, 0x02, 0x00, 0x12, 0x03, 0x02, 0x00, 0x14, 0x03, 0x02, 0x00, + 0x16, 0x03, 0x02, 0x00, 0x18, 0x03, 0x02, 0x00, 0x1a, 0x03, 0x02, 0x00, 0x1c, 0x03, 0x02, 0x00, + 0x1e, 0x03, 0x02, 0x00, 0x20, 0x03, 0x02, 0x00, 0x22, 0x03, 0x02, 0x00, 0x24, 0x03, 0x02, 0x00, + 0x26, 0x03, 0x02, 0x00, 0x28, 0x03, 0x02, 0x00, 0x2a, 0x03, 0x02, 0x00, 0x2c, 0x03, 0x02, 0x00, + 0x2e, 0x03, 0x02, 0x00, 0x30, 0x03, 0x02, 0x00, 0x32, 0x03, 0x02, 0x00, 0x34, 0x03, 0x02, 0x00, + 0x36, 0x03, 0x02, 0x00, 0x38, 0x03, 0x02, 0x00, 0x3a, 0x03, 0x02, 0x00, 0x3c, 0x03, 0x02, 0x00, + 0x3e, 0x03, 0x02, 0x00, 0x40, 0x03, 0x02, 0x00, 0x42, 0x03, 0x02, 0x00, 0x44, 0x03, 0x02, 0x00, + 0x46, 0x03, 0x02, 0x00, 0x48, 0x03, 0x02, 0x00, 0x4a, 0x03, 0x02, 0x00, 0x4c, 0x03, 0x02, 0x00, + 0x4e, 0x03, 0x02, 0x00, 0x50, 0x03, 0x02, 0x00, 0x52, 0x03, 0x02, 0x00, 0x54, 0x03, 0x02, 0x00, + 0x56, 0x03, 0x02, 0x00, 0x58, 0x03, 0x02, 0x00, 0x5a, 0x03, 0x02, 0x00, 0x5c, 0x03, 0x02, 0x00, + 0x5e, 0x03, 0x02, 0x00, 0x60, 0x03, 0x02, 0x00, 0x62, 0x03, 0x02, 0x00, 0x64, 0x03, 0x02, 0x00, + 0x66, 0x03, 0x02, 0x00, 0x68, 0x03, 0x02, 0x00, 0x6a, 0x03, 0x02, 0x00, 0x6c, 0x03, 0x02, 0x00, + 0x6e, 0x03, 0x02, 0x00, 0x70, 0x03, 0x02, 0x00, 0x72, 0x03, 0x02, 0x00, 0x74, 0x03, 0x02, 0x00, + 0x76, 0x03, 0x02, 0x00, 0x78, 0x03, 0x02, 0x00, 0x7a, 0x03, 0x02, 0x00, 0x7c, 0x03, 0x02, 0x00, + 0x7e, 0x03, 0x02, 0x00, 0x80, 0x03, 0x02, 0x00, 0x82, 0x03, 0x02, 0x00, 0x84, 0x03, 0x02, 0x00, + 0x86, 0x03, 0x02, 0x00, 0x88, 0x03, 0x02, 0x00, 0x8a, 0x03, 0x02, 0x00, 0x8c, 0x03, 0x02, 0x00, + 0x8e, 0x03, 0x02, 0x00, 0x90, 0x03, 0x02, 0x00, 0x92, 0x03, 0x02, 0x00, 0x94, 0x03, 0x02, 0x00, + 0x96, 0x03, 0x02, 0x00, 0x98, 0x03, 0x02, 0x00, 0x9a, 0x03, 0x02, 0x00, 0x9c, 0x03, 0x02, 0x00, + 0x9e, 0x03, 0x02, 0x00, 0xa0, 0x03, 0x02, 0x00, 0xa2, 0x03, 0x02, 0x00, 0xa4, 0x03, 0x02, 0x00, + 0xa6, 0x03, 0x02, 0x00, 0xa8, 0x03, 0x02, 0x00, 0xaa, 0x03, 0x02, 0x00, 0xac, 0x03, 0x02, 0x00, + 0xae, 0x03, 0x02, 0x00, 0xb0, 0x03, 0x02, 0x00, 0xb2, 0x03, 0x02, 0x00, 0xb4, 0x03, 0x02, 0x00, + 0xb6, 0x03, 0x02, 0x00, 0xb8, 0x03, 0x02, 0x00, 0xba, 0x03, 0x02, 0x00, 0xbc, 0x03, 0x02, 0x00, + 0xbe, 0x03, 0x02, 0x00, 0xc0, 0x03, 0x02, 0x00, 0xc2, 0x03, 0x02, 0x00, 0xc4, 0x03, 0x02, 0x00, + 0xc6, 0x03, 0x02, 0x00, 0xc8, 0x03, 0x02, 0x00, 0xca, 0x03, 0x02, 0x00, 0xcc, 0x03, 0x02, 0x00, + 0xce, 0x03, 0x02, 0x00, 0xd0, 0x03, 0x02, 0x00, 0xd2, 0x03, 0x02, 0x00, 0xd4, 0x03, 0x02, 0x00, + 0xd6, 0x03, 0x02, 0x00, 0xd8, 0x03, 0x02, 0x00, 0xda, 0x03, 0x02, 0x00, 0xdc, 0x03, 0x02, 0x00, + 0xde, 0x03, 0x02, 0x00, 0xe0, 0x03, 0x02, 0x00, 0xe2, 0x03, 0x02, 0x00, 0xe4, 0x03, 0x02, 0x00, + 0xe6, 0x03, 0x02, 0x00, 0xe8, 0x03, 0x02, 0x00, 0xea, 0x03, 0x02, 0x00, 0xec, 0x03, 0x02, 0x00, + 0xee, 0x03, 0x02, 0x00, 0xf0, 0x03, 0x02, 0x00, 0xf2, 0x03, 0x02, 0x00, 0xf4, 0x03, 0x02, 0x00, + + 0xf6, 0x03, 0x02, 0x00, 0xf8, 0x03, 0x02, 0x00, 0xfa, 0x03, 0x02, 0x00, 0xfc, 0x03, 0x02, 0x00, + 0xfe, 0x03, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x06, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x02, 0x00, + 0x0e, 0x00, 0x02, 0x00, 0x10, 0x00, 0x02, 0x00, 0x12, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, + 0x16, 0x00, 0x02, 0x00, 0x18, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x02, 0x00, 0x1c, 0x00, 0x02, 0x00, + 0x1e, 0x00, 0x02, 0x00, 0x20, 0x00, 0x02, 0x00, 0x22, 0x00, 0x02, 0x00, 0x24, 0x00, 0x02, 0x00, + 0x26, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x2a, 0x00, 0x02, 0x00, 0x2c, 0x00, 0x02, 0x00, + 0x2e, 0x00, 0x02, 0x00, 0x30, 0x00, 0x02, 0x00, 0x32, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, + 0x36, 0x00, 0x02, 0x00, 0x38, 0x00, 0x02, 0x00, 0x3a, 0x00, 0x02, 0x00, 0x3c, 0x00, 0x02, 0x00, + 0x3e, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x42, 0x00, 0x02, 0x00, 0x44, 0x00, 0x02, 0x00, + 0x46, 0x00, 0x02, 0x00, 0x48, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x02, 0x00, 0x4c, 0x00, 0x02, 0x00, + 0x4e, 0x00, 0x02, 0x00, 0x50, 0x00, 0x02, 0x00, 0x52, 0x00, 0x02, 0x00, 0x54, 0x00, 0x02, 0x00, + 0x56, 0x00, 0x02, 0x00, 0x58, 0x00, 0x02, 0x00, 0x5a, 0x00, 0x02, 0x00, 0x5c, 0x00, 0x02, 0x00, + 0x5e, 0x00, 0x02, 0x00, 0x60, 0x00, 0x02, 0x00, 0x62, 0x00, 0x02, 0x00, 0x64, 0x00, 0x02, 0x00, + 0x66, 0x00, 0x02, 0x00, 0x68, 0x00, 0x02, 0x00, 0x6a, 0x00, 0x02, 0x00, 0x6c, 0x00, 0x02, 0x00, + 0x6e, 0x00, 0x02, 0x00, 0x70, 0x00, 0x02, 0x00, 0x72, 0x00, 0x02, 0x00, 0x74, 0x00, 0x02, 0x00, + 0x76, 0x00, 0x02, 0x00, 0x78, 0x00, 0x02, 0x00, 0x7a, 0x00, 0x02, 0x00, 0x7c, 0x00, 0x02, 0x00, + 0x7e, 0x00, 0x02, 0x00, 0x80, 0x00, 0x02, 0x00, 0x82, 0x00, 0x02, 0x00, 0x84, 0x00, 0x02, 0x00, + 0x86, 0x00, 0x02, 0x00, 0x88, 0x00, 0x02, 0x00, 0x8a, 0x00, 0x02, 0x00, 0x8c, 0x00, 0x02, 0x00, + 0x8e, 0x00, 0x02, 0x00, 0x90, 0x00, 0x02, 0x00, 0x92, 0x00, 0x02, 0x00, 0x94, 0x00, 0x02, 0x00, + 0x96, 0x00, 0x02, 0x00, 0x98, 0x00, 0x02, 0x00, 0x9a, 0x00, 0x02, 0x00, 0x9c, 0x00, 0x02, 0x00, + 0x9e, 0x00, 0x02, 0x00, 0xa0, 0x00, 0x02, 0x00, 0xa2, 0x00, 0x02, 0x00, 0xa4, 0x00, 0x02, 0x00, + 0xa6, 0x00, 0x02, 0x00, 0xa8, 0x00, 0x02, 0x00, 0xaa, 0x00, 0x02, 0x00, 0xac, 0x00, 0x02, 0x00, + 0xae, 0x00, 0x02, 0x00, 0xb0, 0x00, 0x02, 0x00, 0xb2, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x02, 0x00, + 0xb6, 0x00, 0x02, 0x00, 0xb8, 0x00, 0x02, 0x00, 0xba, 0x00, 0x02, 0x00, 0xbc, 0x00, 0x02, 0x00, + 0xbe, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x02, 0x00, 0xc2, 0x00, 0x02, 0x00, 0xc4, 0x00, 0x02, 0x00, + 0xc6, 0x00, 0x02, 0x00, 0xc8, 0x00, 0x02, 0x00, 0xca, 0x00, 0x02, 0x00, 0xcc, 0x00, 0x02, 0x00, + 0xce, 0x00, 0x02, 0x00, 0xd0, 0x00, 0x02, 0x00, 0xd2, 0x00, 0x02, 0x00, 0xd4, 0x00, 0x02, 0x00, + 0xd6, 0x00, 0x02, 0x00, 0xd8, 0x00, 0x02, 0x00, 0xda, 0x00, 0x02, 0x00, 0xdc, 0x00, 0x02, 0x00, + 0xde, 0x00, 0x02, 0x00, 0xe0, 0x00, 0x02, 0x00, 0xe2, 0x00, 0x02, 0x00, 0xe4, 0x00, 0x02, 0x00, + 0xe6, 0x00, 0x02, 0x00, 0xe8, 0x00, 0x02, 0x00, 0xea, 0x00, 0x02, 0x00, 0xec, 0x00, 0x02, 0x00, + 0xee, 0x00, 0x02, 0x00, 0xf0, 0x00, 0x02, 0x00, 0xf2, 0x00, 0x02, 0x00, 0xf4, 0x00, 0x02, 0x00, + + 0xf6, 0x00, 0x02, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xfa, 0x00, 0x02, 0x00, 0xfc, 0x00, 0x02, 0x00, + 0xfe, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x02, 0x01, 0x02, 0x00, 0x04, 0x01, 0x02, 0x00, + 0x06, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x0a, 0x01, 0x02, 0x00, 0x0c, 0x01, 0x02, 0x00, + 0x0e, 0x01, 0x02, 0x00, 0x10, 0x01, 0x02, 0x00, 0x12, 0x01, 0x02, 0x00, 0x14, 0x01, 0x02, 0x00, + 0x16, 0x01, 0x02, 0x00, 0x18, 0x01, 0x02, 0x00, 0x1a, 0x01, 0x02, 0x00, 0x1c, 0x01, 0x02, 0x00, + 0x1e, 0x01, 0x02, 0x00, 0x20, 0x01, 0x02, 0x00, 0x22, 0x01, 0x02, 0x00, 0x24, 0x01, 0x02, 0x00, + 0x26, 0x01, 0x02, 0x00, 0x28, 0x01, 0x02, 0x00, 0x2a, 0x01, 0x02, 0x00, 0x2c, 0x01, 0x02, 0x00, + 0x2e, 0x01, 0x02, 0x00, 0x30, 0x01, 0x02, 0x00, 0x32, 0x01, 0x02, 0x00, 0x34, 0x01, 0x02, 0x00, + 0x36, 0x01, 0x02, 0x00, 0x38, 0x01, 0x02, 0x00, 0x3a, 0x01, 0x02, 0x00, 0x3c, 0x01, 0x02, 0x00, + 0x3e, 0x01, 0x02, 0x00, 0x40, 0x01, 0x02, 0x00, 0x42, 0x01, 0x02, 0x00, 0x44, 0x01, 0x02, 0x00, + 0x46, 0x01, 0x02, 0x00, 0x48, 0x01, 0x02, 0x00, 0x4a, 0x01, 0x02, 0x00, 0x4c, 0x01, 0x02, 0x00, + 0x4e, 0x01, 0x02, 0x00, 0x50, 0x01, 0x02, 0x00, 0x52, 0x01, 0x02, 0x00, 0x54, 0x01, 0x02, 0x00, + 0x56, 0x01, 0x02, 0x00, 0x58, 0x01, 0x02, 0x00, 0x5a, 0x01, 0x02, 0x00, 0x5c, 0x01, 0x02, 0x00, + 0x5e, 0x01, 0x02, 0x00, 0x60, 0x01, 0x02, 0x00, 0x62, 0x01, 0x02, 0x00, 0x64, 0x01, 0x02, 0x00, + 0x66, 0x01, 0x02, 0x00, 0x68, 0x01, 0x02, 0x00, 0x6a, 0x01, 0x02, 0x00, 0x6c, 0x01, 0x02, 0x00, + 0x6e, 0x01, 0x02, 0x00, 0x70, 0x01, 0x02, 0x00, 0x72, 0x01, 0x02, 0x00, 0x74, 0x01, 0x02, 0x00, + 0x76, 0x01, 0x02, 0x00, 0x78, 0x01, 0x02, 0x00, 0x7a, 0x01, 0x02, 0x00, 0x7c, 0x01, 0x02, 0x00, + 0x7e, 0x01, 0x02, 0x00, 0x80, 0x01, 0x02, 0x00, 0x82, 0x01, 0x02, 0x00, 0x84, 0x01, 0x02, 0x00, + 0x86, 0x01, 0x02, 0x00, 0x88, 0x01, 0x02, 0x00, 0x8a, 0x01, 0x02, 0x00, 0x8c, 0x01, 0x02, 0x00, + 0x8e, 0x01, 0x02, 0x00, 0x90, 0x01, 0x02, 0x00, 0x92, 0x01, 0x02, 0x00, 0x94, 0x01, 0x02, 0x00, + 0x96, 0x01, 0x02, 0x00, 0x98, 0x01, 0x02, 0x00, 0x9a, 0x01, 0x02, 0x00, 0x9c, 0x01, 0x02, 0x00, + 0x9e, 0x01, 0x02, 0x00, 0xa0, 0x01, 0x02, 0x00, 0xa2, 0x01, 0x02, 0x00, 0xa4, 0x01, 0x02, 0x00, + 0xa6, 0x01, 0x02, 0x00, 0xa8, 0x01, 0x02, 0x00, 0xaa, 0x01, 0x02, 0x00, 0xac, 0x01, 0x02, 0x00, + 0xae, 0x01, 0x02, 0x00, 0xb0, 0x01, 0x02, 0x00, 0xb2, 0x01, 0x02, 0x00, 0xb4, 0x01, 0x02, 0x00, + 0xb6, 0x01, 0x02, 0x00, 0xb8, 0x01, 0x02, 0x00, 0xba, 0x01, 0x02, 0x00, 0xbc, 0x01, 0x02, 0x00, + 0xbe, 0x01, 0x02, 0x00, 0xc0, 0x01, 0x02, 0x00, 0xc2, 0x01, 0x02, 0x00, 0xc4, 0x01, 0x02, 0x00, + 0xc6, 0x01, 0x02, 0x00, 0xc8, 0x01, 0x02, 0x00, 0xca, 0x01, 0x02, 0x00, 0xcc, 0x01, 0x02, 0x00, + 0xce, 0x01, 0x02, 0x00, 0xd0, 0x01, 0x02, 0x00, 0xd2, 0x01, 0x02, 0x00, 0xd4, 0x01, 0x02, 0x00, + 0xd6, 0x01, 0x02, 0x00, 0xd8, 0x01, 0x02, 0x00, 0xda, 0x01, 0x02, 0x00, 0xdc, 0x01, 0x02, 0x00, + 0xde, 0x01, 0x02, 0x00, 0xe0, 0x01, 0x02, 0x00, 0xe2, 0x01, 0x02, 0x00, 0xe4, 0x01, 0x02, 0x00, + 0xe6, 0x01, 0x02, 0x00, 0xe8, 0x01, 0x02, 0x00, 0xea, 0x01, 0x02, 0x00, 0xec, 0x01, 0x02, 0x00, + 0xee, 0x01, 0x02, 0x00, 0xf0, 0x01, 0x02, 0x00, 0xf2, 0x01, 0x02, 0x00, 0xf4, 0x01, 0x02, 0x00, + + 0xf6, 0x01, 0x02, 0x00, 0xf8, 0x01, 0x02, 0x00, 0xfa, 0x01, 0x02, 0x00, 0xfc, 0x01, 0x02, 0x00, + 0xfe, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x04, 0x02, 0x02, 0x00, + 0x06, 0x02, 0x02, 0x00, 0x08, 0x02, 0x02, 0x00, 0x0a, 0x02, 0x02, 0x00, 0x0c, 0x02, 0x02, 0x00, + 0x0e, 0x02, 0x02, 0x00, 0x10, 0x02, 0x02, 0x00, 0x12, 0x02, 0x02, 0x00, 0x14, 0x02, 0x02, 0x00, + 0x16, 0x02, 0x02, 0x00, 0x18, 0x02, 0x02, 0x00, 0x1a, 0x02, 0x02, 0x00, 0x1c, 0x02, 0x02, 0x00, + 0x1e, 0x02, 0x02, 0x00, 0x20, 0x02, 0x02, 0x00, 0x22, 0x02, 0x02, 0x00, 0x24, 0x02, 0x02, 0x00, + 0x26, 0x02, 0x02, 0x00, 0x28, 0x02, 0x02, 0x00, 0x2a, 0x02, 0x02, 0x00, 0x2c, 0x02, 0x02, 0x00, + 0x2e, 0x02, 0x02, 0x00, 0x30, 0x02, 0x02, 0x00, 0x32, 0x02, 0x02, 0x00, 0x34, 0x02, 0x02, 0x00, + 0x36, 0x02, 0x02, 0x00, 0x38, 0x02, 0x02, 0x00, 0x3a, 0x02, 0x02, 0x00, 0x3c, 0x02, 0x02, 0x00, + 0x3e, 0x02, 0x02, 0x00, 0x40, 0x02, 0x02, 0x00, 0x42, 0x02, 0x02, 0x00, 0x44, 0x02, 0x02, 0x00, + 0x46, 0x02, 0x02, 0x00, 0x48, 0x02, 0x02, 0x00, 0x4a, 0x02, 0x02, 0x00, 0x4c, 0x02, 0x02, 0x00, + 0x4e, 0x02, 0x02, 0x00, 0x50, 0x02, 0x02, 0x00, 0x52, 0x02, 0x02, 0x00, 0x54, 0x02, 0x02, 0x00, + 0x56, 0x02, 0x02, 0x00, 0x58, 0x02, 0x02, 0x00, 0x5a, 0x02, 0x02, 0x00, 0x5c, 0x02, 0x02, 0x00, + 0x5e, 0x02, 0x02, 0x00, 0x60, 0x02, 0x02, 0x00, 0x62, 0x02, 0x02, 0x00, 0x64, 0x02, 0x02, 0x00, + 0x66, 0x02, 0x02, 0x00, 0x68, 0x02, 0x02, 0x00, 0x6a, 0x02, 0x02, 0x00, 0x6c, 0x02, 0x02, 0x00, + 0x6e, 0x02, 0x02, 0x00, 0x70, 0x02, 0x02, 0x00, 0x72, 0x02, 0x02, 0x00, 0x74, 0x02, 0x02, 0x00, + 0x76, 0x02, 0x02, 0x00, 0x78, 0x02, 0x02, 0x00, 0x7a, 0x02, 0x02, 0x00, 0x7c, 0x02, 0x02, 0x00, + 0x7e, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x00, 0x82, 0x02, 0x02, 0x00, 0x84, 0x02, 0x02, 0x00, + 0x86, 0x02, 0x02, 0x00, 0x88, 0x02, 0x02, 0x00, 0x8a, 0x02, 0x02, 0x00, 0x8c, 0x02, 0x02, 0x00, + 0x8e, 0x02, 0x02, 0x00, 0x90, 0x02, 0x02, 0x00, 0x92, 0x02, 0x02, 0x00, 0x94, 0x02, 0x02, 0x00, + 0x96, 0x02, 0x02, 0x00, 0x98, 0x02, 0x02, 0x00, 0x9a, 0x02, 0x02, 0x00, 0x9c, 0x02, 0x02, 0x00, + 0x9e, 0x02, 0x02, 0x00, 0xa0, 0x02, 0x02, 0x00, 0xa2, 0x02, 0x02, 0x00, 0xa4, 0x02, 0x02, 0x00, + 0xa6, 0x02, 0x02, 0x00, 0xa8, 0x02, 0x02, 0x00, 0xaa, 0x02, 0x02, 0x00, 0xac, 0x02, 0x02, 0x00, + 0xae, 0x02, 0x02, 0x00, 0xb0, 0x02, 0x02, 0x00, 0xb2, 0x02, 0x02, 0x00, 0xb4, 0x02, 0x02, 0x00, + 0xb6, 0x02, 0x02, 0x00, 0xb8, 0x02, 0x02, 0x00, 0xba, 0x02, 0x02, 0x00, 0xbc, 0x02, 0x02, 0x00, + 0xbe, 0x02, 0x02, 0x00, 0xc0, 0x02, 0x02, 0x00, 0xc2, 0x02, 0x02, 0x00, 0xc4, 0x02, 0x02, 0x00, + 0xc6, 0x02, 0x02, 0x00, 0xc8, 0x02, 0x02, 0x00, 0xca, 0x02, 0x02, 0x00, 0xcc, 0x02, 0x02, 0x00, + 0xce, 0x02, 0x02, 0x00, 0xd0, 0x02, 0x02, 0x00, 0xd2, 0x02, 0x02, 0x00, 0xd4, 0x02, 0x02, 0x00, + 0xd6, 0x02, 0x02, 0x00, 0xd8, 0x02, 0x02, 0x00, 0xda, 0x02, 0x02, 0x00, 0xdc, 0x02, 0x02, 0x00, + 0xde, 0x02, 0x02, 0x00, 0xe0, 0x02, 0x02, 0x00, 0xe2, 0x02, 0x02, 0x00, 0xe4, 0x02, 0x02, 0x00, + 0xe6, 0x02, 0x02, 0x00, 0xe8, 0x02, 0x02, 0x00, 0xea, 0x02, 0x02, 0x00, 0xec, 0x02, 0x02, 0x00, + 0xee, 0x02, 0x02, 0x00, 0xf0, 0x02, 0x02, 0x00, 0xf2, 0x02, 0x02, 0x00, 0xf4, 0x02, 0x02, 0x00, + + 0xf6, 0x02, 0x02, 0x00, 0xf8, 0x02, 0x02, 0x00, 0xfa, 0x02, 0x02, 0x00, 0xfc, 0x02, 0x02, 0x00, + 0xfe, 0x02, 0x02, 0x00, 0x00, 0x03, 0x02, 0x00, 0x02, 0x03, 0x02, 0x00, 0x04, 0x03, 0x02, 0x00, + 0x06, 0x03, 0x02, 0x00, 0x08, 0x03, 0x02, 0x00, 0x0a, 0x03, 0x02, 0x00, 0x0c, 0x03, 0x02, 0x00, + 0x0e, 0x03, 0x02, 0x00, 0x10, 0x03, 0x02, 0x00, 0x12, 0x03, 0x02, 0x00, 0x14, 0x03, 0x02, 0x00, + 0x16, 0x03, 0x02, 0x00, 0x18, 0x03, 0x02, 0x00, 0x1a, 0x03, 0x02, 0x00, 0x1c, 0x03, 0x02, 0x00, + 0x1e, 0x03, 0x02, 0x00, 0x20, 0x03, 0x02, 0x00, 0x22, 0x03, 0x02, 0x00, 0x24, 0x03, 0x02, 0x00, + 0x26, 0x03, 0x02, 0x00, 0x28, 0x03, 0x02, 0x00, 0x2a, 0x03, 0x02, 0x00, 0x2c, 0x03, 0x02, 0x00, + 0x2e, 0x03, 0x02, 0x00, 0x30, 0x03, 0x02, 0x00, 0x32, 0x03, 0x02, 0x00, 0x34, 0x03, 0x02, 0x00, + 0x36, 0x03, 0x02, 0x00, 0x38, 0x03, 0x02, 0x00, 0x3a, 0x03, 0x02, 0x00, 0x3c, 0x03, 0x02, 0x00, + 0x3e, 0x03, 0x02, 0x00, 0x40, 0x03, 0x02, 0x00, 0x42, 0x03, 0x02, 0x00, 0x44, 0x03, 0x02, 0x00, + 0x46, 0x03, 0x02, 0x00, 0x48, 0x03, 0x02, 0x00, 0x4a, 0x03, 0x02, 0x00, 0x4c, 0x03, 0x02, 0x00, + 0x4e, 0x03, 0x02, 0x00, 0x50, 0x03, 0x02, 0x00, 0x52, 0x03, 0x02, 0x00, 0x54, 0x03, 0x02, 0x00, + 0x56, 0x03, 0x02, 0x00, 0x58, 0x03, 0x02, 0x00, 0x5a, 0x03, 0x02, 0x00, 0x5c, 0x03, 0x02, 0x00, + 0x5e, 0x03, 0x02, 0x00, 0x60, 0x03, 0x02, 0x00, 0x62, 0x03, 0x02, 0x00, 0x64, 0x03, 0x02, 0x00, + 0x66, 0x03, 0x02, 0x00, 0x68, 0x03, 0x02, 0x00, 0x6a, 0x03, 0x02, 0x00, 0x6c, 0x03, 0x02, 0x00, + 0x6e, 0x03, 0x02, 0x00, 0x70, 0x03, 0x02, 0x00, 0x72, 0x03, 0x02, 0x00, 0x74, 0x03, 0x02, 0x00, + 0x76, 0x03, 0x02, 0x00, 0x78, 0x03, 0x02, 0x00, 0x7a, 0x03, 0x02, 0x00, 0x7c, 0x03, 0x02, 0x00, + 0x7e, 0x03, 0x02, 0x00, 0x80, 0x03, 0x02, 0x00, 0x82, 0x03, 0x02, 0x00, 0x84, 0x03, 0x02, 0x00, + 0x86, 0x03, 0x02, 0x00, 0x88, 0x03, 0x02, 0x00, 0x8a, 0x03, 0x02, 0x00, 0x8c, 0x03, 0x02, 0x00, + 0x8e, 0x03, 0x02, 0x00, 0x90, 0x03, 0x02, 0x00, 0x92, 0x03, 0x02, 0x00, 0x94, 0x03, 0x02, 0x00, + 0x96, 0x03, 0x02, 0x00, 0x98, 0x03, 0x02, 0x00, 0x9a, 0x03, 0x02, 0x00, 0x9c, 0x03, 0x02, 0x00, + 0x9e, 0x03, 0x02, 0x00, 0xa0, 0x03, 0x02, 0x00, 0xa2, 0x03, 0x02, 0x00, 0xa4, 0x03, 0x02, 0x00, + 0xa6, 0x03, 0x02, 0x00, 0xa8, 0x03, 0x02, 0x00, 0xaa, 0x03, 0x02, 0x00, 0xac, 0x03, 0x02, 0x00, + 0xae, 0x03, 0x02, 0x00, 0xb0, 0x03, 0x02, 0x00, 0xb2, 0x03, 0x02, 0x00, 0xb4, 0x03, 0x02, 0x00, + 0xb6, 0x03, 0x02, 0x00, 0xb8, 0x03, 0x02, 0x00, 0xba, 0x03, 0x02, 0x00, 0xbc, 0x03, 0x02, 0x00, + 0xbe, 0x03, 0x02, 0x00, 0xc0, 0x03, 0x02, 0x00, 0xc2, 0x03, 0x02, 0x00, 0xc4, 0x03, 0x02, 0x00, + 0xc6, 0x03, 0x02, 0x00, 0xc8, 0x03, 0x02, 0x00, 0xca, 0x03, 0x02, 0x00, 0xcc, 0x03, 0x02, 0x00, + 0xce, 0x03, 0x02, 0x00, 0xd0, 0x03, 0x02, 0x00, 0xd2, 0x03, 0x02, 0x00, 0xd4, 0x03, 0x02, 0x00, + 0xd6, 0x03, 0x02, 0x00, 0xd8, 0x03, 0x02, 0x00, 0xda, 0x03, 0x02, 0x00, 0xdc, 0x03, 0x02, 0x00, + 0xde, 0x03, 0x02, 0x00, 0xe0, 0x03, 0x02, 0x00, 0xe2, 0x03, 0x02, 0x00, 0xe4, 0x03, 0x02, 0x00, + 0xe6, 0x03, 0x02, 0x00, 0xe8, 0x03, 0x02, 0x00, 0xea, 0x03, 0x02, 0x00, 0xec, 0x03, 0x02, 0x00, + 0xee, 0x03, 0x02, 0x00, 0xf0, 0x03, 0x02, 0x00, 0xf2, 0x03, 0x02, 0x00, 0xf4, 0x03, 0x02, 0x00, + + 0xf6, 0x03, 0x02, 0x00, 0xf8, 0x03, 0x02, 0x00, 0xfa, 0x03, 0x02, 0x00, 0xfc, 0x03, 0x02, 0x00, + 0xfe, 0x03, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x06, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x02, 0x00, + 0x0e, 0x00, 0x02, 0x00, 0x10, 0x00, 0x02, 0x00, 0x12, 0x00, 0x02, 0x00, 0x14, 0x00, 0x02, 0x00, + 0x16, 0x00, 0x02, 0x00, 0x18, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x02, 0x00, 0x1c, 0x00, 0x02, 0x00, + 0x1e, 0x00, 0x02, 0x00, 0x20, 0x00, 0x02, 0x00, 0x22, 0x00, 0x02, 0x00, 0x24, 0x00, 0x02, 0x00, + 0x26, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x2a, 0x00, 0x02, 0x00, 0x2c, 0x00, 0x02, 0x00, + 0x2e, 0x00, 0x02, 0x00, 0x30, 0x00, 0x02, 0x00, 0x32, 0x00, 0x02, 0x00, 0x34, 0x00, 0x02, 0x00, + 0x36, 0x00, 0x02, 0x00, 0x38, 0x00, 0x02, 0x00, 0x3a, 0x00, 0x02, 0x00, 0x3c, 0x00, 0x02, 0x00, + 0x3e, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x42, 0x00, 0x02, 0x00, 0x44, 0x00, 0x02, 0x00, + 0x46, 0x00, 0x02, 0x00, 0x48, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x02, 0x00, 0x4c, 0x00, 0x02, 0x00, + 0x4e, 0x00, 0x02, 0x00, 0x50, 0x00, 0x02, 0x00, 0x52, 0x00, 0x02, 0x00, 0x54, 0x00, 0x02, 0x00, + 0x56, 0x00, 0x02, 0x00, 0x58, 0x00, 0x02, 0x00, 0x5a, 0x00, 0x02, 0x00, 0x5c, 0x00, 0x02, 0x00, + 0x5e, 0x00, 0x02, 0x00, 0x60, 0x00, 0x02, 0x00, 0x62, 0x00, 0x02, 0x00, 0x64, 0x00, 0x02, 0x00, + 0x66, 0x00, 0x02, 0x00, 0x68, 0x00, 0x02, 0x00, 0x6a, 0x00, 0x02, 0x00, 0x6c, 0x00, 0x02, 0x00, + 0x6e, 0x00, 0x02, 0x00, 0x70, 0x00, 0x02, 0x00, 0x72, 0x00, 0x02, 0x00, 0x74, 0x00, 0x02, 0x00, + 0x76, 0x00, 0x02, 0x00, 0x78, 0x00, 0x02, 0x00, 0x7a, 0x00, 0x02, 0x00, 0x7c, 0x00, 0x02, 0x00, + 0x7e, 0x00, 0x02, 0x00, 0x80, 0x00, 0x02, 0x00, 0x82, 0x00, 0x02, 0x00, 0x84, 0x00, 0x02, 0x00, + 0x86, 0x00, 0x02, 0x00, 0x88, 0x00, 0x02, 0x00, 0x8a, 0x00, 0x02, 0x00, 0x8c, 0x00, 0x02, 0x00, + 0x8e, 0x00, 0x02, 0x00, 0x90, 0x00, 0x02, 0x00, 0x92, 0x00, 0x02, 0x00, 0x94, 0x00, 0x02, 0x00, + 0x96, 0x00, 0x02, 0x00, 0x98, 0x00, 0x02, 0x00, 0x9a, 0x00, 0x02, 0x00, 0x9c, 0x00, 0x02, 0x00, + 0x9e, 0x00, 0x02, 0x00, 0xa0, 0x00, 0x02, 0x00, 0xa2, 0x00, 0x02, 0x00, 0xa4, 0x00, 0x02, 0x00, + 0xa6, 0x00, 0x02, 0x00, 0xa8, 0x00, 0x02, 0x00, 0xaa, 0x00, 0x02, 0x00, 0xac, 0x00, 0x02, 0x00, + 0xae, 0x00, 0x02, 0x00, 0xb0, 0x00, 0x02, 0x00, 0xb2, 0x00, 0x02, 0x00, 0xb4, 0x00, 0x02, 0x00, + 0xb6, 0x00, 0x02, 0x00, 0xb8, 0x00, 0x02, 0x00, 0xba, 0x00, 0x02, 0x00, 0xbc, 0x00, 0x02, 0x00, + 0xbe, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x02, 0x00, 0xc2, 0x00, 0x02, 0x00, 0xc4, 0x00, 0x02, 0x00, + 0xc6, 0x00, 0x02, 0x00, 0xc8, 0x00, 0x02, 0x00, 0xca, 0x00, 0x02, 0x00, 0xcc, 0x00, 0x02, 0x00, + 0xce, 0x00, 0x02, 0x00, 0xd0, 0x00, 0x02, 0x00, 0xd2, 0x00, 0x02, 0x00, 0xd4, 0x00, 0x02, 0x00, + 0xd6, 0x00, 0x02, 0x00, 0xd8, 0x00, 0x02, 0x00, 0xda, 0x00, 0x02, 0x00, 0xdc, 0x00, 0x02, 0x00, + 0xde, 0x00, 0x02, 0x00, 0xe0, 0x00, 0x02, 0x00, 0xe2, 0x00, 0x02, 0x00, 0xe4, 0x00, 0x02, 0x00, + 0xe6, 0x00, 0x02, 0x00, 0xe8, 0x00, 0x02, 0x00, 0xea, 0x00, 0x02, 0x00, 0xec, 0x00, 0x02, 0x00, + 0xee, 0x00, 0x02, 0x00, 0xf0, 0x00, 0x02, 0x00, 0xf2, 0x00, 0x02, 0x00, 0xf4, 0x00, 0x02, 0x00, + + 0xf6, 0x00, 0x02, 0x00, 0xf8, 0x00, 0x02, 0x00, 0xfa, 0x00, 0x02, 0x00, 0xfc, 0x00, 0x02, 0x00, + 0xfe, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x02, 0x01, 0x02, 0x00, 0x04, 0x01, 0x02, 0x00, + 0x06, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x0a, 0x01, 0x02, 0x00, 0x0c, 0x01, 0x02, 0x00, + 0x0e, 0x01, 0x02, 0x00, 0x10, 0x01, 0x02, 0x00, 0x12, 0x01, 0x02, 0x00, 0x14, 0x01, 0x02, 0x00, + 0x16, 0x01, 0x02, 0x00, 0x18, 0x01, 0x02, 0x00, 0x1a, 0x01, 0x02, 0x00, 0x1c, 0x01, 0x02, 0x00, + 0x1e, 0x01, 0x02, 0x00, 0x20, 0x01, 0x02, 0x00, 0x22, 0x01, 0x02, 0x00, 0x24, 0x01, 0x02, 0x00, + 0x26, 0x01, 0x02, 0x00, 0x28, 0x01, 0x02, 0x00, 0x2a, 0x01, 0x02, 0x00, 0x2c, 0x01, 0x02, 0x00, + 0x2e, 0x01, 0x02, 0x00, 0x30, 0x01, 0x02, 0x00, 0x32, 0x01, 0x02, 0x00, 0x34, 0x01, 0x02, 0x00, + 0x36, 0x01, 0x02, 0x00, 0x38, 0x01, 0x02, 0x00, 0x3a, 0x01, 0x02, 0x00, 0x3c, 0x01, 0x02, 0x00, + 0x3e, 0x01, 0x02, 0x00, 0x40, 0x01, 0x02, 0x00, 0x42, 0x01, 0x02, 0x00, 0x44, 0x01, 0x02, 0x00, + 0x46, 0x01, 0x02, 0x00, 0x48, 0x01, 0x02, 0x00, 0x4a, 0x01, 0x02, 0x00, 0x4c, 0x01, 0x02, 0x00, + 0x4e, 0x01, 0x02, 0x00, 0x50, 0x01, 0x02, 0x00, 0x52, 0x01, 0x02, 0x00, 0x54, 0x01, 0x02, 0x00, + 0x56, 0x01, 0x02, 0x00, 0x58, 0x01, 0x02, 0x00, 0x5a, 0x01, 0x02, 0x00, 0x5c, 0x01, 0x02, 0x00, + 0x5e, 0x01, 0x02, 0x00, 0x60, 0x01, 0x02, 0x00, 0x62, 0x01, 0x02, 0x00, 0x64, 0x01, 0x02, 0x00, + 0x66, 0x01, 0x02, 0x00, 0x68, 0x01, 0x02, 0x00, 0x6a, 0x01, 0x02, 0x00, 0x6c, 0x01, 0x02, 0x00, + 0x6e, 0x01, 0x02, 0x00, 0x70, 0x01, 0x02, 0x00, 0x72, 0x01, 0x02, 0x00, 0x74, 0x01, 0x02, 0x00, + 0x76, 0x01, 0x02, 0x00, 0x78, 0x01, 0x02, 0x00, 0x7a, 0x01, 0x02, 0x00, 0x7c, 0x01, 0x02, 0x00, + 0x7e, 0x01, 0x02, 0x00, 0x80, 0x01, 0x02, 0x00, 0x82, 0x01, 0x02, 0x00, 0x84, 0x01, 0x02, 0x00, + 0x86, 0x01, 0x02, 0x00, 0x88, 0x01, 0x02, 0x00, 0x8a, 0x01, 0x02, 0x00, 0x8c, 0x01, 0x02, 0x00, + 0x8e, 0x01, 0x02, 0x00, 0x90, 0x01, 0x02, 0x00, 0x92, 0x01, 0x02, 0x00, 0x94, 0x01, 0x02, 0x00, + 0x96, 0x01, 0x02, 0x00, 0x98, 0x01, 0x02, 0x00, 0x9a, 0x01, 0x02, 0x00, 0x9c, 0x01, 0x02, 0x00, + 0x9e, 0x01, 0x02, 0x00, 0xa0, 0x01, 0x02, 0x00, 0xa2, 0x01, 0x02, 0x00, 0xa4, 0x01, 0x02, 0x00, + 0xa6, 0x01, 0x02, 0x00, 0xa8, 0x01, 0x02, 0x00, 0xaa, 0x01, 0x02, 0x00, 0xac, 0x01, 0x02, 0x00, + 0xae, 0x01, 0x02, 0x00, 0xb0, 0x01, 0x02, 0x00, 0xb2, 0x01, 0x02, 0x00, 0xb4, 0x01, 0x02, 0x00, + 0xb6, 0x01, 0x02, 0x00, 0xb8, 0x01, 0x02, 0x00, 0xba, 0x01, 0x02, 0x00, 0xbc, 0x01, 0x02, 0x00, + 0xbe, 0x01, 0x02, 0x00, 0xc0, 0x01, 0x02, 0x00, 0xc2, 0x01, 0x02, 0x00, 0xc4, 0x01, 0x02, 0x00, + 0xc6, 0x01, 0x02, 0x00, 0xc8, 0x01, 0x02, 0x00, 0xca, 0x01, 0x02, 0x00, 0xcc, 0x01, 0x02, 0x00, + 0xce, 0x01, 0x02, 0x00, 0xd0, 0x01, 0x02, 0x00, 0xd2, 0x01, 0x02, 0x00, 0xd4, 0x01, 0x02, 0x00, + 0xd6, 0x01, 0x02, 0x00, 0xd8, 0x01, 0x02, 0x00, 0xda, 0x01, 0x02, 0x00, 0xdc, 0x01, 0x02, 0x00, + 0xde, 0x01, 0x02, 0x00, 0xe0, 0x01, 0x02, 0x00, 0xe2, 0x01, 0x02, 0x00, 0xe4, 0x01, 0x02, 0x00, + 0xe6, 0x01, 0x02, 0x00, 0xe8, 0x01, 0x02, 0x00, 0xea, 0x01, 0x02, 0x00, 0xec, 0x01, 0x02, 0x00, + 0xee, 0x01, 0x02, 0x00, 0xf0, 0x01, 0x02, 0x00, 0xf2, 0x01, 0x02, 0x00, 0xf4, 0x01, 0x02, 0x00, + + 0xf6, 0x01, 0x02, 0x00, 0xf8, 0x01, 0x02, 0x00, 0xfa, 0x01, 0x02, 0x00, 0xfc, 0x01, 0x02, 0x00, + 0xfe, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x04, 0x02, 0x02, 0x00, + 0x06, 0x02, 0x02, 0x00, 0x08, 0x02, 0x02, 0x00, 0x0a, 0x02, 0x02, 0x00, 0x0c, 0x02, 0x02, 0x00, + 0x0e, 0x02, 0x02, 0x00, 0x10, 0x02, 0x02, 0x00, 0x12, 0x02, 0x02, 0x00, 0x14, 0x02, 0x02, 0x00, + 0x16, 0x02, 0x02, 0x00, 0x18, 0x02, 0x02, 0x00, 0x1a, 0x02, 0x02, 0x00, 0x1c, 0x02, 0x02, 0x00, + 0x1e, 0x02, 0x02, 0x00, 0x20, 0x02, 0x02, 0x00, 0x22, 0x02, 0x02, 0x00, 0x24, 0x02, 0x02, 0x00, + 0x26, 0x02, 0x02, 0x00, 0x28, 0x02, 0x02, 0x00, 0x2a, 0x02, 0x02, 0x00, 0x2c, 0x02, 0x02, 0x00, + 0x2e, 0x02, 0x02, 0x00, 0x30, 0x02, 0x02, 0x00, 0x32, 0x02, 0x02, 0x00, 0x34, 0x02, 0x02, 0x00, + 0x36, 0x02, 0x02, 0x00, 0x38, 0x02, 0x02, 0x00, 0x3a, 0x02, 0x02, 0x00, 0x3c, 0x02, 0x02, 0x00, + 0x3e, 0x02, 0x02, 0x00, 0x40, 0x02, 0x02, 0x00, 0x42, 0x02, 0x02, 0x00, 0x44, 0x02, 0x02, 0x00, + 0x46, 0x02, 0x02, 0x00, 0x48, 0x02, 0x02, 0x00, 0x4a, 0x02, 0x02, 0x00, 0x4c, 0x02, 0x02, 0x00, + 0x4e, 0x02, 0x02, 0x00, 0x50, 0x02, 0x02, 0x00, 0x52, 0x02, 0x02, 0x00, 0x54, 0x02, 0x02, 0x00, + 0x56, 0x02, 0x02, 0x00, 0x58, 0x02, 0x02, 0x00, 0x5a, 0x02, 0x02, 0x00, 0x5c, 0x02, 0x02, 0x00, + 0x5e, 0x02, 0x02, 0x00, 0x60, 0x02, 0x02, 0x00, 0x62, 0x02, 0x02, 0x00, 0x64, 0x02, 0x02, 0x00, + 0x66, 0x02, 0x02, 0x00, 0x68, 0x02, 0x02, 0x00, 0x6a, 0x02, 0x02, 0x00, 0x6c, 0x02, 0x02, 0x00, + 0x6e, 0x02, 0x02, 0x00, 0x70, 0x02, 0x02, 0x00, 0x72, 0x02, 0x02, 0x00, 0x74, 0x02, 0x02, 0x00, + 0x76, 0x02, 0x02, 0x00, 0x78, 0x02, 0x02, 0x00, 0x7a, 0x02, 0x02, 0x00, 0x7c, 0x02, 0x02, 0x00, + 0x7e, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x00, 0x82, 0x02, 0x02, 0x00, 0x84, 0x02, 0x02, 0x00, + 0x86, 0x02, 0x02, 0x00, 0x88, 0x02, 0x02, 0x00, 0x8a, 0x02, 0x02, 0x00, 0x8c, 0x02, 0x02, 0x00, + 0x8e, 0x02, 0x02, 0x00, 0x90, 0x02, 0x02, 0x00, 0x92, 0x02, 0x02, 0x00, 0x94, 0x02, 0x02, 0x00, + 0x96, 0x02, 0x02, 0x00, 0x98, 0x02, 0x02, 0x00, 0x9a, 0x02, 0x02, 0x00, 0x9c, 0x02, 0x02, 0x00, + 0x9e, 0x02, 0x02, 0x00, 0xa0, 0x02, 0x02, 0x00, 0xa2, 0x02, 0x02, 0x00, 0xa4, 0x02, 0x02, 0x00, + 0xa6, 0x02, 0x02, 0x00, 0xa8, 0x02, 0x02, 0x00, 0xaa, 0x02, 0x02, 0x00, 0xac, 0x02, 0x02, 0x00, + 0xae, 0x02, 0x02, 0x00, 0xb0, 0x02, 0x02, 0x00, 0xb2, 0x02, 0x02, 0x00, 0xb4, 0x02, 0x02, 0x00, + 0xb6, 0x02, 0x02, 0x00, 0xb8, 0x02, 0x02, 0x00, 0xba, 0x02, 0x02, 0x00, 0xbc, 0x02, 0x02, 0x00, + 0xbe, 0x02, 0x02, 0x00, 0xc0, 0x02, 0x02, 0x00, 0xc2, 0x02, 0x02, 0x00, 0xc4, 0x02, 0x02, 0x00, + 0xc6, 0x02, 0x02, 0x00, 0xc8, 0x02, 0x02, 0x00, 0xca, 0x02, 0x02, 0x00, 0xcc, 0x02, 0x02, 0x00, + 0xce, 0x02, 0x02, 0x00, 0xd0, 0x02, 0x02, 0x00, 0xd2, 0x02, 0x02, 0x00, 0xd4, 0x02, 0x02, 0x00, + 0xd6, 0x02, 0x02, 0x00, 0xd8, 0x02, 0x02, 0x00, 0xda, 0x02, 0x02, 0x00, 0xdc, 0x02, 0x02, 0x00, + 0xde, 0x02, 0x02, 0x00, 0xe0, 0x02, 0x02, 0x00, 0xe2, 0x02, 0x02, 0x00, 0xe4, 0x02, 0x02, 0x00, + 0xe6, 0x02, 0x02, 0x00, 0xe8, 0x02, 0x02, 0x00, 0xea, 0x02, 0x02, 0x00, 0xec, 0x02, 0x02, 0x00, + 0xee, 0x02, 0x02, 0x00, 0xf0, 0x02, 0x02, 0x00, 0xf2, 0x02, 0x02, 0x00, 0xf4, 0x02, 0x02, 0x00, + + 0xf6, 0x02, 0x02, 0x00, 0xf8, 0x02, 0x02, 0x00, 0xfa, 0x02, 0x02, 0x00, 0xfc, 0x02, 0x02, 0x00, + 0xfe, 0x02, 0x02, 0x00, 0x00, 0x03, 0x02, 0x00, 0x02, 0x03, 0x02, 0x00, 0x04, 0x03, 0x02, 0x00, + 0x06, 0x03, 0x02, 0x00, 0x08, 0x03, 0x02, 0x00, 0x0a, 0x03, 0x02, 0x00, 0x0c, 0x03, 0x02, 0x00, + 0x0e, 0x03, 0x02, 0x00, 0x10, 0x03, 0x02, 0x00, 0x12, 0x03, 0x02, 0x00, 0x14, 0x03, 0x02, 0x00, + 0x16, 0x03, 0x02, 0x00, 0x18, 0x03, 0x02, 0x00, 0x1a, 0x03, 0x02, 0x00, 0x1c, 0x03, 0x02, 0x00, + 0x1e, 0x03, 0x02, 0x00, 0x20, 0x03, 0x02, 0x00, 0x22, 0x03, 0x02, 0x00, 0x24, 0x03, 0x02, 0x00, + 0x26, 0x03, 0x02, 0x00, 0x28, 0x03, 0x02, 0x00, 0x2a, 0x03, 0x02, 0x00, 0x2c, 0x03, 0x02, 0x00, + 0x2e, 0x03, 0x02, 0x00, 0x30, 0x03, 0x02, 0x00, 0x32, 0x03, 0x02, 0x00, 0x34, 0x03, 0x02, 0x00, + 0x36, 0x03, 0x02, 0x00, 0x38, 0x03, 0x02, 0x00, 0x3a, 0x03, 0x02, 0x00, 0x3c, 0x03, 0x02, 0x00, + 0x3e, 0x03, 0x02, 0x00, 0x40, 0x03, 0x02, 0x00, 0x42, 0x03, 0x02, 0x00, 0x44, 0x03, 0x02, 0x00, + 0x46, 0x03, 0x02, 0x00, 0x48, 0x03, 0x02, 0x00, 0x4a, 0x03, 0x02, 0x00, 0x4c, 0x03, 0x02, 0x00, + 0x4e, 0x03, 0x02, 0x00, 0x50, 0x03, 0x02, 0x00, 0x52, 0x03, 0x02, 0x00, 0x54, 0x03, 0x02, 0x00, + 0x56, 0x03, 0x02, 0x00, 0x58, 0x03, 0x02, 0x00, 0x5a, 0x03, 0x02, 0x00, 0x5c, 0x03, 0x02, 0x00, + 0x5e, 0x03, 0x02, 0x00, 0x60, 0x03, 0x02, 0x00, 0x62, 0x03, 0x02, 0x00, 0x64, 0x03, 0x02, 0x00, + 0x66, 0x03, 0x02, 0x00, 0x68, 0x03, 0x02, 0x00, 0x6a, 0x03, 0x02, 0x00, 0x6c, 0x03, 0x02, 0x00, + 0x6e, 0x03, 0x02, 0x00, 0x70, 0x03, 0x02, 0x00, 0x72, 0x03, 0x02, 0x00, 0x74, 0x03, 0x02, 0x00, + 0x76, 0x03, 0x02, 0x00, 0x78, 0x03, 0x02, 0x00, 0x7a, 0x03, 0x02, 0x00, 0x7c, 0x03, 0x02, 0x00, + 0x7e, 0x03, 0x02, 0x00, 0x80, 0x03, 0x02, 0x00, 0x82, 0x03, 0x02, 0x00, 0x84, 0x03, 0x02, 0x00, + 0x86, 0x03, 0x02, 0x00, 0x88, 0x03, 0x02, 0x00, 0x8a, 0x03, 0x02, 0x00, 0x8c, 0x03, 0x02, 0x00, + 0x8e, 0x03, 0x02, 0x00, 0x90, 0x03, 0x02, 0x00, 0x92, 0x03, 0x02, 0x00, 0x94, 0x03, 0x02, 0x00, + 0x96, 0x03, 0x02, 0x00, 0x98, 0x03, 0x02, 0x00, 0x9a, 0x03, 0x02, 0x00, 0x9c, 0x03, 0x02, 0x00, + 0x9e, 0x03, 0x02, 0x00, 0xa0, 0x03, 0x02, 0x00, 0xa2, 0x03, 0x02, 0x00, 0xa4, 0x03, 0x02, 0x00, + 0xa6, 0x03, 0x02, 0x00, 0xa8, 0x03, 0x02, 0x00, 0xaa, 0x03, 0x02, 0x00, 0xac, 0x03, 0x02, 0x00, + 0xae, 0x03, 0x02, 0x00, 0xb0, 0x03, 0x02, 0x00, 0xb2, 0x03, 0x02, 0x00, 0xb4, 0x03, 0x02, 0x00, + 0xb6, 0x03, 0x02, 0x00, 0xb8, 0x03, 0x02, 0x00, 0xba, 0x03, 0x02, 0x00, 0xbc, 0x03, 0x02, 0x00, + 0xbe, 0x03, 0x02, 0x00, 0xc0, 0x03, 0x02, 0x00, 0xc2, 0x03, 0x02, 0x00, 0xc4, 0x03, 0x02, 0x00, + 0xc6, 0x03, 0x02, 0x00, 0xc8, 0x03, 0x02, 0x00, 0xca, 0x03, 0x02, 0x00, 0xcc, 0x03, 0x02, 0x00, + 0xce, 0x03, 0x02, 0x00, 0xd0, 0x03, 0x02, 0x00, 0xd2, 0x03, 0x02, 0x00, 0xd4, 0x03, 0x02, 0x00, + 0xd6, 0x03, 0x02, 0x00, 0xd8, 0x03, 0x02, 0x00, 0xda, 0x03, 0x02, 0x00, 0xdc, 0x03, 0x02, 0x00, + 0xde, 0x03, 0x02, 0x00, 0xe0, 0x03, 0x02, 0x00, 0xe2, 0x03, 0x02, 0x00, 0xe4, 0x03, 0x02, 0x00, + 0xe6, 0x03, 0x02, 0x00, 0xe8, 0x03, 0x02, 0x00, 0xea, 0x03, 0x02, 0x00, 0xec, 0x03, 0x02, 0x00, + 0xee, 0x03, 0x02, 0x00, 0xf0, 0x03, 0x02, 0x00, 0xf2, 0x03, 0x02, 0x00, 0xf4, 0x03, 0x02, 0x00, + + 0xf6, 0x03, 0x02, 0x00, 0xf8, 0x03, 0x02, 0x00, 0xfa, 0x03, 0x02, 0x00, 0xfc, 0x03, 0x02, 0x00, + 0xfe, 0x03, 0x02, 0x00 +}; +#else +const uint8_t mGammaResetTablesBuf[] = { + 0x0E, 0x00, 0x00, 0x00, /// ID -> 4 bytes +}; +#endif /// _USE_GAMMA_RESET_HC_ + +// const uint8_t mGammaResetTablesBuf[] = { +// 0x0E, 0x00, 0x00, 0x00 +// }; +#endif /// _gamma_tables_ + diff --git a/source/dvp/VisionCam/OMXVisionCam_WB_patch.h b/source/dvp/VisionCam/OMXVisionCam_WB_patch.h new file mode 100644 index 0000000..d46e31e --- /dev/null +++ b/source/dvp/VisionCam/OMXVisionCam_WB_patch.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WB_GAIN_PATCH +#define WB_GAIN_PATCH + +uint8_t mWBbuffer[] = { 0x0C, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x02, + 0x00, 0x02, 0x00, 0x02 + }; + +const uint8_t mWBresetBuffer[] = { 0x0C, 0x00, 0x00, 0x00 }; + +#endif diff --git a/source/dvp/VisionCam/Params3Adump.h b/source/dvp/VisionCam/Params3Adump.h new file mode 100644 index 0000000..53760a3 --- /dev/null +++ b/source/dvp/VisionCam/Params3Adump.h @@ -0,0 +1,1135 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +static VCAM_3ASKIP_IPIPE_3DCC_CFGTYPE t3dccDump = { + /*.enable = */0, + /*.pInBiffData = */{ 0 } +}; + +static VCAM_3ASKIP_IPIPE_BOXCAR_CFGTYPE boxCarDump = { + /*.nEnable = */0, + /*.nOst = */1, + /*.nBoxSize = */1, + /*.nShift = */0, + /*.pAddr = */{ 0 } +}; + +static VCAM_3ASKIP_IPIPE_BSC_CFGTYPE bscDump = { + /*.nEnable = */1, + /*.nMode = */1, + /*.nColSample = */1, + /*.nRowSample = */1, + /*.nElement = */0, + { + /*.nColPos.nVectors = */3, + /*.nColPos.nShift = */0, + /*.nColPos.nVPos = */0, + /*.nColPos.nHPos = */0, + /*.nColPos.nVNum = */144, + /*.nColPos.nHNum = */636, + /*.nColPos.nVSkip = */2, + /*.nColPos.nHSkip = */2 + }, + { + /*.nRowPos.nVectors = */3, + /*.nRowPos.nShift = */0, + /*.nRowPos.nVPos = */0, + /*.nRowPos.nHPos = */0, + /*.nRowPos.nVNum = */432, + /*.nRowPos.nHNum = */212, + /*.nRowPos.nVSkip = */2, + /*.nRowPos.nHSkip = */2 + } +}; + +static VCAM_3ASKIP_IPIPE_CAR_CFGTYPE carDump = { + /*.nEnable = */0, + /*.nTyp = */3, + /*.nSw0Thr = */255, + /*.nSw1Thr = */192, + /*.nHpfType = */3, + /*.nHpfShift = */0, + /*.nHpfThr = */32, + /*.nGn1Gain = */255, + /*.nGn1Shift = */5, + /*.nGn1Min = */128, + /*.nGn2Gain = */255, + /*.nGn2Shift = */12, + /*.nGn2Min = */128 +}; + +static VCAM_3ASKIP_IPIPE_CFA_CFGTYPE cfaDump = { + /*.nEnable = */1, + /*.eMode = */(VCAM_3ASKIP_IPIPE_CFA_MODETYPE)0, + { + /*.tDir.nHpfThr = */600, + /*.tDir.nHpfSlope = */57, + /*.tDir.nMixThr = */10, + /*.tDir.nMixSlope = */10, + /*.tDir.nDirThr = */16, + /*.tDir.nDirSlope = */10, + /*.tDir.nDirNdwt = */16 + }, + { + /*.tDaa.nMonoHueFra = */16, + /*.tDaa.nMonoEdgThr = */25, + /*.tDaa.nMonoThrMin = */25, + /*.tDaa.nMonoThrSlope = */20, + /*.tDaa.nMonoSlpMin = */500, + /*.tDaa.nMonoSlpSlp = */20, + /*.tDaa.nMonoLpwt = */24 + } +}; + +static VCAM_3ASKIP_IPIPE_CGS_CFGTYPE cgsDump = { + /*.enable = */0, + { + /*.y_chroma_low.thr = */0, + /*.y_chroma_low.gain = */250, + /*.y_chroma_low.shift = */0, + /*.y_chroma_low.min = */10 + }, + { + /*.y_chroma_high.thr = */106, + /*.y_chroma_high.gain = */100, + /*.y_chroma_high.shift = */0, + /*.y_chroma_high.min = */50 + }, + { + /*.c_chroma.thr = */22, + /*.c_chroma.gain = */10, + /*.c_chroma.shift = */0, + /*.c_chroma.min = */50 + } +}; + +static VCAM_3ASKIP_ISIF_CLAMP_CFGTYPE clampDump = { + /*.nEnable = */0, + /*.eHClampMode = */(VCAM_3ASKIP_ISIF_HORIZONTAL_CLAMP_MODETYPE)0, + /*.eBlackClampMode = */(VCAM_3ASKIP_ISIF_BLACK_CLAMP_MODETYPE)0, + /*.nDCOffsetClampVal = */65472, + /*.nBlackClampVStartPos = */0, + { + /*.tHorizontalBlack.nVPos = */0, + /*.tHorizontalBlack.eVSize = */0, + /*.tHorizontalBlack.nHPos = */0, + /*.tHorizontalBlack.eHSize = */(VCAM_3ASKIP_ISIF_VBLACK_PIXEL_WIDTHTYPE)0, + /*.tHorizontalBlack.line_avg_coef = */0, + /*.tHorizontalBlack.reset_mode = */(VCAM_3ASKIP_ISIF_VBLACK_RESET_MODETYPE)0, + /*.tHorizontalBlack.reset_value = */0 + }, + { + /*.tVerticalBlack.nVPos = */0, + /*.tVerticalBlack.nVSize = */0, + /*.tVerticalBlack.nHPos = */0, + /*.tVerticalBlack.HSize = */(VCAM_3ASKIP_ISIF_VBLACK_PIXEL_WIDTHTYPE)0, + /*.tVerticalBlack.line_avg_coef = */0, + /*.tVerticalBlack.reset_mode = */(VCAM_3ASKIP_ISIF_VBLACK_RESET_MODETYPE)0, + /*.tVerticalBlack.reset_value = */0 + } +}; + +static VCAM_3ASKIP_IPIPEIF_DFS_CFGTYPE dfsDump = { + /*.eDfsGainEn = */(VCAM_3ASKIP_IPIPEIF_FEATURE_SELECTTYPE)1, + /*.nDfsGainVal = */512, + /*.nDfsGainThr = */16, + /*.nOclip = */255, + /*.nDfsDir = */0 +}; + +static VCAM_3ASKIP_IPIPEIF_DPC_CFGTYPE dpc1Dump = { + /*.eDpcEn = */(VCAM_3ASKIP_IPIPEIF_FEATURE_SELECTTYPE)1, + /*.eDpcThr = */20 +}; + +static VCAM_3ASKIP_IPIPEIF_DPC_CFGTYPE dpc2Dump = { + /*.eDpcEn = */(VCAM_3ASKIP_IPIPEIF_FEATURE_SELECTTYPE)1, + /*.eDpcThr = */20 +}; + +static VCAM_3ASKIP_IPIPEIF_DPCM_CFGTYPE dpcmDump = { + /*.nDpcmBitSize = */ (VCAM_3ASKIP_IPIPEIF_FEATURE_SELECTTYPE)1, + /*.nDpcmEn = */ (VCAM_3ASKIP_IPIPEIF_DPCM_PRED_TYPTYPE)1, + /*.nDpcmPredictor = */ (VCAM_3ASKIP_IPIPEIF_DPCM_BIT_SIZETYPE)1 +}; + + +static VCAM_3ASKIP_IPIPE_DPCLUT_CFGTYPE dpcLutDump = { + /*.nEnable = */0, + /*.eTableType = */(VCAM_3ASKIP_IPIPE_DPC_LUT_TBL_SIZETYPE)0, + /*.eReplaceType = */(VCAM_3ASKIP_IPIPE_DPC_LUT_REPLACEMENTTYPE)0, + /*.nLutValidAddr = */ { 0 }, + /*.nLutSize = */0, + /*.nLutTable0Addr = */{ 0 }, + /*.nLutTable1Addr = */{ 0 } +}; + +//*(ptDpcm) = {...} +// nDpcmEn = 0 +// nDpcmPredictor = 0 +// nDpcmBitSize = 0 + +static VCAM_3ASKIP_IPIPE_DPCOTF_CFGTYPE dpcOtfDump; + +static VCAM_3ASKIP_ISIF_GAINOFFSET_CFGTYPE gainOffsetDump = { + /*.gain_offset_featureflag = */6, + /*.gain_r = */520, + /*.gain_gr = */520, + /*.gain_gb = */520, + /*.gain_bg = */520, + /*.offset = */0 +}; + + +static VCAM_3ASKIP_IPIPE_GIC_CFGTYPE gicDump = { + /*.nEnable = */1, + /*.eLscGain = */(VCAM_3ASKIP_IPIPE_GIC_LSC_GAINTYPE)0, + /*.eSel = */(VCAM_3ASKIP_IPIPE_GIC_SELTYPE)0, + /*.eTyp = */(VCAM_3ASKIP_IPIPE_GIC_INDEXTYPE)0, + /*.nGicGain = */128, + /*.nGicNfGain = */128, + /*.nGicThr = */64, + /*.nGicSlope = */20 +}; + +static VCAM_3ASKIP_H3A_AEWB_PARAMTYPE h3aAewbDump = { + /*.eAewbEnable = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)1, + /*.ptAewbPaxelWin = */{ (uint16_t)0, (uint8_t)0, (uint16_t)0, (uint8_t)0, (uint8_t)0, (uint8_t)0, (uint8_t)0, (uint8_t)0 }, + /*.ptBlkWinDims = */{ 0, 0 }, + /*.eAeOpFmt = */(VCAM_3ASKIP_H3A_AEWB_OP_FMTTYPE)2, + /*.nShiftValue = */0, + /*.nSaturationLimit = */1022, + /*.nAewbOpAddr = */{ 0 } +}; + +static VCAM_3ASKIP_H3A_COMMON_CFGTYPE h3aCommonDump = { + /*.eAfMedianEn = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)0, + /*.eAewbMedianEn = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)0, + /*.nMedianFilterThreshold = */0, + /*.eAfAlawEn = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)1, + /*.eAewbAlawEn = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)0, + /*.eIpipeifAveFiltEn = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)0, + /*.eH3aDecimEnable = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)0, + /*.nReserved = */ 0 +}; + +static VCAM_3ASKIP_IPIPE_HIST_CFGTYPE histDump = { + /*.nEnable = */0, + /*.nOst = */0, + /*.nSel = */0, + /*.nType = */0, + /*.nBins = */0, + /*.nShift = */0, + /*.nCol = */0, + /*.nRegions = */0, + /*.ptHistDim = */ + { + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 } + }, + /*.nClearTable = */0, + /*.nTableSel = */0, + /*.pnGainTbl = */{ 0, 0, 0, 0 } +}; + +static VCAM_3ASKIP_RSZ_LPF_CFGTYPE hlpfDump = { + /*.nCIntensity = */22, + /*.nYIntensity = */21 +}; + +static VCAM_3ASKIP_ISIF_2DLSC_CFGTYPE lsc2dDump = { + /*.nEnable = */0, + /*.nLscHSize = */0, + /*.nLscVSize = */0, + /*.nHDirDataOffset = */16, + /*.nVDirDataOffset = */2, + /*.nHPosInPaxel = */0, + /*.nVPosInPaxel = */0, + /*.ePaxHeight = */(VCAM_3ASKIP_ISIF_LSC_GAIN_MODE_MNTYPE)3, + /*.ePaxLength = */(VCAM_3ASKIP_ISIF_LSC_GAIN_MODE_MNTYPE)3, + /*.eGainFormat = */(VCAM_3ASKIP_ISIF_LSC_GAIN_FORMATTYPE)0, + /*.nOffsetScalingFactor = */0, + /*.eOffsetShiftVal = */(VCAM_3ASKIP_ISIF_LSC_OFFSET_SHIFTTYPE)0, + /*.eOffsetEnable = */(VCAM_3ASKIP_ISIF_LSC_OFFSET_ENABLETYPE)0, + /*.nGainTableAddress = */{ 0 }, + /*.nGainTableLength = */255, + /*.nOffsetTableAddress = */{ 0 }, + /*.nOffsetTableLength = */255 +}; + +static VCAM_3ASKIP_IPIPE_LSC_CFGTYPE lscDump = { + /*.nVOffset = */0, + /*.nVLinearCoeff = */0, + /*.nVQuadraticCoeff = */3720, + /*.nVLinearShift = */11, + /*.nVQuadraticShift = */11, + /*.nHOffset = */0, + /*.nHLinearCoeff = */0, + /*.nHQuadraticCoeff = */3601, + /*.nHLinearShift = */11, + /*.nHQuadraticShift = */11, + /*.nGainR = */57, + /*.nGainGR = */64, + /*.nGainGB = */64, + /*.nGainB = */50, + /*.nOffR = */227, + /*.nOffGR = */245, + /*.nOffGB = */246, + /*.nOffB = */207, + /*.nShift = */9, + /*.nMax = */511 +}; + +static VCAM_3ASKIP_IPIPE_NOISE_FILTER_CFGTYPE nf1Dump = { + /*.nEnable = */0, + /*.eNFNum = */(VCAM_3ASKIP_IPIPE_NOISE_FILTERTYPE)2, + /*.eSel = */(VCAM_3ASKIP_IPIPE_NF_SELTYPE)0, + /*.eLscGain = */(VCAM_3ASKIP_IPIPE_NF_LSC_GAINTYPE)0, + /*.eTyp = */(VCAM_3ASKIP_IPIPE_NF_SAMPLE_METHODTYPE)0, + /*.nDownShiftVal = */0, + /*.nSpread = */0, + + /*.pnThr = */ + { + 0x0041, + 0x003C, + 0x004B, + 0x0046, + 0x0055, + 0x0050, + 0x0064, + 0x005A + }, + + /*.pnStr = */ + { + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08 + }, + + /*.pnSpr = */ + { + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08 + }, + /*.nEdgeMin = */0, + /*.nEdgeMax = */0 +}; + +static VCAM_3ASKIP_IPIPE_NOISE_FILTER_CFGTYPE nf2Dump = { + /*.nEnable = */0, + /*.eNFNum = */(VCAM_3ASKIP_IPIPE_NOISE_FILTERTYPE)2, + /*.eSel = */(VCAM_3ASKIP_IPIPE_NF_SELTYPE)0, + /*.eLscGain = */(VCAM_3ASKIP_IPIPE_NF_LSC_GAINTYPE)0, + /*.eTyp = */(VCAM_3ASKIP_IPIPE_NF_SAMPLE_METHODTYPE)0, + /*.nDownShiftVal = */0, + /*.nSpread = */0, + + /*.pnThr = */ + { + 0x0041, + 0x003C, + 0x004B, + 0x0046, + 0x0055, + 0x0050, + 0x0064, + 0x005A + }, + + /*.pnStr = */ + { + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08 + }, + + /*.pnSpr = */ + { + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + }, + + /*.nEdgeMin = */0, + /*.nEdgeMax = */0 +}; + +static VCAM_3ASKIP_IPIPE_RGBRGB_CFGTYPE rgb2rgb1Dump = { + /*.pnMulOff = */ + { + { + 0xFFBA, + 0x016A, + 0xFFAA + }, + { + 0xFFDC, + 0xFFFD, + 0x0159 + }, + { + 0xFF1B, + 0xFFFD, + 0x0100 + } + }, + /*.pnOft = */ + { + 0x0000, + 0x0000, + 0x0000 + } +}; + + +static VCAM_3ASKIP_IPIPE_RGBRGB_CFGTYPE rgb2rgb2Dump = { + /*.pnMulOff = */ + { + { + 0xFFBA, + 0x016A, + 0xFFAA + }, + { + 0xFFDC, + 0xFFFD, + 0x0159 + }, + { + 0xFF1B, + 0xFFFD, + 0x0100 + } + }, + /*.pnOft = */ + { + 0x0000, + 0x0000, + 0x0000 + } +}; + +static VCAM_3ASKIP_IPIPE_RGBYUV_CFGTYPE rgb2yuvDump = { + /*.nBrightness = */0, + /*.nContrast = */16, + /*.pnMulVal = */ + { + { + 0x004D, + 0x0096, + 0x001D + }, + { + 0xFFD5, + 0xFFAB, + 0x0080 + }, + { + 0x0080, + 0xFF95, + 0xFFEB + } + }, + /*.pnOffset = */ + { + 0x0000, + 0x0080, + 0x0080 + }, +}; + +static VCAM_3ASKIP_ISIF_VLDC_CFGTYPE vldcDump = { + /*.nEnable = */0, + /*.eDisableVldcUpperPixels = */(VCAM_3ASKIP_ISIF_VDLC_PIXEL_DEPENDENCYTYPE)1, + /*.nVldcShiftVal = */3, + /*.eVldcModeSelect = */(VCAM_3ASKIP_ISIF_VLDC_MODE_SELECTTYPE)2, + /*.nVldcSaturationLvl = */511, + /*.nDefectLines = */1, + { + /*.tVldcDefectLineParams.nVerticalDefectPosition = */0, + /*.tVldcDefectLineParams.nHorizontalDefectPosition = */0, + /*.tVldcDefectLineParams.nSub1ValueVldc = */0, + /*.tVldcDefectLineParams.nSub2LessThanVldc = */0, + /*.tVldcDefectLineParams.nSub3GreaterThanVldc = */0 + } +}; + +static VCAM_3ASKIP_RSZ_LPF_CFGTYPE vlpDump = { + /*.nCIntensity = */15, + /*.nYIntensity = */14 +}; + +static VCAM_3ASKIP_IPIPE_WB_CFGTYPE wbDump = { + /*.pnOffset = */ + { + 0x0000, + 0x0000, + 0x0000, + 0x0000 + }, + /*.pnGain = */ + { + 0x0200, + 0x0278, + 0x03D8, + 0x0200 + } +}; + +static VCAM_3ASKIP_IPIPE_YUV444YUV422_CFGTYPE yuv2yuvDump = { + /*.ePos = */(VCAM_3ASKIP_IPIPE_YUV_PHASE_POSTYPE)0, + /*.nLpfEn = */1 +}; + + + +static VCAM_3ASKIP_H3A_AF_PARAMTYPE h3aAfDump = { + /*eAfEnable = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)1, + /*eRgbPos = */(VCAM_3ASKIP_H3A_RGB_POSTYPE)3, + /*ePeakModeEn = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)1, + /*eVerticalFocusEn = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)0, + /*nIirStartPos = */0, + /*ptAfPaxelWin = */ + { + 0 ,0, 0, 0, 0, 0, 0, 0 + }, + /*ptIir1 = */ + { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + 0 + }, + /*ptIir2 = */ + { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + 0 + }, + /*ptFir1 = */ + { + { 0, 0, 0, 0, 0 }, + 0 + }, + /*ptFir2 = */ + { + { 0, 0, 0, 0, 0 }, + 0 + }, + /*nAfOpAddr = */ + { 0 } +}; + +static VCAM_3ASKIP_CAM_CONTROL_EXPGAINTYPE expCtrlDump = { + /*exp =*/ 0xA, + /*a_gain = */0xB, + /*mask = */0xC, + /*nAgainErr = */0xD, + /*nDigitalISPGain = */0xE +}; + +static VCAM_3ASKIP_IPIPE_EE_CFGTYPE edgeEnhDump = { + /*nEnable = */0, + /*eHaloReduction = */(VCAM_3ASKIP_IPIPE_EE_HALO_CTRLTYPE)0, + /*pnMulVal =*/ + { + 0x000C, + 0x0030, + 0x000C, + 0xFFF6, + 0xFFFA, + 0x0000, + 0xFFFA, + 0xFFF6, + 0x0000 + }, + /*nSel = */0, + /*nShiftHp = */3, + /*nThreshold = */0, + /*nGain = */0, + /*nHpfLowThr = */0, + /*nHpfHighThr = */0, + /*nHpfGradientGain = */0, + /*nHpfgradientOffset = */0, + /*pnEeTable =*/ + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, + 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, + 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, + 15, 15, 15, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, + 18, 18, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 21, 21, 21, 21, + 21, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, + 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 28, + 28, 28, 28, 28, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 31, 31, + 31, 31, 31, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, 34, + 34, 34, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 37, 37, 37, 37, + 37, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, + 41, 41, 41, 41, 41, 41, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, + 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, + 43, 42, 42, 42, 42, 42, 42, 41, 41, 41, 41, 41, 40, 40, 40, 40, + 40, 39, 39, 39, 39, 39, 38, 38, 38, 38, 37, 37, 37, 37, 36, 36, + 36, 36, 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 33, 32, 32, + 32, 31, 31, 31, 31, 30, 30, 30, 29, 29, 29, 29, 28, 28, 28, 27, + 27, 27, 27, 26, 26, 26, 25, 25, 25, 24, 24, 24, 24, 23, 23, 23, + 22, 22, 22, 21, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, + 18, 17, 17, 17, 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 13, 13, + 13, 13, 12, 12, 12, 12, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9, + 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, + 5, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, + 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, -2, + -2, -3, -3, -3, -3, -3, -3, -4, -4, -4, -4, -4, -4, -5, -5, -5, + -5, -5, -6, -6, -6, -6, -7, -7, -7, -7, -7, -8, -8, -8, -8, -9, + -9, -9, -9, -10, -10, -10, -10, -11, -11, -11, -12, -12, -12, -12, -13, -13, + -13, -13, -14, -14, -14, -15, -15, -15, -15, -16, -16, -16, -17, -17, -17, -18, + -18, -18, -18, -19, -19, -19, -20, -20, -20, -21, -21, -21, -21, -22, -22, -22, + -23, -23, -23, -24, -24, -24, -24, -25, -25, -25, -26, -26, -26, -27, -27, -27, + -27, -28, -28, -28, -29, -29, -29, -29, -30, -30, -30, -31, -31, -31, -31, -32, + -32, -32, -33, -33, -33, -33, -34, -34, -34, -34, -35, -35, -35, -35, -36, -36, + -36, -36, -37, -37, -37, -37, -38, -38, -38, -38, -39, -39, -39, -39, -39, -40, + -40, -40, -40, -40, -41, -41, -41, -41, -41, -42, -42, -42, -42, -42, -42, -43, + -43, -43, -43, -43, -43, -43, -44, -44, -44, -44, -44, -44, -44, -45, -45, -45, + -45, -45, -45, -45, -45, -45, -45, -46, -46, -46, -46, -46, -46, -46, -46, -46, + -46, -46, -46, -46, -46, -46, -46, -46, -47, -47, -47, -47, -47, -47, -47, -47, + -47, -47, -47, -47, -47, -47, -47, -47, -47, -47, -46, -46, -46, -46, -46, -46, + -46, -46, -46, -46, -46, -46, -46, -46, -46, -46, -46, -45, -45, -45, -45, -45, + -45, -45, -45, -45, -45, -44, -44, -44, -44, -44, -44, -44, -44, -43, -43, -43, + -43, -43, -43, -43, -42, -42, -42, -42, -42, -42, -41, -41, -41, -41, -41, -41, + -40, -40, -40, -40, -40, -39, -39, -39, -39, -39, -38, -38, -38, -38, -38, -37, + -37, -37, -37, -37, -36, -36, -36, -36, -36, -35, -35, -35, -35, -35, -34, -34, + -34, -34, -34, -33, -33, -33, -33, -33, -32, -32, -32, -32, -32, -31, -31, -31, + -31, -31, -30, -30, -30, -30, -30, -29, -29, -29, -29, -29, -28, -28, -28, -28, + -28, -27, -27, -27, -27, -27, -26, -26, -26, -26, -26, -25, -25, -25, -25, -25, + -24, -24, -24, -24, -24, -23, -23, -23, -23, -23, -22, -22, -22, -22, -22, -21, + -21, -21, -21, -21, -20, -20, -20, -20, -20, -19, -19, -19, -19, -19, -18, -18, + -18, -18, -18, -17, -17, -17, -17, -17, -16, -16, -16, -16, -16, -15, -15, -15, + -15, -15, -14, -14, -14, -14, -14, -13, -13, -13, -13, -13, -12, -12, -12, -12, + -12, -11, -11, -11, -11, -11, -10, -10, -10, -10, -10, -9, -9, -9, -9, -9, + -8, -8, -8, -8, -8, -7, -7, -7, -7, -7, -6, -6, -6, -6, -6, -5, + -5, -5, -5, -5, -4, -4, -4, -4, -4, -3, -3, -3, -3, -3, -2, -2, + -2, -2, -2, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 + } +}; + +static VCAM_3ASKIP_IPIPE_GAMMA_CFGTYPE gammaDump = { + /*nEnable = */0, + /*eGammaTblSize = */(VCAM_3ASKIP_IPIPE_GAMMA_TABLE_SIZETYPE)3, + /*nTbl = */0, + /*eBypassB = */(VCAM_3ASKIP_IPIPE_GAMMA_BYPASSTYPE)0, + /*eBypassG = */(VCAM_3ASKIP_IPIPE_GAMMA_BYPASSTYPE)0, + /*eBypassR = */(VCAM_3ASKIP_IPIPE_GAMMA_BYPASSTYPE)0, + /*pnRedTable =*/ + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 4, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 8, 0, 4, 0, 12, 0, 0, 0, 12, 0, 4, 0, + 16, 0, 0, 0, 16, 0, 4, 0, 20, 0, 0, 0, 20, 0, 4, 0, + 24, 0, 4, 0, 28, 0, 4, 0, 32, 0, 8, 0, 40, 0, 8, 0, + 48, 0, 8, 0, 56, 0, 8, 0, 64, 0, 4, 0, 68, 0, 8, 0, + 76, 0, 4, 0, 80, 0, 8, 0, 88, 0, 8, 0, 96, 0, 4, 0, + 100, 0, 8, 0, 108, 0, 8, 0, 116, 0, 4, 0, 120, 0, 12, 0, + -124, 0, 8, 0, -116, 0, 4, 0, -112, 0, 8, 0, -104, 0, 4, 0, + -100, 0, 8, 0, -92, 0, 8, 0, -84, 0, 8, 0, -76, 0, 8, 0, + -68, 0, 8, 0, -60, 0, 8, 0, -52, 0, 8, 0, -44, 0, 8, 0, + -36, 0, 8, 0, -28, 0, 8, 0, -20, 0, 8, 0, -12, 0, 8, 0, + -4, 0, 8, 0, 4, 1, 8, 0, 12, 1, 8, 0, 20, 1, 8, 0, + 28, 1, 8, 0, 36, 1, 8, 0, 44, 1, 8, 0, 52, 1, 8, 0, + 60, 1, 8, 0, 68, 1, 8, 0, 76, 1, 4, 0, 80, 1, 8, 0, + 88, 1, 4, 0, 92, 1, 4, 0, 96, 1, 8, 0, 104, 1, 4, 0, + 108, 1, 4, 0, 112, 1, 8, 0, 120, 1, 4, 0, 124, 1, 4, 0, + -128, 1, 8, 0, -120, 1, 4, 0, -116, 1, 4, 0, -112, 1, 4, 0, + -108, 1, 4, 0, -104, 1, 4, 0, -100, 1, 4, 0, -96, 1, 0, 0, + -96, 1, 4, 0, -92, 1, 4, 0, -88, 1, 4, 0, -84, 1, 4, 0, + -80, 1, 4, 0, -76, 1, 4, 0, -72, 1, 4, 0, -68, 1, 4, 0, + -64, 1, 4, 0, -60, 1, 0, 0, -60, 1, 4, 0, -56, 1, 4, 0, + -52, 1, 0, 0, -52, 1, 4, 0, -48, 1, 4, 0, -44, 1, 0, 0, + -44, 1, 4, 0, -40, 1, 4, 0, -36, 1, 0, 0, -36, 1, 4, 0, + -32, 1, 4, 0, -28, 1, 0, 0, -28, 1, 0, 0, -28, 1, 4, 0, + -24, 1, 0, 0, -24, 1, 4, 0, -20, 1, 4, 0, -16, 1, 0, 0, + -16, 1, 4, 0, -12, 1, 4, 0, -8, 1, 0, 0, -8, 1, 4, 0, + -4, 1, 0, 0, -4, 1, 4, 0, 0, 2, 0, 0, 0, 2, 4, 0, + 4, 2, 4, 0, 8, 2, 0, 0, 8, 2, 4, 0, 12, 2, 0, 0, + 12, 2, 0, 0, 12, 2, 0, 0, 12, 2, 4, 0, 16, 2, 0, 0, + 16, 2, 4, 0, 20, 2, 0, 0, 20, 2, 4, 0, 24, 2, 4, 0, + 28, 2, 0, 0, 28, 2, 4, 0, 32, 2, 0, 0, 32, 2, 4, 0, + 36, 2, 0, 0, 36, 2, 0, 0, 36, 2, 4, 0, 40, 2, 0, 0, + 40, 2, 4, 0, 44, 2, 0, 0, 44, 2, 4, 0, 48, 2, 0, 0, + 48, 2, 4, 0, 52, 2, 0, 0, 52, 2, 4, 0, 56, 2, 0, 0, + 56, 2, 4, 0, 60, 2, 0, 0, 60, 2, 4, 0, 64, 2, 0, 0, + 64, 2, 0, 0, 64, 2, 4, 0, 68, 2, 0, 0, 68, 2, 4, 0, + 72, 2, 0, 0, 72, 2, 4, 0, 76, 2, 0, 0, 76, 2, 4, 0, + 80, 2, 0, 0, 80, 2, 0, 0, 80, 2, 4, 0, 84, 2, 0, 0, + 84, 2, 4, 0, 88, 2, 0, 0, 88, 2, 4, 0, 92, 2, 0, 0, + 92, 2, 4, 0, 96, 2, 0, 0, 96, 2, 4, 0, 100, 2, 0, 0, + 100, 2, 0, 0, 100, 2, 4, 0, 104, 2, 0, 0, 104, 2, 4, 0, + 108, 2, 0, 0, 108, 2, 4, 0, 112, 2, 0, 0, 112, 2, 0, 0, + 112, 2, 4, 0, 116, 2, 0, 0, 116, 2, 0, 0, 116, 2, 4, 0, + 120, 2, 0, 0, 120, 2, 4, 0, 124, 2, 0, 0, 124, 2, 4, 0, + -128, 2, 0, 0, -128, 2, 0, 0, -128, 2, 4, 0, -124, 2, 0, 0, + -124, 2, 0, 0, -124, 2, 4, 0, -120, 2, 0, 0, -120, 2, 4, 0, + -116, 2, 0, 0, -116, 2, 0, 0, -116, 2, 4, 0, -112, 2, 0, 0, + -112, 2, 4, 0, -108, 2, 0, 0, -108, 2, 4, 0, -104, 2, 0, 0, + -104, 2, 0, 0, -104, 2, 4, 0, -100, 2, 0, 0, -100, 2, 0, 0, + -100, 2, 4, 0, -96, 2, 0, 0, -96, 2, 0, 0, -96, 2, 4, 0, + -92, 2, 0, 0, -92, 2, 4, 0, -88, 2, 0, 0, -88, 2, 0, 0, + -88, 2, 4, 0, -84, 2, 0, 0, -84, 2, 0, 0, -84, 2, 0, 0, + -84, 2, 4, 0, -80, 2, 0, 0, -80, 2, 4, 0, -76, 2, 0, 0, + -76, 2, 4, 0, -72, 2, 0, 0, -72, 2, 0, 0, -72, 2, 4, 0, + -68, 2, 0, 0, -68, 2, 0, 0, -68, 2, 4, 0, -64, 2, 0, 0, + -64, 2, 0, 0, -64, 2, 4, 0, -60, 2, 0, 0, -60, 2, 0, 0, + -60, 2, 4, 0, -56, 2, 0, 0, -56, 2, 0, 0, -56, 2, 4, 0, + -52, 2, 0, 0, -52, 2, 4, 0, -48, 2, 0, 0, -48, 2, 0, 0, + -48, 2, 4, 0, -44, 2, 0, 0, -44, 2, 0, 0, -44, 2, 4, 0, + -40, 2, 0, 0, -40, 2, 0, 0, -40, 2, 0, 0, -40, 2, 4, 0, + -36, 2, 0, 0, -36, 2, 4, 0, -32, 2, 0, 0, -32, 2, 0, 0, + -32, 2, 4, 0, -28, 2, 0, 0, -28, 2, 0, 0, -28, 2, 4, 0, + -24, 2, 0, 0, -24, 2, 0, 0, -24, 2, 4, 0, -20, 2, 0, 0//, +// -20, 2, 0, 0, -20, 2, 0, 0, -20, 2, 4, 0, -16, 2, 0, 0, +// -16, 2, 0, 0, -16, 2, 4, 0, -12, 2, 0, 0, -12, 2, 4, 0, +// -8, 2, 0, 0, -8, 2, 0, 0, -8, 2, 0, 0, -8, 2, 4, 0, +// -4, 2, 0, 0, -4, 2, 4, 0, 0, 3, 0, 0, 0, 3, 0, 0, +// 0, 3, 4, 0, 4, 3, 0, 0, 4, 3, 0, 0, 4, 3, 0, 0, +// 4, 3, 4, 0, 8, 3, 0, 0, 8, 3, 0, 0, 8, 3, 0, 0, +// 8, 3, 4, 0, 12, 3, 0, 0, 12, 3, 4, 0, 16, 3, 0, 0, +// 16, 3, 0, 0, 16, 3, 4, 0, 20, 3, 0, 0, 20, 3, 0, 0, +// 20, 3, 4, 0, 24, 3, 0, 0, 24, 3, 0, 0, 24, 3, 0, 0, +// 24, 3, 4, 0, 28, 3, 0, 0, 28, 3, 0, 0, 28, 3, 0, 0, +// 28, 3, 4, 0, 32, 3, 0, 0, 32, 3, 4, 0, 36, 3, 0, 0, +// 36, 3, 0, 0, 36, 3, 4, 0, 40, 3, 0, 0, 40, 3, 0, 0, +// 40, 3, 0, 0, 40, 3, 4, 0, 44, 3, 0, 0, 44, 3, 0, 0, +// 44, 3, 4, 0, 48, 3, 0, 0, 48, 3, 0, 0, 48, 3, 0, 0, +// 48, 3, 4, 0, 52, 3, 0, 0, 52, 3, 0, 0, 52, 3, 0, 0, +// 52, 3, 4, 0, 56, 3, 0, 0, 56, 3, 0, 0, 56, 3, 4, 0, +// 60, 3, 0, 0, 60, 3, 0, 0, 60, 3, 4, 0, 64, 3, 0, 0, +// 64, 3, 4, 0, 68, 3, 0, 0, 68, 3, 0, 0, 68, 3, 0, 0, +// 68, 3, 4, 0, 72, 3, 0, 0, 72, 3, 0, 0, 72, 3, 0, 0, +// 72, 3, 4, 0, 76, 3, 0, 0, 76, 3, 0, 0, 76, 3, 4, 0, +// 80, 3, 0, 0, 80, 3, 0, 0, 80, 3, 0, 0, 80, 3, 4, 0, +// 84, 3, 0, 0, 84, 3, 0, 0, 84, 3, 0, 0, 84, 3, 4, 0, +// 88, 3, 0, 0, 88, 3, 0, 0, 88, 3, 4, 0, 92, 3, 0, 0, +// 92, 3, 0, 0, 92, 3, 0, 0, 92, 3, 4, 0, 96, 3, 0, 0, +// 96, 3, 0, 0, 96, 3, 0, 0, 96, 3, 4, 0, 100, 3, 0, 0, +// 100, 3, 0, 0, 100, 3, 4, 0, 104, 3, 0, 0, 104, 3, 0, 0, +// 104, 3, 0, 0, 104, 3, 4, 0, 108, 3, 0, 0, 108, 3, 0, 0, +// 108, 3, 4, 0, 112, 3, 0, 0, 112, 3, 0, 0, 112, 3, 0, 0, +// 112, 3, 4, 0, 116, 3, 0, 0, 116, 3, 0, 0, 116, 3, 0, 0, +// 116, 3, 0, 0, 116, 3, 4, 0, 120, 3, 0, 0, 120, 3, 0, 0, +// 120, 3, 0, 0, 120, 3, 4, 0, 124, 3, 0, 0, 124, 3, 0, 0, +// 124, 3, 0, 0, 124, 3, 4, 0, -128, 3, 0, 0, -128, 3, 0, 0, +// -128, 3, 4, 0, -124, 3, 0, 0, -124, 3, 0, 0, -124, 3, 4, 0, +// -120, 3, 0, 0, -120, 3, 0, 0, -120, 3, 0, 0, -120, 3, 4, 0, +// -116, 3, 0, 0, -116, 3, 0, 0, -116, 3, 4, 0, -112, 3, 0, 0, +// -112, 3, 0, 0, -112, 3, 0, 0, -112, 3, 4, 0, -108, 3, 0, 0, +// -108, 3, 0, 0, -108, 3, 0, 0, -108, 3, 0, 0, -108, 3, 4, 0, +// -104, 3, 0, 0, -104, 3, 0, 0, -104, 3, 4, 0, -100, 3, 0, 0, +// -100, 3, 0, 0, -100, 3, 4, 0, -96, 3, 0, 0, -96, 3, 0, 0, +// -96, 3, 0, 0, -96, 3, 4, 0, -92, 3, 0, 0, -92, 3, 0, 0, +// -92, 3, 0, 0, -92, 3, 0, 0, -92, 3, 4, 0, -88, 3, 0, 0, +// -88, 3, 0, 0, -88, 3, 4, 0, -84, 3, 0, 0, -84, 3, 0, 0, +// -84, 3, 0, 0, -84, 3, 4, 0, -80, 3, 0, 0, -80, 3, 0, 0, +// -80, 3, 0, 0, -80, 3, 0, 0, -80, 3, 4, 0, -76, 3, 0, 0, +// -76, 3, 0, 0, -76, 3, 4, 0, -72, 3, 0, 0, -72, 3, 0, 0, +// -72, 3, 0, 0, -72, 3, 0, 0, -72, 3, 4, 0, -68, 3, 0, 0, +// -68, 3, 0, 0, -68, 3, 0, 0, -68, 3, 4, 0, -64, 3, 0, 0, +// -64, 3, 0, 0, -64, 3, 4, 0, -60, 3, 0, 0, -60, 3, 0, 0, +// -60, 3, 0, 0, -60, 3, 0, 0, -60, 3, 4, 0, -56, 3, 0, 0, +// -56, 3, 0, 0, -56, 3, 0, 0, -56, 3, 4, 0, -52, 3, 0, 0, +// -52, 3, 0, 0, -52, 3, 0, 0, -52, 3, 4, 0, -48, 3, 0, 0, +// -48, 3, 0, 0, -48, 3, 0, 0, -48, 3, 4, 0, -44, 3, 0, 0, +// -44, 3, 0, 0, -44, 3, 0, 0, -44, 3, 4, 0, -40, 3, 0, 0, +// -40, 3, 0, 0, -40, 3, 0, 0, -40, 3, 4, 0, -36, 3, 0, 0, +// -36, 3, 0, 0, -36, 3, 0, 0, -36, 3, 4, 0, -32, 3, 0, 0, +// -32, 3, 0, 0, -32, 3, 0, 0, -32, 3, 0, 0, -32, 3, 4, 0, +// -28, 3, 0, 0, -28, 3, 0, 0, -28, 3, 0, 0, -28, 3, 0, 0, +// -28, 3, 4, 0, -24, 3, 0, 0, -24, 3, 0, 0, -24, 3, 4, 0, +// -20, 3, 0, 0, -20, 3, 0, 0, -20, 3, 0, 0, -20, 3, 0, 0, +// -20, 3, 4, 0, -16, 3, 0, 0, -16, 3, 0, 0, -16, 3, 0, 0, +// -16, 3, 4, 0, -12, 3, 0, 0, -12, 3, 0, 0, -12, 3, 0, 0, +// -12, 3, 4, 0, -8, 3, 0, 0, -8, 3, 0, 0, -8, 3, 0, 0, +// -8, 3, 0, 0, -8, 3, 4, 0, -4, 3, 0, 0, -4, 3, 0, 0, +// -4, 3, 0, 0, -4, 3, 0, 0, -4, 3, 0, 0, -4, 3, 0, 0 + }, + + /*pnBlueTable =*/ + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 4, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 8, 0, 4, 0, 12, 0, 0, 0, 12, 0, 4, 0, + 16, 0, 0, 0, 16, 0, 4, 0, 20, 0, 0, 0, 20, 0, 4, 0, + 24, 0, 4, 0, 28, 0, 4, 0, 32, 0, 8, 0, 40, 0, 8, 0, + 48, 0, 8, 0, 56, 0, 8, 0, 64, 0, 4, 0, 68, 0, 8, 0, + 76, 0, 4, 0, 80, 0, 8, 0, 88, 0, 8, 0, 96, 0, 4, 0, + 100, 0, 8, 0, 108, 0, 8, 0, 116, 0, 4, 0, 120, 0, 12, 0, + -124, 0, 8, 0, -116, 0, 4, 0, -112, 0, 8, 0, -104, 0, 4, 0, + -100, 0, 8, 0, -92, 0, 8, 0, -84, 0, 8, 0, -76, 0, 8, 0, + -68, 0, 8, 0, -60, 0, 8, 0, -52, 0, 8, 0, -44, 0, 8, 0, + -36, 0, 8, 0, -28, 0, 8, 0, -20, 0, 8, 0, -12, 0, 8, 0, + -4, 0, 8, 0, 4, 1, 8, 0, 12, 1, 8, 0, 20, 1, 8, 0, + 28, 1, 8, 0, 36, 1, 8, 0, 44, 1, 8, 0, 52, 1, 8, 0, + 60, 1, 8, 0, 68, 1, 8, 0, 76, 1, 4, 0, 80, 1, 8, 0, + 88, 1, 4, 0, 92, 1, 4, 0, 96, 1, 8, 0, 104, 1, 4, 0, + 108, 1, 4, 0, 112, 1, 8, 0, 120, 1, 4, 0, 124, 1, 4, 0, + -128, 1, 8, 0, -120, 1, 4, 0, -116, 1, 4, 0, -112, 1, 4, 0, + -108, 1, 4, 0, -104, 1, 4, 0, -100, 1, 4, 0, -96, 1, 0, 0, + -96, 1, 4, 0, -92, 1, 4, 0, -88, 1, 4, 0, -84, 1, 4, 0, + -80, 1, 4, 0, -76, 1, 4, 0, -72, 1, 4, 0, -68, 1, 4, 0, + -64, 1, 4, 0, -60, 1, 0, 0, -60, 1, 4, 0, -56, 1, 4, 0, + -52, 1, 0, 0, -52, 1, 4, 0, -48, 1, 4, 0, -44, 1, 0, 0, + -44, 1, 4, 0, -40, 1, 4, 0, -36, 1, 0, 0, -36, 1, 4, 0, + -32, 1, 4, 0, -28, 1, 0, 0, -28, 1, 0, 0, -28, 1, 4, 0, + -24, 1, 0, 0, -24, 1, 4, 0, -20, 1, 4, 0, -16, 1, 0, 0, + -16, 1, 4, 0, -12, 1, 4, 0, -8, 1, 0, 0, -8, 1, 4, 0, + -4, 1, 0, 0, -4, 1, 4, 0, 0, 2, 0, 0, 0, 2, 4, 0, + 4, 2, 4, 0, 8, 2, 0, 0, 8, 2, 4, 0, 12, 2, 0, 0, + 12, 2, 0, 0, 12, 2, 0, 0, 12, 2, 4, 0, 16, 2, 0, 0, + 16, 2, 4, 0, 20, 2, 0, 0, 20, 2, 4, 0, 24, 2, 4, 0, + 28, 2, 0, 0, 28, 2, 4, 0, 32, 2, 0, 0, 32, 2, 4, 0, + 36, 2, 0, 0, 36, 2, 0, 0, 36, 2, 4, 0, 40, 2, 0, 0, + 40, 2, 4, 0, 44, 2, 0, 0, 44, 2, 4, 0, 48, 2, 0, 0, + 48, 2, 4, 0, 52, 2, 0, 0, 52, 2, 4, 0, 56, 2, 0, 0, + 56, 2, 4, 0, 60, 2, 0, 0, 60, 2, 4, 0, 64, 2, 0, 0, + 64, 2, 0, 0, 64, 2, 4, 0, 68, 2, 0, 0, 68, 2, 4, 0, + 72, 2, 0, 0, 72, 2, 4, 0, 76, 2, 0, 0, 76, 2, 4, 0, + 80, 2, 0, 0, 80, 2, 0, 0, 80, 2, 4, 0, 84, 2, 0, 0, + 84, 2, 4, 0, 88, 2, 0, 0, 88, 2, 4, 0, 92, 2, 0, 0, + 92, 2, 4, 0, 96, 2, 0, 0, 96, 2, 4, 0, 100, 2, 0, 0, + 100, 2, 0, 0, 100, 2, 4, 0, 104, 2, 0, 0, 104, 2, 4, 0, + 108, 2, 0, 0, 108, 2, 4, 0, 112, 2, 0, 0, 112, 2, 0, 0, + 112, 2, 4, 0, 116, 2, 0, 0, 116, 2, 0, 0, 116, 2, 4, 0, + 120, 2, 0, 0, 120, 2, 4, 0, 124, 2, 0, 0, 124, 2, 4, 0, + -128, 2, 0, 0, -128, 2, 0, 0, -128, 2, 4, 0, -124, 2, 0, 0, + -124, 2, 0, 0, -124, 2, 4, 0, -120, 2, 0, 0, -120, 2, 4, 0, + -116, 2, 0, 0, -116, 2, 0, 0, -116, 2, 4, 0, -112, 2, 0, 0, + -112, 2, 4, 0, -108, 2, 0, 0, -108, 2, 4, 0, -104, 2, 0, 0, + -104, 2, 0, 0, -104, 2, 4, 0, -100, 2, 0, 0, -100, 2, 0, 0, + -100, 2, 4, 0, -96, 2, 0, 0, -96, 2, 0, 0, -96, 2, 4, 0, + -92, 2, 0, 0, -92, 2, 4, 0, -88, 2, 0, 0, -88, 2, 0, 0, + -88, 2, 4, 0, -84, 2, 0, 0, -84, 2, 0, 0, -84, 2, 0, 0, + -84, 2, 4, 0, -80, 2, 0, 0, -80, 2, 4, 0, -76, 2, 0, 0, + -76, 2, 4, 0, -72, 2, 0, 0, -72, 2, 0, 0, -72, 2, 4, 0, + -68, 2, 0, 0, -68, 2, 0, 0, -68, 2, 4, 0, -64, 2, 0, 0, + -64, 2, 0, 0, -64, 2, 4, 0, -60, 2, 0, 0, -60, 2, 0, 0, + -60, 2, 4, 0, -56, 2, 0, 0, -56, 2, 0, 0, -56, 2, 4, 0, + -52, 2, 0, 0, -52, 2, 4, 0, -48, 2, 0, 0, -48, 2, 0, 0, + -48, 2, 4, 0, -44, 2, 0, 0, -44, 2, 0, 0, -44, 2, 4, 0, + -40, 2, 0, 0, -40, 2, 0, 0, -40, 2, 0, 0, -40, 2, 4, 0, + -36, 2, 0, 0, -36, 2, 4, 0, -32, 2, 0, 0, -32, 2, 0, 0, + -32, 2, 4, 0, -28, 2, 0, 0, -28, 2, 0, 0, -28, 2, 4, 0, + -24, 2, 0, 0, -24, 2, 0, 0, -24, 2, 4, 0, -20, 2, 0, 0//, +// -20, 2, 0, 0, -20, 2, 0, 0, -20, 2, 4, 0, -16, 2, 0, 0, +// -16, 2, 0, 0, -16, 2, 4, 0, -12, 2, 0, 0, -12, 2, 4, 0, +// -8, 2, 0, 0, -8, 2, 0, 0, -8, 2, 0, 0, -8, 2, 4, 0, +// -4, 2, 0, 0, -4, 2, 4, 0, 0, 3, 0, 0, 0, 3, 0, 0, +// 0, 3, 4, 0, 4, 3, 0, 0, 4, 3, 0, 0, 4, 3, 0, 0, +// 4, 3, 4, 0, 8, 3, 0, 0, 8, 3, 0, 0, 8, 3, 0, 0, +// 8, 3, 4, 0, 12, 3, 0, 0, 12, 3, 4, 0, 16, 3, 0, 0, +// 16, 3, 0, 0, 16, 3, 4, 0, 20, 3, 0, 0, 20, 3, 0, 0, +// 20, 3, 4, 0, 24, 3, 0, 0, 24, 3, 0, 0, 24, 3, 0, 0, +// 24, 3, 4, 0, 28, 3, 0, 0, 28, 3, 0, 0, 28, 3, 0, 0, +// 28, 3, 4, 0, 32, 3, 0, 0, 32, 3, 4, 0, 36, 3, 0, 0, +// 36, 3, 0, 0, 36, 3, 4, 0, 40, 3, 0, 0, 40, 3, 0, 0, +// 40, 3, 0, 0, 40, 3, 4, 0, 44, 3, 0, 0, 44, 3, 0, 0, +// 44, 3, 4, 0, 48, 3, 0, 0, 48, 3, 0, 0, 48, 3, 0, 0, +// 48, 3, 4, 0, 52, 3, 0, 0, 52, 3, 0, 0, 52, 3, 0, 0, +// 52, 3, 4, 0, 56, 3, 0, 0, 56, 3, 0, 0, 56, 3, 4, 0, +// 60, 3, 0, 0, 60, 3, 0, 0, 60, 3, 4, 0, 64, 3, 0, 0, +// 64, 3, 4, 0, 68, 3, 0, 0, 68, 3, 0, 0, 68, 3, 0, 0, +// 68, 3, 4, 0, 72, 3, 0, 0, 72, 3, 0, 0, 72, 3, 0, 0, +// 72, 3, 4, 0, 76, 3, 0, 0, 76, 3, 0, 0, 76, 3, 4, 0, +// 80, 3, 0, 0, 80, 3, 0, 0, 80, 3, 0, 0, 80, 3, 4, 0, +// 84, 3, 0, 0, 84, 3, 0, 0, 84, 3, 0, 0, 84, 3, 4, 0, +// 88, 3, 0, 0, 88, 3, 0, 0, 88, 3, 4, 0, 92, 3, 0, 0, +// 92, 3, 0, 0, 92, 3, 0, 0, 92, 3, 4, 0, 96, 3, 0, 0, +// 96, 3, 0, 0, 96, 3, 0, 0, 96, 3, 4, 0, 100, 3, 0, 0, +// 100, 3, 0, 0, 100, 3, 4, 0, 104, 3, 0, 0, 104, 3, 0, 0, +// 104, 3, 0, 0, 104, 3, 4, 0, 108, 3, 0, 0, 108, 3, 0, 0, +// 108, 3, 4, 0, 112, 3, 0, 0, 112, 3, 0, 0, 112, 3, 0, 0, +// 112, 3, 4, 0, 116, 3, 0, 0, 116, 3, 0, 0, 116, 3, 0, 0, +// 116, 3, 0, 0, 116, 3, 4, 0, 120, 3, 0, 0, 120, 3, 0, 0, +// 120, 3, 0, 0, 120, 3, 4, 0, 124, 3, 0, 0, 124, 3, 0, 0, +// 124, 3, 0, 0, 124, 3, 4, 0, -128, 3, 0, 0, -128, 3, 0, 0, +// -128, 3, 4, 0, -124, 3, 0, 0, -124, 3, 0, 0, -124, 3, 4, 0, +// -120, 3, 0, 0, -120, 3, 0, 0, -120, 3, 0, 0, -120, 3, 4, 0, +// -116, 3, 0, 0, -116, 3, 0, 0, -116, 3, 4, 0, -112, 3, 0, 0, +// -112, 3, 0, 0, -112, 3, 0, 0, -112, 3, 4, 0, -108, 3, 0, 0, +// -108, 3, 0, 0, -108, 3, 0, 0, -108, 3, 0, 0, -108, 3, 4, 0, +// -104, 3, 0, 0, -104, 3, 0, 0, -104, 3, 4, 0, -100, 3, 0, 0, +// -100, 3, 0, 0, -100, 3, 4, 0, -96, 3, 0, 0, -96, 3, 0, 0, +// -96, 3, 0, 0, -96, 3, 4, 0, -92, 3, 0, 0, -92, 3, 0, 0, +// -92, 3, 0, 0, -92, 3, 0, 0, -92, 3, 4, 0, -88, 3, 0, 0, +// -88, 3, 0, 0, -88, 3, 4, 0, -84, 3, 0, 0, -84, 3, 0, 0, +// -84, 3, 0, 0, -84, 3, 4, 0, -80, 3, 0, 0, -80, 3, 0, 0, +// -80, 3, 0, 0, -80, 3, 0, 0, -80, 3, 4, 0, -76, 3, 0, 0, +// -76, 3, 0, 0, -76, 3, 4, 0, -72, 3, 0, 0, -72, 3, 0, 0, +// -72, 3, 0, 0, -72, 3, 0, 0, -72, 3, 4, 0, -68, 3, 0, 0, +// -68, 3, 0, 0, -68, 3, 0, 0, -68, 3, 4, 0, -64, 3, 0, 0, +// -64, 3, 0, 0, -64, 3, 4, 0, -60, 3, 0, 0, -60, 3, 0, 0, +// -60, 3, 0, 0, -60, 3, 0, 0, -60, 3, 4, 0, -56, 3, 0, 0, +// -56, 3, 0, 0, -56, 3, 0, 0, -56, 3, 4, 0, -52, 3, 0, 0, +// -52, 3, 0, 0, -52, 3, 0, 0, -52, 3, 4, 0, -48, 3, 0, 0, +// -48, 3, 0, 0, -48, 3, 0, 0, -48, 3, 4, 0, -44, 3, 0, 0, +// -44, 3, 0, 0, -44, 3, 0, 0, -44, 3, 4, 0, -40, 3, 0, 0, +// -40, 3, 0, 0, -40, 3, 0, 0, -40, 3, 4, 0, -36, 3, 0, 0, +// -36, 3, 0, 0, -36, 3, 0, 0, -36, 3, 4, 0, -32, 3, 0, 0, +// -32, 3, 0, 0, -32, 3, 0, 0, -32, 3, 0, 0, -32, 3, 4, 0, +// -28, 3, 0, 0, -28, 3, 0, 0, -28, 3, 0, 0, -28, 3, 0, 0, +// -28, 3, 4, 0, -24, 3, 0, 0, -24, 3, 0, 0, -24, 3, 4, 0, +// -20, 3, 0, 0, -20, 3, 0, 0, -20, 3, 0, 0, -20, 3, 0, 0, +// -20, 3, 4, 0, -16, 3, 0, 0, -16, 3, 0, 0, -16, 3, 0, 0, +// -16, 3, 4, 0, -12, 3, 0, 0, -12, 3, 0, 0, -12, 3, 0, 0, +// -12, 3, 4, 0, -8, 3, 0, 0, -8, 3, 0, 0, -8, 3, 0, 0, +// -8, 3, 0, 0, -8, 3, 4, 0, -4, 3, 0, 0, -4, 3, 0, 0, +// -4, 3, 0, 0, -4, 3, 0, 0, -4, 3, 0, 0, -4, 3, 0, 0 + }, + + /*pnGreenTable =*/ + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 4, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 8, 0, 4, 0, 12, 0, 0, 0, 12, 0, 4, 0, + 16, 0, 0, 0, 16, 0, 4, 0, 20, 0, 0, 0, 20, 0, 4, 0, + 24, 0, 4, 0, 28, 0, 4, 0, 32, 0, 8, 0, 40, 0, 8, 0, + 48, 0, 8, 0, 56, 0, 8, 0, 64, 0, 4, 0, 68, 0, 8, 0, + 76, 0, 4, 0, 80, 0, 8, 0, 88, 0, 8, 0, 96, 0, 4, 0, + 100, 0, 8, 0, 108, 0, 8, 0, 116, 0, 4, 0, 120, 0, 12, 0, + -124, 0, 8, 0, -116, 0, 4, 0, -112, 0, 8, 0, -104, 0, 4, 0, + -100, 0, 8, 0, -92, 0, 8, 0, -84, 0, 8, 0, -76, 0, 8, 0, + -68, 0, 8, 0, -60, 0, 8, 0, -52, 0, 8, 0, -44, 0, 8, 0, + -36, 0, 8, 0, -28, 0, 8, 0, -20, 0, 8, 0, -12, 0, 8, 0, + -4, 0, 8, 0, 4, 1, 8, 0, 12, 1, 8, 0, 20, 1, 8, 0, + 28, 1, 8, 0, 36, 1, 8, 0, 44, 1, 8, 0, 52, 1, 8, 0, + 60, 1, 8, 0, 68, 1, 8, 0, 76, 1, 4, 0, 80, 1, 8, 0, + 88, 1, 4, 0, 92, 1, 4, 0, 96, 1, 8, 0, 104, 1, 4, 0, + 108, 1, 4, 0, 112, 1, 8, 0, 120, 1, 4, 0, 124, 1, 4, 0, + -128, 1, 8, 0, -120, 1, 4, 0, -116, 1, 4, 0, -112, 1, 4, 0, + -108, 1, 4, 0, -104, 1, 4, 0, -100, 1, 4, 0, -96, 1, 0, 0, + -96, 1, 4, 0, -92, 1, 4, 0, -88, 1, 4, 0, -84, 1, 4, 0, + -80, 1, 4, 0, -76, 1, 4, 0, -72, 1, 4, 0, -68, 1, 4, 0, + -64, 1, 4, 0, -60, 1, 0, 0, -60, 1, 4, 0, -56, 1, 4, 0, + -52, 1, 0, 0, -52, 1, 4, 0, -48, 1, 4, 0, -44, 1, 0, 0, + -44, 1, 4, 0, -40, 1, 4, 0, -36, 1, 0, 0, -36, 1, 4, 0, + -32, 1, 4, 0, -28, 1, 0, 0, -28, 1, 0, 0, -28, 1, 4, 0, + -24, 1, 0, 0, -24, 1, 4, 0, -20, 1, 4, 0, -16, 1, 0, 0, + -16, 1, 4, 0, -12, 1, 4, 0, -8, 1, 0, 0, -8, 1, 4, 0, + -4, 1, 0, 0, -4, 1, 4, 0, 0, 2, 0, 0, 0, 2, 4, 0, + 4, 2, 4, 0, 8, 2, 0, 0, 8, 2, 4, 0, 12, 2, 0, 0, + 12, 2, 0, 0, 12, 2, 0, 0, 12, 2, 4, 0, 16, 2, 0, 0, + 16, 2, 4, 0, 20, 2, 0, 0, 20, 2, 4, 0, 24, 2, 4, 0, + 28, 2, 0, 0, 28, 2, 4, 0, 32, 2, 0, 0, 32, 2, 4, 0, + 36, 2, 0, 0, 36, 2, 0, 0, 36, 2, 4, 0, 40, 2, 0, 0, + 40, 2, 4, 0, 44, 2, 0, 0, 44, 2, 4, 0, 48, 2, 0, 0, + 48, 2, 4, 0, 52, 2, 0, 0, 52, 2, 4, 0, 56, 2, 0, 0, + 56, 2, 4, 0, 60, 2, 0, 0, 60, 2, 4, 0, 64, 2, 0, 0, + 64, 2, 0, 0, 64, 2, 4, 0, 68, 2, 0, 0, 68, 2, 4, 0, + 72, 2, 0, 0, 72, 2, 4, 0, 76, 2, 0, 0, 76, 2, 4, 0, + 80, 2, 0, 0, 80, 2, 0, 0, 80, 2, 4, 0, 84, 2, 0, 0, + 84, 2, 4, 0, 88, 2, 0, 0, 88, 2, 4, 0, 92, 2, 0, 0, + 92, 2, 4, 0, 96, 2, 0, 0, 96, 2, 4, 0, 100, 2, 0, 0, + 100, 2, 0, 0, 100, 2, 4, 0, 104, 2, 0, 0, 104, 2, 4, 0, + 108, 2, 0, 0, 108, 2, 4, 0, 112, 2, 0, 0, 112, 2, 0, 0, + 112, 2, 4, 0, 116, 2, 0, 0, 116, 2, 0, 0, 116, 2, 4, 0, + 120, 2, 0, 0, 120, 2, 4, 0, 124, 2, 0, 0, 124, 2, 4, 0, + -128, 2, 0, 0, -128, 2, 0, 0, -128, 2, 4, 0, -124, 2, 0, 0, + -124, 2, 0, 0, -124, 2, 4, 0, -120, 2, 0, 0, -120, 2, 4, 0, + -116, 2, 0, 0, -116, 2, 0, 0, -116, 2, 4, 0, -112, 2, 0, 0, + -112, 2, 4, 0, -108, 2, 0, 0, -108, 2, 4, 0, -104, 2, 0, 0, + -104, 2, 0, 0, -104, 2, 4, 0, -100, 2, 0, 0, -100, 2, 0, 0, + -100, 2, 4, 0, -96, 2, 0, 0, -96, 2, 0, 0, -96, 2, 4, 0, + -92, 2, 0, 0, -92, 2, 4, 0, -88, 2, 0, 0, -88, 2, 0, 0, + -88, 2, 4, 0, -84, 2, 0, 0, -84, 2, 0, 0, -84, 2, 0, 0, + -84, 2, 4, 0, -80, 2, 0, 0, -80, 2, 4, 0, -76, 2, 0, 0, + -76, 2, 4, 0, -72, 2, 0, 0, -72, 2, 0, 0, -72, 2, 4, 0, + -68, 2, 0, 0, -68, 2, 0, 0, -68, 2, 4, 0, -64, 2, 0, 0, + -64, 2, 0, 0, -64, 2, 4, 0, -60, 2, 0, 0, -60, 2, 0, 0, + -60, 2, 4, 0, -56, 2, 0, 0, -56, 2, 0, 0, -56, 2, 4, 0, + -52, 2, 0, 0, -52, 2, 4, 0, -48, 2, 0, 0, -48, 2, 0, 0, + -48, 2, 4, 0, -44, 2, 0, 0, -44, 2, 0, 0, -44, 2, 4, 0, + -40, 2, 0, 0, -40, 2, 0, 0, -40, 2, 0, 0, -40, 2, 4, 0, + -36, 2, 0, 0, -36, 2, 4, 0, -32, 2, 0, 0, -32, 2, 0, 0 + //, +// -32, 2, 4, 0, -28, 2, 0, 0, -28, 2, 0, 0, -28, 2, 4, 0, +// -24, 2, 0, 0, -24, 2, 0, 0, -24, 2, 4, 0, -20, 2, 0, 0, +// -20, 2, 0, 0, -20, 2, 0, 0, -20, 2, 4, 0, -16, 2, 0, 0, +// -16, 2, 0, 0, -16, 2, 4, 0, -12, 2, 0, 0, -12, 2, 4, 0, +// -8, 2, 0, 0, -8, 2, 0, 0, -8, 2, 0, 0, -8, 2, 4, 0, +// -4, 2, 0, 0, -4, 2, 4, 0, 0, 3, 0, 0, 0, 3, 0, 0, +// 0, 3, 4, 0, 4, 3, 0, 0, 4, 3, 0, 0, 4, 3, 0, 0, +// 4, 3, 4, 0, 8, 3, 0, 0, 8, 3, 0, 0, 8, 3, 0, 0, +// 8, 3, 4, 0, 12, 3, 0, 0, 12, 3, 4, 0, 16, 3, 0, 0, +// 16, 3, 0, 0, 16, 3, 4, 0, 20, 3, 0, 0, 20, 3, 0, 0, +// 20, 3, 4, 0, 24, 3, 0, 0, 24, 3, 0, 0, 24, 3, 0, 0, +// 24, 3, 4, 0, 28, 3, 0, 0, 28, 3, 0, 0, 28, 3, 0, 0, +// 28, 3, 4, 0, 32, 3, 0, 0, 32, 3, 4, 0, 36, 3, 0, 0, +// 36, 3, 0, 0, 36, 3, 4, 0, 40, 3, 0, 0, 40, 3, 0, 0, +// 40, 3, 0, 0, 40, 3, 4, 0, 44, 3, 0, 0, 44, 3, 0, 0, +// 44, 3, 4, 0, 48, 3, 0, 0, 48, 3, 0, 0, 48, 3, 0, 0, +// 48, 3, 4, 0, 52, 3, 0, 0, 52, 3, 0, 0, 52, 3, 0, 0, +// 52, 3, 4, 0, 56, 3, 0, 0, 56, 3, 0, 0, 56, 3, 4, 0, +// 60, 3, 0, 0, 60, 3, 0, 0, 60, 3, 4, 0, 64, 3, 0, 0, +// 64, 3, 4, 0, 68, 3, 0, 0, 68, 3, 0, 0, 68, 3, 0, 0, +// 68, 3, 4, 0, 72, 3, 0, 0, 72, 3, 0, 0, 72, 3, 0, 0, +// 72, 3, 4, 0, 76, 3, 0, 0, 76, 3, 0, 0, 76, 3, 4, 0, +// 80, 3, 0, 0, 80, 3, 0, 0, 80, 3, 0, 0, 80, 3, 4, 0, +// 84, 3, 0, 0, 84, 3, 0, 0, 84, 3, 0, 0, 84, 3, 4, 0, +// 88, 3, 0, 0, 88, 3, 0, 0, 88, 3, 4, 0, 92, 3, 0, 0, +// 92, 3, 0, 0, 92, 3, 0, 0, 92, 3, 4, 0, 96, 3, 0, 0, +// 96, 3, 0, 0, 96, 3, 0, 0, 96, 3, 4, 0, 100, 3, 0, 0, +// 100, 3, 0, 0, 100, 3, 4, 0, 104, 3, 0, 0, 104, 3, 0, 0, +// 104, 3, 0, 0, 104, 3, 4, 0, 108, 3, 0, 0, 108, 3, 0, 0, +// 108, 3, 4, 0, 112, 3, 0, 0, 112, 3, 0, 0, 112, 3, 0, 0, +// 112, 3, 4, 0, 116, 3, 0, 0, 116, 3, 0, 0, 116, 3, 0, 0, +// 116, 3, 0, 0, 116, 3, 4, 0, 120, 3, 0, 0, 120, 3, 0, 0, +// 120, 3, 0, 0, 120, 3, 4, 0, 124, 3, 0, 0, 124, 3, 0, 0, +// 124, 3, 0, 0, 124, 3, 4, 0, -128, 3, 0, 0, -128, 3, 0, 0, +// -128, 3, 4, 0, -124, 3, 0, 0, -124, 3, 0, 0, -124, 3, 4, 0, +// -120, 3, 0, 0, -120, 3, 0, 0, -120, 3, 0, 0, -120, 3, 4, 0, +// -116, 3, 0, 0, -116, 3, 0, 0, -116, 3, 4, 0, -112, 3, 0, 0, +// -112, 3, 0, 0, -112, 3, 0, 0, -112, 3, 4, 0, -108, 3, 0, 0, +// -108, 3, 0, 0, -108, 3, 0, 0, -108, 3, 0, 0, -108, 3, 4, 0, +// -104, 3, 0, 0, -104, 3, 0, 0, -104, 3, 4, 0, -100, 3, 0, 0, +// -100, 3, 0, 0, -100, 3, 4, 0, -96, 3, 0, 0, -96, 3, 0, 0, +// -96, 3, 0, 0, -96, 3, 4, 0, -92, 3, 0, 0, -92, 3, 0, 0, +// -92, 3, 0, 0, -92, 3, 0, 0, -92, 3, 4, 0, -88, 3, 0, 0, +// -88, 3, 0, 0, -88, 3, 4, 0, -84, 3, 0, 0, -84, 3, 0, 0, +// -84, 3, 0, 0, -84, 3, 4, 0, -80, 3, 0, 0, -80, 3, 0, 0, +// -80, 3, 0, 0, -80, 3, 0, 0, -80, 3, 4, 0, -76, 3, 0, 0, +// -76, 3, 0, 0, -76, 3, 4, 0, -72, 3, 0, 0, -72, 3, 0, 0, +// -72, 3, 0, 0, -72, 3, 0, 0, -72, 3, 4, 0, -68, 3, 0, 0, +// -68, 3, 0, 0, -68, 3, 0, 0, -68, 3, 4, 0, -64, 3, 0, 0, +// -64, 3, 0, 0, -64, 3, 4, 0, -60, 3, 0, 0, -60, 3, 0, 0, +// -60, 3, 0, 0, -60, 3, 0, 0, -60, 3, 4, 0, -56, 3, 0, 0, +// -56, 3, 0, 0, -56, 3, 0, 0, -56, 3, 4, 0, -52, 3, 0, 0, +// -52, 3, 0, 0, -52, 3, 0, 0, -52, 3, 4, 0, -48, 3, 0, 0, +// -48, 3, 0, 0, -48, 3, 0, 0, -48, 3, 4, 0, -44, 3, 0, 0, +// -44, 3, 0, 0, -44, 3, 0, 0, -44, 3, 4, 0, -40, 3, 0, 0, +// -40, 3, 0, 0, -40, 3, 0, 0, -40, 3, 4, 0, -36, 3, 0, 0, +// -36, 3, 0, 0, -36, 3, 0, 0, -36, 3, 4, 0, -32, 3, 0, 0, +// -32, 3, 0, 0, -32, 3, 0, 0, -32, 3, 0, 0, -32, 3, 4, 0, +// -28, 3, 0, 0, -28, 3, 0, 0, -28, 3, 0, 0, -28, 3, 0, 0, +// -28, 3, 4, 0, -24, 3, 0, 0, -24, 3, 0, 0, -24, 3, 4, 0, +// -20, 3, 0, 0, -20, 3, 0, 0, -20, 3, 0, 0, -20, 3, 0, 0, +// -20, 3, 4, 0, -16, 3, 0, 0, -16, 3, 0, 0, -16, 3, 0, 0, +// -16, 3, 4, 0, -12, 3, 0, 0, -12, 3, 0, 0, -12, 3, 0, 0, +// -12, 3, 4, 0, -8, 3, 0, 0, -8, 3, 0, 0, -8, 3, 0, 0, +// -8, 3, 0, 0, -8, 3, 4, 0, -4, 3, 0, 0, -4, 3, 0, 0, +// -4, 3, 0, 0, -4, 3, 0, 0, -4, 3, 0, 0, -4, 3, 0, 0 + } +}; + +static VCAM_3ASKIP_IPIPE_GBCE_CFGTYPE gbceDump = { + /*nEnable = */0, + /*nTyp = */(VCAM_3ASKIP_IPIPE_GBCE_METHODTYPE)1, + /*LookupTable =*/ + { + 0x0000, 0x0001, 0x0001, 0x0002, 0x0002, 0x0003, 0x0003, 0x0004, 0x0004, 0x0005, 0x0005, 0x0006, 0x0006, 0x0007, 0x0007, 0x0008, + 0x0008, 0x0009, 0x0009, 0x000a, 0x000a, 0x000b, 0x000b, 0x000c, 0x000c, 0x000d, 0x000d, 0x000e, 0x000e, 0x000f, 0x000f, 0x0010, + 0x0010, 0x0011, 0x0011, 0x0012, 0x0012, 0x0013, 0x0013, 0x0014, 0x0014, 0x0015, 0x0015, 0x0016, 0x0016, 0x0017, 0x0017, 0x0018, + 0x0018, 0x0019, 0x0019, 0x001a, 0x001a, 0x001b, 0x001b, 0x001c, 0x001c, 0x001d, 0x001d, 0x001e, 0x001e, 0x001f, 0x001f, 0x0020, + 0x0020, 0x0021, 0x0021, 0x0022, 0x0022, 0x0023, 0x0023, 0x0024, 0x0024, 0x0025, 0x0025, 0x0026, 0x0026, 0x0027, 0x0027, 0x0028, + 0x0028, 0x0029, 0x0029, 0x002a, 0x002a, 0x002b, 0x002b, 0x002c, 0x002c, 0x002d, 0x002d, 0x002e, 0x002e, 0x002f, 0x002f, 0x0030, + 0x0030, 0x0031, 0x0031, 0x0032, 0x0032, 0x0033, 0x0033, 0x0034, 0x0034, 0x0035, 0x0035, 0x0036, 0x0036, 0x0037, 0x0037, 0x0038, + 0x0038, 0x0039, 0x0039, 0x003a, 0x003a, 0x003b, 0x003b, 0x003c, 0x003c, 0x003c, 0x003c, 0x003c, 0x003c, 0x003d, 0x003d, 0x003d, + 0x003d, 0x003d, 0x003e, 0x003e, 0x003e, 0x003e, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x0040, 0x0040, 0x0040, 0x0040, 0x0040, + 0x0041, 0x0041, 0x0041, 0x0041, 0x0042, 0x0042, 0x0042, 0x0042, 0x0042, 0x0043, 0x0043, 0x0043, 0x0043, 0x0044, 0x0044, 0x0044, + 0x0044, 0x0044, 0x0045, 0x0045, 0x0045, 0x0045, 0x0045, 0x0046, 0x0046, 0x0046, 0x0046, 0x0047, 0x0047, 0x0047, 0x0047, 0x0047, + 0x0048, 0x0048, 0x0048, 0x0048, 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, 0x004a, 0x004a, 0x004a, 0x004a, 0x004a, 0x004b, 0x004b, + 0x004b, 0x004b, 0x004c, 0x004c, 0x004c, 0x004c, 0x004c, 0x004d, 0x004d, 0x004d, 0x004d, 0x004e, 0x004e, 0x004e, 0x004e, 0x004e, + 0x004f, 0x004f, 0x004f, 0x004f, 0x004f, 0x0050, 0x0050, 0x0050, 0x0050, 0x0051, 0x0051, 0x0051, 0x0051, 0x0051, 0x0052, 0x0052, + 0x0052, 0x0052, 0x0053, 0x0053, 0x0053, 0x0053, 0x0053, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054, 0x0055, 0x0055, 0x0055, 0x0055, + 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0057, 0x0057, 0x0057, 0x0057, 0x0057, 0x0058, 0x0058, 0x0058, 0x0058, 0x0059, 0x0059, + 0x0059, 0x0059, 0x0059, 0x005a, 0x005a, 0x005a, 0x005a, 0x005b, 0x005b, 0x005b, 0x005b, 0x005b, 0x005c, 0x005c, 0x005c, 0x005c, + 0x005c, 0x005d, 0x005d, 0x005d, 0x005d, 0x005e, 0x005e, 0x005e, 0x005e, 0x005e, 0x005f, 0x005f, 0x005f, 0x005f, 0x0060, 0x0060, + 0x0060, 0x0060, 0x0060, 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x0062, 0x0062, 0x0062, 0x0062, 0x0063, 0x0063, 0x0063, 0x0063, + 0x0063, 0x0064, 0x0064, 0x0064, 0x0064, 0x0065, 0x0065, 0x0065, 0x0065, 0x0065, 0x0066, 0x0066, 0x0066, 0x0066, 0x0066, 0x0067, + 0x0067, 0x0067, 0x0067, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0069, 0x0069, 0x0069, 0x0069, 0x006a, 0x006a, 0x006a, 0x006a, + 0x006a, 0x006b, 0x006b, 0x006b, 0x006b, 0x006b, 0x006c, 0x006c, 0x006c, 0x006c, 0x006d, 0x006d, 0x006d, 0x006d, 0x006d, 0x006e, + 0x006e, 0x006e, 0x006e, 0x006e, 0x006f, 0x006f, 0x006f, 0x006f, 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x0071, 0x0071, 0x0071, + 0x0071, 0x0072, 0x0072, 0x0072, 0x0072, 0x0072, 0x0073, 0x0073, 0x0073, 0x0073, 0x0073, 0x0074, 0x0074, 0x0074, 0x0074, 0x0075, + 0x0075, 0x0075, 0x0075, 0x0075, 0x0076, 0x0076, 0x0076, 0x0076, 0x0077, 0x0077, 0x0077, 0x0077, 0x0077, 0x0078, 0x0078, 0x0078, + 0x0078, 0x0078, 0x0079, 0x0079, 0x0079, 0x0079, 0x007a, 0x007a, 0x007a, 0x007a, 0x007a, 0x007b, 0x007b, 0x007b, 0x007b, 0x007c, + 0x007c, 0x007c, 0x007c, 0x007c, 0x007d, 0x007d, 0x007d, 0x007d, 0x007d, 0x007e, 0x007e, 0x007e, 0x007e, 0x007f, 0x007f, 0x007f, + 0x007f, 0x007f, 0x0080, 0x0080, 0x0080, 0x0080, 0x0081, 0x0081, 0x0081, 0x0081, 0x0081, 0x0082, 0x0082, 0x0082, 0x0082, 0x0082, + 0x0083, 0x0083, 0x0083, 0x0083, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0085, 0x0085, 0x0085, 0x0085, 0x0085, 0x0086, 0x0086, + 0x0086, 0x0086, 0x0087, 0x0087, 0x0087, 0x0087, 0x0087, 0x0088, 0x0088, 0x0088, 0x0088, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, + 0x008a, 0x008a, 0x008a, 0x008a, 0x008a, 0x008b, 0x008b, 0x008b, 0x008b, 0x008c, 0x008c, 0x008c, 0x008c, 0x008c, 0x008d, 0x008d, + 0x008d, 0x008d, 0x008e, 0x008e, 0x008e, 0x008e, 0x008e, 0x008f, 0x008f, 0x008f, 0x008f, 0x008f, 0x0090, 0x0090, 0x0090, 0x0090, + 0x0091, 0x0091, 0x0091, 0x0091, 0x0091, 0x0092, 0x0092, 0x0092, 0x0092, 0x0093, 0x0093, 0x0093, 0x0093, 0x0093, 0x0094, 0x0094, + 0x0094, 0x0094, 0x0094, 0x0095, 0x0095, 0x0095, 0x0095, 0x0096, 0x0096, 0x0096, 0x0096, 0x0096, 0x0097, 0x0097, 0x0097, 0x0097, + 0x0098, 0x0098, 0x0098, 0x0098, 0x0098, 0x0099, 0x0099, 0x0099, 0x0099, 0x0099, 0x009a, 0x009a, 0x009a, 0x009a, 0x009b, 0x009b, + 0x009b, 0x009b, 0x009b, 0x009c, 0x009c, 0x009c, 0x009c, 0x009c, 0x009d, 0x009d, 0x009d, 0x009d, 0x009e, 0x009e, 0x009e, 0x009e, + 0x009e, 0x009f, 0x009f, 0x009f, 0x009f, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a1, 0x00a1, 0x00a1, 0x00a1, 0x00a1, 0x00a2, + 0x00a2, 0x00a2, 0x00a2, 0x00a3, 0x00a3, 0x00a3, 0x00a3, 0x00a3, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a5, 0x00a5, 0x00a5, 0x00a5, + 0x00a5, 0x00a6, 0x00a6, 0x00a6, 0x00a6, 0x00a6, 0x00a7, 0x00a7, 0x00a7, 0x00a7, 0x00a8, 0x00a8, 0x00a8, 0x00a8, 0x00a8, 0x00a9, + 0x00a9, 0x00a9, 0x00a9, 0x00aa, 0x00aa, 0x00aa, 0x00aa, 0x00aa, 0x00ab, 0x00ab, 0x00ab, 0x00ab, 0x00ab, 0x00ac, 0x00ac, 0x00ac, + 0x00ac, 0x00ad, 0x00ad, 0x00ad, 0x00ad, 0x00ad, 0x00ae, 0x00ae, 0x00ae, 0x00ae, 0x00af, 0x00af, 0x00af, 0x00af, 0x00af, 0x00b0, + 0x00b0, 0x00b0, 0x00b0, 0x00b0, 0x00b1, 0x00b1, 0x00b1, 0x00b1, 0x00b2, 0x00b2, 0x00b2, 0x00b2, 0x00b2, 0x00b3, 0x00b3, 0x00b3, + 0x00b3, 0x00b4, 0x00b4, 0x00b4, 0x00b4, 0x00b4, 0x00b5, 0x00b5, 0x00b5, 0x00b5, 0x00b5, 0x00b6, 0x00b6, 0x00b6, 0x00b6, 0x00b7, + 0x00b7, 0x00b7, 0x00b7, 0x00b7, 0x00b8, 0x00b8, 0x00b8, 0x00b8, 0x00b8, 0x00b9, 0x00b9, 0x00b9, 0x00b9, 0x00ba, 0x00ba, 0x00ba, + 0x00ba, 0x00ba, 0x00bb, 0x00bb, 0x00bb, 0x00bb, 0x00bc, 0x00bc, 0x00bc, 0x00bc, 0x00bc, 0x00bd, 0x00bd, 0x00bd, 0x00bd, 0x00bd, + 0x00be, 0x00be, 0x00be, 0x00be, 0x00bf, 0x00bf, 0x00bf, 0x00bf, 0x00bf, 0x00c0, 0x00c0, 0x00c0, 0x00c0, 0x00c1, 0x00c1, 0x00c1, + 0x00c1, 0x00c1, 0x00c2, 0x00c2, 0x00c2, 0x00c2, 0x00c2, 0x00c3, 0x00c3, 0x00c3, 0x00c3, 0x00c4, 0x00c4, 0x00c4, 0x00c4, 0x00c4, + 0x00c5, 0x00c5, 0x00c5, 0x00c5, 0x00c6, 0x00c6, 0x00c6, 0x00c6, 0x00c6, 0x00c7, 0x00c7, 0x00c7, 0x00c7, 0x00c7, 0x00c8, 0x00c8, + 0x00c8, 0x00c8, 0x00c9, 0x00c9, 0x00c9, 0x00c9, 0x00c9, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00cb, 0x00cb, 0x00cb, 0x00cb, 0x00cb, + 0x00cc, 0x00cc, 0x00cc, 0x00cc, 0x00cc, 0x00cd, 0x00cd, 0x00cd, 0x00cd, 0x00ce, 0x00ce, 0x00ce, 0x00ce, 0x00ce, 0x00cf, 0x00cf, + 0x00cf, 0x00cf, 0x00cf, 0x00d0, 0x00d0, 0x00d0, 0x00d0, 0x00d1, 0x00d1, 0x00d1, 0x00d1, 0x00d1, 0x00d2, 0x00d2, 0x00d2, 0x00d2, + 0x00d3, 0x00d3, 0x00d3, 0x00d3, 0x00d3, 0x00d4, 0x00d4, 0x00d4, 0x00d4, 0x00d4, 0x00d5, 0x00d5, 0x00d5, 0x00d5, 0x00d6, 0x00d6, + 0x00d6, 0x00d6, 0x00d6, 0x00d7, 0x00d7, 0x00d7, 0x00d7, 0x00d8, 0x00d8, 0x00d8, 0x00d8, 0x00d8, 0x00d9, 0x00d9, 0x00d9, 0x00d9, + 0x00d9, 0x00da, 0x00da, 0x00da, 0x00da, 0x00db, 0x00db, 0x00db, 0x00db, 0x00db, 0x00dc, 0x00dc, 0x00dc, 0x00dc, 0x00dd, 0x00dd, + 0x00dd, 0x00dd, 0x00dd, 0x00de, 0x00de, 0x00de, 0x00de, 0x00de, 0x00df, 0x00df, 0x00df, 0x00df, 0x00e0, 0x00e0, 0x00e0, 0x00e0, + 0x00e0, 0x00e1, 0x00e1, 0x00e1, 0x00e1, 0x00e2, 0x00e2, 0x00e2, 0x00e2, 0x00e2, 0x00e3, 0x00e3, 0x00e3, 0x00e3, 0x00e3, 0x00e4, + 0x00e4, 0x00e4, 0x00e4, 0x00e5, 0x00e5, 0x00e5, 0x00e5, 0x00e5, 0x00e6, 0x00e6, 0x00e6, 0x00e6, 0x00e6, 0x00e7, 0x00e7, 0x00e7, + 0x00e7, 0x00e8, 0x00e8, 0x00e8, 0x00e8, 0x00e8, 0x00e9, 0x00e9, 0x00e9, 0x00e9, 0x00ea, 0x00ea, 0x00ea, 0x00ea, 0x00ea, 0x00eb, + 0x00eb, 0x00eb, 0x00eb, 0x00eb, 0x00ec, 0x00ec, 0x00ec, 0x00ec, 0x00ed, 0x00ed, 0x00ed, 0x00ed, 0x00ed, 0x00ee, 0x00ee, 0x00ee, + 0x00ee, 0x00ef, 0x00ef, 0x00ef, 0x00ef, 0x00ef, 0x00f0, 0x00f0, 0x00f0, 0x00f0, 0x00f0, 0x00f1, 0x00f1, 0x00f1, 0x00f1, 0x00f2, + 0x00f2, 0x00f2, 0x00f2, 0x00f2, 0x00f3, 0x00f3, 0x00f3, 0x00f3, 0x00f4, 0x00f4, 0x00f4, 0x00f4, 0x00f4, 0x00f5, 0x00f5, 0x00f5, + 0x00f5, 0x00f5, 0x00f6, 0x00f6, 0x00f6, 0x00f6, 0x00f7, 0x00f7, 0x00f7, 0x00f7, 0x00f7, 0x00f8, 0x00f8, 0x00f8, 0x00f8, 0x00f9, + 0x00f9, 0x00f9, 0x00f9, 0x00f9, 0x00fa, 0x00fa, 0x00fa, 0x00fa, 0x00fa, 0x00fb, 0x00fb, 0x00fb, 0x00fb, 0x00fc, 0x00fc, 0x00fc, + 0x00fc, 0x00fc, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fe, 0x00fe, 0x00fe, 0x00fe, 0x00ff, 0x00ff, 0x00ff, 0x00ff, 0x00ff + } +}; diff --git a/source/dvp/VisionCam/Params3Adump_mod.h b/source/dvp/VisionCam/Params3Adump_mod.h new file mode 100644 index 0000000..eba0793 --- /dev/null +++ b/source/dvp/VisionCam/Params3Adump_mod.h @@ -0,0 +1,1097 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +static VCAM_3ASKIP_IPIPE_3DCC_CFGTYPE t3dccDump = { + /*.enable = */0, + /*.pInBiffData = */NULL +}; + +static VCAM_3ASKIP_IPIPE_BOXCAR_CFGTYPE boxCarDump = { + /*.nEnable = */0, + /*.nOst = */1, + /*.nBoxSize = */1, + /*.nShift = */1, + /*.pAddr = */0 +}; + +static VCAM_3ASKIP_IPIPE_BSC_CFGTYPE bscDump = { + /*.nEnable = */0, + /*.nMode = */1, + /*.nColSample = */1, + /*.nRowSample = */1, + /*.nElement = */0, + { + /*.nColPos.nVectors = */ 8, + /*.nColPos.nShift = */ 8, + /*.nColPos.nVPos = */ 8, + /*.nColPos.nHPos = */ 8, + /*.nColPos.nVNum = */ 8, + /*.nColPos.nHNum = */ 8, + /*.nColPos.nVSkip = */ 8, + /*.nColPos.nHSkip = */ 8 + }, + { + /*.nRowPos.nVectors = */ 8, + /*.nRowPos.nShift = */ 8, + /*.nRowPos.nVPos = */ 8, + /*.nRowPos.nHPos = */ 8, + /*.nRowPos.nVNum = */ 8, + /*.nRowPos.nHNum = */ 8, + /*.nRowPos.nVSkip = */ 8, + /*.nRowPos.nHSkip = */ 8 + } +}; + +static VCAM_3ASKIP_IPIPE_CAR_CFGTYPE carDump = { + /*.nEnable = */ 0, + /*.nTyp = */ 1, + /*.nSw0Thr = */ 1, + /*.nSw1Thr = */ 1, + /*.nHpfType = */ 1, + /*.nHpfShift = */ 1, + /*.nHpfThr = */ 1, + /*.nGn1Gain = */ 1, + /*.nGn1Shift = */ 1, + /*.nGn1Min = */ 1, + /*.nGn2Gain = */ 1, + /*.nGn2Shift = */ 1, + /*.nGn2Min = */ 1 +}; + +static VCAM_3ASKIP_IPIPE_CFA_CFGTYPE cfaDump = { + /*.nEnable = */0, + /*.eMode = */(VCAM_3ASKIP_IPIPE_CFA_MODETYPE)1, + { + /*.tDir.nHpfThr = */ 16, + /*.tDir.nHpfSlope = */ 16, + /*.tDir.nMixThr = */ 16, + /*.tDir.nMixSlope = */ 16, + /*.tDir.nDirThr = */ 16, + /*.tDir.nDirSlope = */ 16, + /*.tDir.nDirNdwt = */ 16 + }, + { + /*.tDaa.nMonoHueFra = */ 8, + /*.tDaa.nMonoEdgThr = */ 8, + /*.tDaa.nMonoThrMin = */ 8, + /*.tDaa.nMonoThrSlope = */ 8, + /*.tDaa.nMonoSlpMin = */ 8, + /*.tDaa.nMonoSlpSlp = */ 8, + /*.tDaa.nMonoLpwt = */ 8 + } +}; + +static VCAM_3ASKIP_IPIPE_CGS_CFGTYPE cgsDump = { + /*.enable = */0, + { + /*.y_chroma_low.thr = */ 8, + /*.y_chroma_low.gain = */ 16, + /*.y_chroma_low.shift = */ 16, + /*.y_chroma_low.min = */ 16 + }, + { + /*.y_chroma_high.thr = */ 8, + /*.y_chroma_high.gain = */ 16, + /*.y_chroma_high.shift = */ 16, + /*.y_chroma_high.min = */ 16 + }, + { + /*.c_chroma.thr = */ 8, + /*.c_chroma.gain = */ 16, + /*.c_chroma.shift = */ 16, + /*.c_chroma.min = */ 16 + } +}; + +static VCAM_3ASKIP_ISIF_CLAMP_CFGTYPE clampDump = { + /*.nEnable = */0, + /*.eHClampMode = */(VCAM_3ASKIP_ISIF_HORIZONTAL_CLAMP_MODETYPE)1, + /*.eBlackClampMode = */(VCAM_3ASKIP_ISIF_BLACK_CLAMP_MODETYPE)1, + /*.nDCOffsetClampVal = */ 128, + /*.nBlackClampVStartPos = */128, + { + /*.tHorizontalBlack.nVPos = */ 64, + /*.tHorizontalBlack.eVSize = */ 64, + /*.tHorizontalBlack.nHPos = */ 64, + /*.tHorizontalBlack.eHSize = */(VCAM_3ASKIP_ISIF_VBLACK_PIXEL_WIDTHTYPE)0, + /*.tHorizontalBlack.line_avg_coef = */64, + /*.tHorizontalBlack.reset_mode = */(VCAM_3ASKIP_ISIF_VBLACK_RESET_MODETYPE)2, + /*.tHorizontalBlack.reset_value = */2 + }, + { + /*.tVerticalBlack.nVPos = */ 64, + /*.tVerticalBlack.nVSize = */ 64, + /*.tVerticalBlack.nHPos = */ 64, + /*.tVerticalBlack.HSize = */(VCAM_3ASKIP_ISIF_VBLACK_PIXEL_WIDTHTYPE)0, + /*.tVerticalBlack.line_avg_coef = */64, + /*.tVerticalBlack.reset_mode = */(VCAM_3ASKIP_ISIF_VBLACK_RESET_MODETYPE)2, + /*.tVerticalBlack.reset_value = */2 + } +}; + +static VCAM_3ASKIP_IPIPEIF_DFS_CFGTYPE dfsDump = { + /*.eDfsGainEn = */(VCAM_3ASKIP_IPIPEIF_FEATURE_SELECTTYPE)1, + /*.nDfsGainVal = */ 128, + /*.nDfsGainThr = */ 64, + /*.nOclip = */ 16, + /*.nDfsDir = */ 16 +}; + +static VCAM_3ASKIP_IPIPEIF_DPC_CFGTYPE dpc1Dump = { + /*.eDpcEn = */(VCAM_3ASKIP_IPIPEIF_FEATURE_SELECTTYPE)1, + /*.eDpcThr = */1 +}; + +static VCAM_3ASKIP_IPIPEIF_DPC_CFGTYPE dpc2Dump = { + /*.eDpcEn = */(VCAM_3ASKIP_IPIPEIF_FEATURE_SELECTTYPE)1, + /*.eDpcThr = */1 +}; + +static VCAM_3ASKIP_IPIPEIF_DPCM_CFGTYPE dpcmDump = { + /*.nDpcmBitSize = */ (VCAM_3ASKIP_IPIPEIF_FEATURE_SELECTTYPE)1, + /*.nDpcmEn = */ (VCAM_3ASKIP_IPIPEIF_DPCM_PRED_TYPTYPE)1, + /*.nDpcmPredictor = */ (VCAM_3ASKIP_IPIPEIF_DPCM_BIT_SIZETYPE)1 +}; + +static VCAM_3ASKIP_IPIPE_DPCLUT_CFGTYPE dpcLutDump = { + /*.nEnable = */0, + /*.eTableType = */(VCAM_3ASKIP_IPIPE_DPC_LUT_TBL_SIZETYPE)1, + /*.eReplaceType = */(VCAM_3ASKIP_IPIPE_DPC_LUT_REPLACEMENTTYPE)1, + /*.nLutValidAddr = */0, + /*.nLutSize = */256, + /*.nLutTable0Addr = */0, + /*.nLutTable1Addr = */0 +}; + + +//VCAM_3ASKIP_IPIPEIF_DPCM_CFGTYPE ptDpcm { +//OMX_TI_3ASKIP_IPIPEIF_FEATURE_SELECTTYPE nDpcmEn +//OMX_TI_3ASKIP_IPIPEIF_DPCM_PRED_TYPTYPE nDpcmPredictor +//OMX_TI_3ASKIP_IPIPEIF_DPCM_BIT_SIZETYPE nDpcmBitSize +//}; + +static VCAM_3ASKIP_IPIPE_DPCOTF_CFGTYPE dpcOtfDump; + +static VCAM_3ASKIP_ISIF_GAINOFFSET_CFGTYPE gainOffsetDump = { + /*.gain_offset_featureflag = */256, + /*.gain_r = */ 128, + /*.gain_gr = */ 128, + /*.gain_gb = */ 128, + /*.gain_bg = */ 128, + /*.offset = */ 128 +}; + + +static VCAM_3ASKIP_IPIPE_GIC_CFGTYPE gicDump = { + /*.nEnable = */0, + /*.eLscGain = */(VCAM_3ASKIP_IPIPE_GIC_LSC_GAINTYPE)1, + /*.eSel = */(VCAM_3ASKIP_IPIPE_GIC_SELTYPE)1, + /*.eTyp = */(VCAM_3ASKIP_IPIPE_GIC_INDEXTYPE)1, + /*.nGicGain = */1, + /*.nGicNfGain = */1, + /*.nGicThr = */1, + /*.nGicSlope = */1 +}; + +static VCAM_3ASKIP_H3A_AEWB_PARAMTYPE h3aAewbDump = { + /*.eAewbEnable = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)0, + /*.ptAewbPaxelWin = */0, + /*.ptBlkWinDims = */0, + /*.eAeOpFmt = */(VCAM_3ASKIP_H3A_AEWB_OP_FMTTYPE)1, + /*.nShiftValue = */128, + /*.nSaturationLimit = */50, + /*.nAewbOpAddr = */0 +}; + +static VCAM_3ASKIP_H3A_COMMON_CFGTYPE h3aCommonDump = { + /*.eAfMedianEn = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE) 1, + /*.eAewbMedianEn = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)1, + /*.nMedianFilterThreshold = */8, + /*.eAfAlawEn = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)1, + /*.eAewbAlawEn = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)1, + /*.eIpipeifAveFiltEn = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)1, + /*.eH3aDecimEnable = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)1 + /*.nReserved = */ // 0 +}; + +static VCAM_3ASKIP_IPIPE_HIST_CFGTYPE histDump = { + /*.nEnable = */ 0, + /*.nOst = */ 8, + /*.nSel = */ 8, + /*.nType = */ 8, + /*.nBins = */ 8, + /*.nShift = */ 8, + /*.nCol = */ 8, + /*.nRegions = */ 8, + /*.ptHistDim = */ 8, + /*.nClearTable = */ 8, + /*.nTableSel = */ 8, + /*.pnGainTbl = */ 8 +}; + +static VCAM_3ASKIP_RSZ_LPF_CFGTYPE hlpfDump = { + /*.nCIntensity = */1, + /*.nYIntensity = */1 +}; + +static VCAM_3ASKIP_ISIF_2DLSC_CFGTYPE lsc2dDump = { + /*.nEnable = */0, + /*.nLscHSize = */8, + /*.nLscVSize = */8, + /*.nHDirDataOffset = */16, + /*.nVDirDataOffset = */16, + /*.nHPosInPaxel = */16, + /*.nVPosInPaxel = */16, + /*.ePaxHeight = */(VCAM_3ASKIP_ISIF_LSC_GAIN_MODE_MNTYPE)1, + /*.ePaxLength = */(VCAM_3ASKIP_ISIF_LSC_GAIN_MODE_MNTYPE)1, + /*.eGainFormat = */(VCAM_3ASKIP_ISIF_LSC_GAIN_FORMATTYPE)1, + /*.nOffsetScalingFactor = */16, + /*.eOffsetShiftVal = */(VCAM_3ASKIP_ISIF_LSC_OFFSET_SHIFTTYPE)1, + /*.eOffsetEnable = */(VCAM_3ASKIP_ISIF_LSC_OFFSET_ENABLETYPE)1, + /*.nGainTableAddress = */ 16, //4294967040 + /*.nGainTableLength = */ 16, + /*.nOffsetTableAddress = */ 16, //4294967040 + /*.nOffsetTableLength = */ 16 +}; + +static VCAM_3ASKIP_IPIPE_LSC_CFGTYPE lscDump = { + /*.nVOffset = */ 8, + /*.nVLinearCoeff = */ 8, + /*.nVQuadraticCoeff = */ 8, + /*.nVLinearShift = */ 8, + /*.nVQuadraticShift = */ 8, + /*.nHOffset = */ 8, + /*.nHLinearCoeff = */ 8, + /*.nHQuadraticCoeff = */ 8, + /*.nHLinearShift = */ 8, + /*.nHQuadraticShift = */ 8, + /*.nGainR = */ 8, + /*.nGainGR = */ 8, + /*.nGainGB = */ 8, + /*.nGainB = */ 8, + /*.nOffR = */ 8, + /*.nOffGR = */ 8, + /*.nOffGB = */ 8, + /*.nOffB = */ 8, + /*.nShift = */ 8, + /*.nMax = */ 8 +}; + +static VCAM_3ASKIP_IPIPE_NOISE_FILTER_CFGTYPE nf1Dump = { + /*.nEnable = */0, + /*.eNFNum = */(VCAM_3ASKIP_IPIPE_NOISE_FILTERTYPE)1, + /*.eSel = */(VCAM_3ASKIP_IPIPE_NF_SELTYPE)1, + /*.eLscGain = */(VCAM_3ASKIP_IPIPE_NF_LSC_GAINTYPE)1, + /*.eTyp = */(VCAM_3ASKIP_IPIPE_NF_SAMPLE_METHODTYPE)1, + /*.nDownShiftVal = */1, + /*.nSpread = */1, + + /*.pnThr = */ + { + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F + }, + + /*.pnStr = */ + { + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F + }, + + /*.pnSpr = */ + { + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F + }, + /*.nEdgeMin = */15, + /*.nEdgeMax = */15 +}; + +static VCAM_3ASKIP_IPIPE_NOISE_FILTER_CFGTYPE nf2Dump = { + /*.nEnable = */0, + /*.eNFNum = */(VCAM_3ASKIP_IPIPE_NOISE_FILTERTYPE)1, + /*.eSel = */(VCAM_3ASKIP_IPIPE_NF_SELTYPE)1, + /*.eLscGain = */(VCAM_3ASKIP_IPIPE_NF_LSC_GAINTYPE)1, + /*.eTyp = */(VCAM_3ASKIP_IPIPE_NF_SAMPLE_METHODTYPE)1, + /*.nDownShiftVal = */1, + /*.nSpread = */1, + + /*.pnThr = */ + { + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F + }, + + /*.pnStr = */ + { + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F + }, + + /*.pnSpr = */ + { + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + }, + + /*.nEdgeMin = */15, + /*.nEdgeMax = */15 +}; + +static VCAM_3ASKIP_IPIPE_RGBRGB_CFGTYPE rgb2rgb1Dump = { + /*.pnMulOff = */ + { + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F + }, + /*.pnOft = */ + { + 0x000F, + 0x000F, + 0x000F + } +}; + + +static VCAM_3ASKIP_IPIPE_RGBRGB_CFGTYPE rgb2rgb2Dump = { + /*.pnMulOff = */ + { + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F + }, + /*.pnOft = */ + { + 0x000F, + 0x000F, + 0x000F + } +}; + +static VCAM_3ASKIP_IPIPE_RGBYUV_CFGTYPE rgb2yuvDump = { + /*.nBrightness = */50, + /*.nContrast = */50, + /*.pnMulVal = */ + { + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F, + 0x000F + }, + /*.pnOffset = */ + { + 0x000F, + 0x000F, + 0x000F + }, +}; + +static VCAM_3ASKIP_ISIF_VLDC_CFGTYPE vldcDump = { + /*.nEnable = */0, + /*.eDisableVldcUpperPixels = */(VCAM_3ASKIP_ISIF_VDLC_PIXEL_DEPENDENCYTYPE)1, + /*.nVldcShiftVal = */64, + /*.eVldcModeSelect = */(VCAM_3ASKIP_ISIF_VLDC_MODE_SELECTTYPE)1, + /*.nVldcSaturationLvl = */64, + /*.nDefectLines = */4, + { + /*.tVldcDefectLineParams.nVerticalDefectPosition = */ 8, + /*.tVldcDefectLineParams.nHorizontalDefectPosition = */ 8, + /*.tVldcDefectLineParams.nSub1ValueVldc = */ 8, + /*.tVldcDefectLineParams.nSub2LessThanVldc = */ 8, + /*.tVldcDefectLineParams.nSub3GreaterThanVldc = */ 8 + } +}; + +static VCAM_3ASKIP_RSZ_LPF_CFGTYPE vlpDump = { + /*.nCIntensity = */1, + /*.nYIntensity = */1 +}; + +static VCAM_3ASKIP_IPIPE_WB_CFGTYPE wbDump = { + /*.pnOffset = */ + { + 0x0200, + 0x0200, + 0x0400, + 0x0400 + }, + /*.pnGain = */ + { + 0x0200, + 0x0200, + 0x0400, + 0x0400 + } +}; + +static VCAM_3ASKIP_IPIPE_YUV444YUV422_CFGTYPE yuv2yuvDump = { + /*.ePos = */(VCAM_3ASKIP_IPIPE_YUV_PHASE_POSTYPE)1, + /*.nLpfEn = */15 +}; + + + +static VCAM_3ASKIP_H3A_AF_PARAMTYPE h3aAfDump = { + /*eAfEnable = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)1, + /*eRgbPos = */(VCAM_3ASKIP_H3A_RGB_POSTYPE)1, + /*ePeakModeEn = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)1, + /*eVerticalFocusEn = */(VCAM_3ASKIP_H3A_FEATURE_ENABLETYPE)1, + /*nIirStartPos = */1, + /*ptAfPaxelWin = */ + { + 0 ,0, 0, 0, 0, 0, 0, 0 + }, + /*ptIir1 = */ {0, 0}, + /*ptIir2 = */{0, 0}, + /*ptFir1 = */{0, 0}, + /*ptFir2 = */{0, 0}, + /*nAfOpAddr = */0 +}; + + +static VCAM_3ASKIP_CAM_CONTROL_EXPGAINTYPE expCtrlDump = { + /*exp =*/ 8, + /*a_gain = */8, + /*mask = */8, + /*nAgainErr = */8, + /*nDigitalISPGain = */8 +}; + +static VCAM_3ASKIP_IPIPE_EE_CFGTYPE edgeEnhDump = { + /*nEnable = */0, + /*eHaloReduction = */(VCAM_3ASKIP_IPIPE_EE_HALO_CTRLTYPE)0, + /*pnMulVal =*/ + { + 0x0008, + 0x0008, + 0x0008, + 0x0008, + 0x0008, + 0x0008, + 0x0008, + 0x0008, + 0x0008 + }, + /*nSel = */1, + /*nShiftHp = */1, + /*nThreshold = */4, + /*nGain = */8, + /*nHpfLowThr = */8, + /*nHpfHighThr = */8, + /*nHpfGradientGain = */8, + /*nHpfgradientOffset = */8, + /*pnEeTable =*/ + { + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 77 + } +}; + +static VCAM_3ASKIP_IPIPE_GAMMA_CFGTYPE gammaDump = { + /*nEnable = */0, + /*eGammaTblSize = */(VCAM_3ASKIP_IPIPE_GAMMA_TABLE_SIZETYPE)256, + /*nTbl = */256, + /*eBypassB = */(VCAM_3ASKIP_IPIPE_GAMMA_BYPASSTYPE)1, + /*eBypassG = */(VCAM_3ASKIP_IPIPE_GAMMA_BYPASSTYPE)1, + /*eBypassR = */(VCAM_3ASKIP_IPIPE_GAMMA_BYPASSTYPE)1, + /*pnRedTable =*/ + { + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 77 +// -20, 2, 0, 0, -20, 2, 0, 0, -20, 2, 4, 0, -16, 2, 0, 0, +// -16, 2, 0, 0, -16, 2, 4, 0, -12, 2, 0, 0, -12, 2, 4, 0, +// -8, 2, 0, 0, -8, 2, 0, 0, -8, 2, 0, 0, -8, 2, 4, 0, +// -4, 2, 0, 0, -4, 2, 4, 0, 0, 3, 0, 0, 0, 3, 0, 0, +// 0, 3, 4, 0, 4, 3, 0, 0, 4, 3, 0, 0, 4, 3, 0, 0, +// 4, 3, 4, 0, 8, 3, 0, 0, 8, 3, 0, 0, 8, 3, 0, 0, +// 8, 3, 4, 0, 12, 3, 0, 0, 12, 3, 4, 0, 16, 3, 0, 0, +// 16, 3, 0, 0, 16, 3, 4, 0, 20, 3, 0, 0, 20, 3, 0, 0, +// 20, 3, 4, 0, 24, 3, 0, 0, 24, 3, 0, 0, 24, 3, 0, 0, +// 24, 3, 4, 0, 28, 3, 0, 0, 28, 3, 0, 0, 28, 3, 0, 0, +// 28, 3, 4, 0, 32, 3, 0, 0, 32, 3, 4, 0, 36, 3, 0, 0, +// 36, 3, 0, 0, 36, 3, 4, 0, 40, 3, 0, 0, 40, 3, 0, 0, +// 40, 3, 0, 0, 40, 3, 4, 0, 44, 3, 0, 0, 44, 3, 0, 0, +// 44, 3, 4, 0, 48, 3, 0, 0, 48, 3, 0, 0, 48, 3, 0, 0, +// 48, 3, 4, 0, 52, 3, 0, 0, 52, 3, 0, 0, 52, 3, 0, 0, +// 52, 3, 4, 0, 56, 3, 0, 0, 56, 3, 0, 0, 56, 3, 4, 0, +// 60, 3, 0, 0, 60, 3, 0, 0, 60, 3, 4, 0, 64, 3, 0, 0, +// 64, 3, 4, 0, 68, 3, 0, 0, 68, 3, 0, 0, 68, 3, 0, 0, +// 68, 3, 4, 0, 72, 3, 0, 0, 72, 3, 0, 0, 72, 3, 0, 0, +// 72, 3, 4, 0, 76, 3, 0, 0, 76, 3, 0, 0, 76, 3, 4, 0, +// 80, 3, 0, 0, 80, 3, 0, 0, 80, 3, 0, 0, 80, 3, 4, 0, +// 84, 3, 0, 0, 84, 3, 0, 0, 84, 3, 0, 0, 84, 3, 4, 0, +// 88, 3, 0, 0, 88, 3, 0, 0, 88, 3, 4, 0, 92, 3, 0, 0, +// 92, 3, 0, 0, 92, 3, 0, 0, 92, 3, 4, 0, 96, 3, 0, 0, +// 96, 3, 0, 0, 96, 3, 0, 0, 96, 3, 4, 0, 100, 3, 0, 0, +// 100, 3, 0, 0, 100, 3, 4, 0, 104, 3, 0, 0, 104, 3, 0, 0, +// 104, 3, 0, 0, 104, 3, 4, 0, 108, 3, 0, 0, 108, 3, 0, 0, +// 108, 3, 4, 0, 112, 3, 0, 0, 112, 3, 0, 0, 112, 3, 0, 0, +// 112, 3, 4, 0, 116, 3, 0, 0, 116, 3, 0, 0, 116, 3, 0, 0, +// 116, 3, 0, 0, 116, 3, 4, 0, 120, 3, 0, 0, 120, 3, 0, 0, +// 120, 3, 0, 0, 120, 3, 4, 0, 124, 3, 0, 0, 124, 3, 0, 0, +// 124, 3, 0, 0, 124, 3, 4, 0, -128, 3, 0, 0, -128, 3, 0, 0, +// -128, 3, 4, 0, -124, 3, 0, 0, -124, 3, 0, 0, -124, 3, 4, 0, +// -120, 3, 0, 0, -120, 3, 0, 0, -120, 3, 0, 0, -120, 3, 4, 0, +// -116, 3, 0, 0, -116, 3, 0, 0, -116, 3, 4, 0, -112, 3, 0, 0, +// -112, 3, 0, 0, -112, 3, 0, 0, -112, 3, 4, 0, -108, 3, 0, 0, +// -108, 3, 0, 0, -108, 3, 0, 0, -108, 3, 0, 0, -108, 3, 4, 0, +// -104, 3, 0, 0, -104, 3, 0, 0, -104, 3, 4, 0, -100, 3, 0, 0, +// -100, 3, 0, 0, -100, 3, 4, 0, -96, 3, 0, 0, -96, 3, 0, 0, +// -96, 3, 0, 0, -96, 3, 4, 0, -92, 3, 0, 0, -92, 3, 0, 0, +// -92, 3, 0, 0, -92, 3, 0, 0, -92, 3, 4, 0, -88, 3, 0, 0, +// -88, 3, 0, 0, -88, 3, 4, 0, -84, 3, 0, 0, -84, 3, 0, 0, +// -84, 3, 0, 0, -84, 3, 4, 0, -80, 3, 0, 0, -80, 3, 0, 0, +// -80, 3, 0, 0, -80, 3, 0, 0, -80, 3, 4, 0, -76, 3, 0, 0, +// -76, 3, 0, 0, -76, 3, 4, 0, -72, 3, 0, 0, -72, 3, 0, 0, +// -72, 3, 0, 0, -72, 3, 0, 0, -72, 3, 4, 0, -68, 3, 0, 0, +// -68, 3, 0, 0, -68, 3, 0, 0, -68, 3, 4, 0, -64, 3, 0, 0, +// -64, 3, 0, 0, -64, 3, 4, 0, -60, 3, 0, 0, -60, 3, 0, 0, +// -60, 3, 0, 0, -60, 3, 0, 0, -60, 3, 4, 0, -56, 3, 0, 0, +// -56, 3, 0, 0, -56, 3, 0, 0, -56, 3, 4, 0, -52, 3, 0, 0, +// -52, 3, 0, 0, -52, 3, 0, 0, -52, 3, 4, 0, -48, 3, 0, 0, +// -48, 3, 0, 0, -48, 3, 0, 0, -48, 3, 4, 0, -44, 3, 0, 0, +// -44, 3, 0, 0, -44, 3, 0, 0, -44, 3, 4, 0, -40, 3, 0, 0, +// -40, 3, 0, 0, -40, 3, 0, 0, -40, 3, 4, 0, -36, 3, 0, 0, +// -36, 3, 0, 0, -36, 3, 0, 0, -36, 3, 4, 0, -32, 3, 0, 0, +// -32, 3, 0, 0, -32, 3, 0, 0, -32, 3, 0, 0, -32, 3, 4, 0, +// -28, 3, 0, 0, -28, 3, 0, 0, -28, 3, 0, 0, -28, 3, 0, 0, +// -28, 3, 4, 0, -24, 3, 0, 0, -24, 3, 0, 0, -24, 3, 4, 0, +// -20, 3, 0, 0, -20, 3, 0, 0, -20, 3, 0, 0, -20, 3, 0, 0, +// -20, 3, 4, 0, -16, 3, 0, 0, -16, 3, 0, 0, -16, 3, 0, 0, +// -16, 3, 4, 0, -12, 3, 0, 0, -12, 3, 0, 0, -12, 3, 0, 0, +// -12, 3, 4, 0, -8, 3, 0, 0, -8, 3, 0, 0, -8, 3, 0, 0, +// -8, 3, 0, 0, -8, 3, 4, 0, -4, 3, 0, 0, -4, 3, 0, 0, +// -4, 3, 0, 0, -4, 3, 0, 0, -4, 3, 0, 0, -4, 3, 0, 0 + }, + + /*pnBlueTable =*/ + { + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 77//, +// -20, 2, 0, 0, -20, 2, 0, 0, -20, 2, 4, 0, -16, 2, 0, 0, +// -16, 2, 0, 0, -16, 2, 4, 0, -12, 2, 0, 0, -12, 2, 4, 0, +// -8, 2, 0, 0, -8, 2, 0, 0, -8, 2, 0, 0, -8, 2, 4, 0, +// -4, 2, 0, 0, -4, 2, 4, 0, 0, 3, 0, 0, 0, 3, 0, 0, +// 0, 3, 4, 0, 4, 3, 0, 0, 4, 3, 0, 0, 4, 3, 0, 0, +// 4, 3, 4, 0, 8, 3, 0, 0, 8, 3, 0, 0, 8, 3, 0, 0, +// 8, 3, 4, 0, 12, 3, 0, 0, 12, 3, 4, 0, 16, 3, 0, 0, +// 16, 3, 0, 0, 16, 3, 4, 0, 20, 3, 0, 0, 20, 3, 0, 0, +// 20, 3, 4, 0, 24, 3, 0, 0, 24, 3, 0, 0, 24, 3, 0, 0, +// 24, 3, 4, 0, 28, 3, 0, 0, 28, 3, 0, 0, 28, 3, 0, 0, +// 28, 3, 4, 0, 32, 3, 0, 0, 32, 3, 4, 0, 36, 3, 0, 0, +// 36, 3, 0, 0, 36, 3, 4, 0, 40, 3, 0, 0, 40, 3, 0, 0, +// 40, 3, 0, 0, 40, 3, 4, 0, 44, 3, 0, 0, 44, 3, 0, 0, +// 44, 3, 4, 0, 48, 3, 0, 0, 48, 3, 0, 0, 48, 3, 0, 0, +// 48, 3, 4, 0, 52, 3, 0, 0, 52, 3, 0, 0, 52, 3, 0, 0, +// 52, 3, 4, 0, 56, 3, 0, 0, 56, 3, 0, 0, 56, 3, 4, 0, +// 60, 3, 0, 0, 60, 3, 0, 0, 60, 3, 4, 0, 64, 3, 0, 0, +// 64, 3, 4, 0, 68, 3, 0, 0, 68, 3, 0, 0, 68, 3, 0, 0, +// 68, 3, 4, 0, 72, 3, 0, 0, 72, 3, 0, 0, 72, 3, 0, 0, +// 72, 3, 4, 0, 76, 3, 0, 0, 76, 3, 0, 0, 76, 3, 4, 0, +// 80, 3, 0, 0, 80, 3, 0, 0, 80, 3, 0, 0, 80, 3, 4, 0, +// 84, 3, 0, 0, 84, 3, 0, 0, 84, 3, 0, 0, 84, 3, 4, 0, +// 88, 3, 0, 0, 88, 3, 0, 0, 88, 3, 4, 0, 92, 3, 0, 0, +// 92, 3, 0, 0, 92, 3, 0, 0, 92, 3, 4, 0, 96, 3, 0, 0, +// 96, 3, 0, 0, 96, 3, 0, 0, 96, 3, 4, 0, 100, 3, 0, 0, +// 100, 3, 0, 0, 100, 3, 4, 0, 104, 3, 0, 0, 104, 3, 0, 0, +// 104, 3, 0, 0, 104, 3, 4, 0, 108, 3, 0, 0, 108, 3, 0, 0, +// 108, 3, 4, 0, 112, 3, 0, 0, 112, 3, 0, 0, 112, 3, 0, 0, +// 112, 3, 4, 0, 116, 3, 0, 0, 116, 3, 0, 0, 116, 3, 0, 0, +// 116, 3, 0, 0, 116, 3, 4, 0, 120, 3, 0, 0, 120, 3, 0, 0, +// 120, 3, 0, 0, 120, 3, 4, 0, 124, 3, 0, 0, 124, 3, 0, 0, +// 124, 3, 0, 0, 124, 3, 4, 0, -128, 3, 0, 0, -128, 3, 0, 0, +// -128, 3, 4, 0, -124, 3, 0, 0, -124, 3, 0, 0, -124, 3, 4, 0, +// -120, 3, 0, 0, -120, 3, 0, 0, -120, 3, 0, 0, -120, 3, 4, 0, +// -116, 3, 0, 0, -116, 3, 0, 0, -116, 3, 4, 0, -112, 3, 0, 0, +// -112, 3, 0, 0, -112, 3, 0, 0, -112, 3, 4, 0, -108, 3, 0, 0, +// -108, 3, 0, 0, -108, 3, 0, 0, -108, 3, 0, 0, -108, 3, 4, 0, +// -104, 3, 0, 0, -104, 3, 0, 0, -104, 3, 4, 0, -100, 3, 0, 0, +// -100, 3, 0, 0, -100, 3, 4, 0, -96, 3, 0, 0, -96, 3, 0, 0, +// -96, 3, 0, 0, -96, 3, 4, 0, -92, 3, 0, 0, -92, 3, 0, 0, +// -92, 3, 0, 0, -92, 3, 0, 0, -92, 3, 4, 0, -88, 3, 0, 0, +// -88, 3, 0, 0, -88, 3, 4, 0, -84, 3, 0, 0, -84, 3, 0, 0, +// -84, 3, 0, 0, -84, 3, 4, 0, -80, 3, 0, 0, -80, 3, 0, 0, +// -80, 3, 0, 0, -80, 3, 0, 0, -80, 3, 4, 0, -76, 3, 0, 0, +// -76, 3, 0, 0, -76, 3, 4, 0, -72, 3, 0, 0, -72, 3, 0, 0, +// -72, 3, 0, 0, -72, 3, 0, 0, -72, 3, 4, 0, -68, 3, 0, 0, +// -68, 3, 0, 0, -68, 3, 0, 0, -68, 3, 4, 0, -64, 3, 0, 0, +// -64, 3, 0, 0, -64, 3, 4, 0, -60, 3, 0, 0, -60, 3, 0, 0, +// -60, 3, 0, 0, -60, 3, 0, 0, -60, 3, 4, 0, -56, 3, 0, 0, +// -56, 3, 0, 0, -56, 3, 0, 0, -56, 3, 4, 0, -52, 3, 0, 0, +// -52, 3, 0, 0, -52, 3, 0, 0, -52, 3, 4, 0, -48, 3, 0, 0, +// -48, 3, 0, 0, -48, 3, 0, 0, -48, 3, 4, 0, -44, 3, 0, 0, +// -44, 3, 0, 0, -44, 3, 0, 0, -44, 3, 4, 0, -40, 3, 0, 0, +// -40, 3, 0, 0, -40, 3, 0, 0, -40, 3, 4, 0, -36, 3, 0, 0, +// -36, 3, 0, 0, -36, 3, 0, 0, -36, 3, 4, 0, -32, 3, 0, 0, +// -32, 3, 0, 0, -32, 3, 0, 0, -32, 3, 0, 0, -32, 3, 4, 0, +// -28, 3, 0, 0, -28, 3, 0, 0, -28, 3, 0, 0, -28, 3, 0, 0, +// -28, 3, 4, 0, -24, 3, 0, 0, -24, 3, 0, 0, -24, 3, 4, 0, +// -20, 3, 0, 0, -20, 3, 0, 0, -20, 3, 0, 0, -20, 3, 0, 0, +// -20, 3, 4, 0, -16, 3, 0, 0, -16, 3, 0, 0, -16, 3, 0, 0, +// -16, 3, 4, 0, -12, 3, 0, 0, -12, 3, 0, 0, -12, 3, 0, 0, +// -12, 3, 4, 0, -8, 3, 0, 0, -8, 3, 0, 0, -8, 3, 0, 0, +// -8, 3, 0, 0, -8, 3, 4, 0, -4, 3, 0, 0, -4, 3, 0, 0, +// -4, 3, 0, 0, -4, 3, 0, 0, -4, 3, 0, 0, -4, 3, 0, 0 + }, + + /*pnGreenTable =*/ + { + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 77//, +// 128, 128, 128, 128, 128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255 -32, 2, 4, 0, -28, 2, 0, 0, -28, 2, 0, 0, -28, 2, 4, 0, +// -24, 2, 0, 0, -24, 2, 0, 0, -24, 2, 4, 0, -20, 2, 0, 0, +// -20, 2, 0, 0, -20, 2, 0, 0, -20, 2, 4, 0, -16, 2, 0, 0, +// -16, 2, 0, 0, -16, 2, 4, 0, -12, 2, 0, 0, -12, 2, 4, 0, +// -8, 2, 0, 0, -8, 2, 0, 0, -8, 2, 0, 0, -8, 2, 4, 0, +// -4, 2, 0, 0, -4, 2, 4, 0, 0, 3, 0, 0, 0, 3, 0, 0, +// 0, 3, 4, 0, 4, 3, 0, 0, 4, 3, 0, 0, 4, 3, 0, 0, +// 4, 3, 4, 0, 8, 3, 0, 0, 8, 3, 0, 0, 8, 3, 0, 0, +// 8, 3, 4, 0, 12, 3, 0, 0, 12, 3, 4, 0, 16, 3, 0, 0, +// 16, 3, 0, 0, 16, 3, 4, 0, 20, 3, 0, 0, 20, 3, 0, 0, +// 20, 3, 4, 0, 24, 3, 0, 0, 24, 3, 0, 0, 24, 3, 0, 0, +// 24, 3, 4, 0, 28, 3, 0, 0, 28, 3, 0, 0, 28, 3, 0, 0, +// 28, 3, 4, 0, 32, 3, 0, 0, 32, 3, 4, 0, 36, 3, 0, 0, +// 36, 3, 0, 0, 36, 3, 4, 0, 40, 3, 0, 0, 40, 3, 0, 0, +// 40, 3, 0, 0, 40, 3, 4, 0, 44, 3, 0, 0, 44, 3, 0, 0, +// 44, 3, 4, 0, 48, 3, 0, 0, 48, 3, 0, 0, 48, 3, 0, 0, +// 48, 3, 4, 0, 52, 3, 0, 0, 52, 3, 0, 0, 52, 3, 0, 0, +// 52, 3, 4, 0, 56, 3, 0, 0, 56, 3, 0, 0, 56, 3, 4, 0, +// 60, 3, 0, 0, 60, 3, 0, 0, 60, 3, 4, 0, 64, 3, 0, 0, +// 64, 3, 4, 0, 68, 3, 0, 0, 68, 3, 0, 0, 68, 3, 0, 0, +// 68, 3, 4, 0, 72, 3, 0, 0, 72, 3, 0, 0, 72, 3, 0, 0, +// 72, 3, 4, 0, 76, 3, 0, 0, 76, 3, 0, 0, 76, 3, 4, 0, +// 80, 3, 0, 0, 80, 3, 0, 0, 80, 3, 0, 0, 80, 3, 4, 0, +// 84, 3, 0, 0, 84, 3, 0, 0, 84, 3, 0, 0, 84, 3, 4, 0, +// 88, 3, 0, 0, 88, 3, 0, 0, 88, 3, 4, 0, 92, 3, 0, 0, +// 92, 3, 0, 0, 92, 3, 0, 0, 92, 3, 4, 0, 96, 3, 0, 0, +// 96, 3, 0, 0, 96, 3, 0, 0, 96, 3, 4, 0, 100, 3, 0, 0, + +// 100, 3, 0, 0, 100, 3, 4, 0, 104, 3, 0, 0, 104, 3, 0, 0, +// 104, 3, 0, 0, 104, 3, 4, 0, 108, 3, 0, 0, 108, 3, 0, 0, +// 108, 3, 4, 0, 112, 3, 0, 0, 112, 3, 0, 0, 112, 3, 0, 0, +// 112, 3, 4, 0, 116, 3, 0, 0, 116, 3, 0, 0, 116, 3, 0, 0, +// 116, 3, 0, 0, 116, 3, 4, 0, 120, 3, 0, 0, 120, 3, 0, 0, +// 120, 3, 0, 0, 120, 3, 4, 0, 124, 3, 0, 0, 124, 3, 0, 0, +// 124, 3, 0, 0, 124, 3, 4, 0, -128, 3, 0, 0, -128, 3, 0, 0, +// -128, 3, 4, 0, -124, 3, 0, 0, -124, 3, 0, 0, -124, 3, 4, 0, +// -120, 3, 0, 0, -120, 3, 0, 0, -120, 3, 0, 0, -120, 3, 4, 0, +// -116, 3, 0, 0, -116, 3, 0, 0, -116, 3, 4, 0, -112, 3, 0, 0, +// -112, 3, 0, 0, -112, 3, 0, 0, -112, 3, 4, 0, -108, 3, 0, 0, +// -108, 3, 0, 0, -108, 3, 0, 0, -108, 3, 0, 0, -108, 3, 4, 0, +// -104, 3, 0, 0, -104, 3, 0, 0, -104, 3, 4, 0, -100, 3, 0, 0, +// -100, 3, 0, 0, -100, 3, 4, 0, -96, 3, 0, 0, -96, 3, 0, 0, +// -96, 3, 0, 0, -96, 3, 4, 0, -92, 3, 0, 0, -92, 3, 0, 0, +// -92, 3, 0, 0, -92, 3, 0, 0, -92, 3, 4, 0, -88, 3, 0, 0, +// -88, 3, 0, 0, -88, 3, 4, 0, -84, 3, 0, 0, -84, 3, 0, 0, +// -84, 3, 0, 0, -84, 3, 4, 0, -80, 3, 0, 0, -80, 3, 0, 0, +// -80, 3, 0, 0, -80, 3, 0, 0, -80, 3, 4, 0, -76, 3, 0, 0, +// -76, 3, 0, 0, -76, 3, 4, 0, -72, 3, 0, 0, -72, 3, 0, 0, +// -72, 3, 0, 0, -72, 3, 0, 0, -72, 3, 4, 0, -68, 3, 0, 0, +// -68, 3, 0, 0, -68, 3, 0, 0, -68, 3, 4, 0, -64, 3, 0, 0, +// -64, 3, 0, 0, -64, 3, 4, 0, -60, 3, 0, 0, -60, 3, 0, 0, +// -60, 3, 0, 0, -60, 3, 0, 0, -60, 3, 4, 0, -56, 3, 0, 0, +// -56, 3, 0, 0, -56, 3, 0, 0, -56, 3, 4, 0, -52, 3, 0, 0, +// -52, 3, 0, 0, -52, 3, 0, 0, -52, 3, 4, 0, -48, 3, 0, 0, +// -48, 3, 0, 0, -48, 3, 0, 0, -48, 3, 4, 0, -44, 3, 0, 0, +// -44, 3, 0, 0, -44, 3, 0, 0, -44, 3, 4, 0, -40, 3, 0, 0, +// -40, 3, 0, 0, -40, 3, 0, 0, -40, 3, 4, 0, -36, 3, 0, 0, +// -36, 3, 0, 0, -36, 3, 0, 0, -36, 3, 4, 0, -32, 3, 0, 0, +// -32, 3, 0, 0, -32, 3, 0, 0, -32, 3, 0, 0, -32, 3, 4, 0, +// -28, 3, 0, 0, -28, 3, 0, 0, -28, 3, 0, 0, -28, 3, 0, 0, +// -28, 3, 4, 0, -24, 3, 0, 0, -24, 3, 0, 0, -24, 3, 4, 0, +// -20, 3, 0, 0, -20, 3, 0, 0, -20, 3, 0, 0, -20, 3, 0, 0, +// -20, 3, 4, 0, -16, 3, 0, 0, -16, 3, 0, 0, -16, 3, 0, 0, +// -16, 3, 4, 0, -12, 3, 0, 0, -12, 3, 0, 0, -12, 3, 0, 0, +// -12, 3, 4, 0, -8, 3, 0, 0, -8, 3, 0, 0, -8, 3, 0, 0, +// -8, 3, 0, 0, -8, 3, 4, 0, -4, 3, 0, 0, -4, 3, 0, 0, +// -4, 3, 0, 0, -4, 3, 0, 0, -4, 3, 0, 0, -4, 3, 0, 0 + } +}; + +static VCAM_3ASKIP_IPIPE_GBCE_CFGTYPE gbceDump = { + /*nEnable = */0, + /*nTyp = */(VCAM_3ASKIP_IPIPE_GBCE_METHODTYPE)2, + /*LookupTable =*/ + { + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, + 128, 128, 128, 128, 128, 128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 77, + + } +}; diff --git a/source/dvp/VisionCam/ServerVisionCam.cpp b/source/dvp/VisionCam/ServerVisionCam.cpp new file mode 100644 index 0000000..466a5a5 --- /dev/null +++ b/source/dvp/VisionCam/ServerVisionCam.cpp @@ -0,0 +1,415 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +ServerVisionCam::ServerVisionCam() : + m_dvp(0), + m_running(false_e), + m_server(NULL), + m_data(NULL), + m_pCam(NULL), + m_frameData(NULL), + m_numDataBytes(0), + m_numImageBytes(0), + m_pImages(NULL), + m_status(STATUS_SUCCESS), + m_param(NULL), +//#if defined(__QNX__) + m_display_enabled(true_e), +//#else +// m_display_enabled(false_e), +//#endif + m_display(NULL), + m_allocWidth(0), + m_allocHeight(0) +{ + event_init(&m_wait, false_e); + memset(&m_img, 0, sizeof(VisionCamImages_t)); + m_dvp = DVP_KernelGraph_Init(); + m_pImages = (DVP_Image_t *)calloc(VCAM_NUM_BUFFERS, sizeof(DVP_Image_t)); +} + +ServerVisionCam::~ServerVisionCam() +{ + if (m_param) { + free(m_param); + m_param = NULL; + } + free(m_pImages); + DVP_KernelGraph_Deinit(m_dvp); + event_deinit(&m_wait); +} + +void ServerVisionCam::FrameCallback(VisionCamFrame * cameraFrame) +{ + ServerVisionCam *pSVCam = reinterpret_cast(cameraFrame->mCookie); + uint32_t offset = 0; + + if (pSVCam->m_display_enabled && cameraFrame->mFrameSource == VCAM_PORT_PREVIEW) + { + DVP_Image_t *pImage = (DVP_Image_t *)cameraFrame->mFrameBuff; + DVP_Display_Render(pSVCam->m_display, pImage); + } + + // serialize the camera frame to a flat buffer + offset += cameraFrame->serialize(pSVCam->m_frameData, pSVCam->m_numDataBytes); + + // send the buffer size + socket_send(pSVCam->m_data, (uint8_t *)&offset, sizeof(offset)); + + // send the frame + socket_send(pSVCam->m_data, pSVCam->m_frameData, offset); + + pSVCam->m_pCam->returnFrame(cameraFrame); +} + +void ServerVisionCam::FocusCallback(int state) +{ + state = state; // warnings + DVP_PRINT(DVP_ZONE_ALWAYS, "Focus state %d\n", state); +} + +bool_e ServerVisionCam::init(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns) +{ + ServerVisionCam *pSVCam = (ServerVisionCam *)arg; + VisionCam *pCam = pSVCam->m_pCam; + params = params; // remove warning + if (pCam && numParams == 0) + { + pSVCam->m_status = pCam->init(pSVCam); + if (pSVCam->m_status == STATUS_SUCCESS) + { + socket_connect(pSVCam->m_data); + pCam->enablePreviewCbk(FrameCallback); + pCam->setFocusCallBack(FocusCallback); + } + returns[0].type = RPC_SOCKET_TYPE_INT32; + returns[0].numElements = 1; + returns[0].sizeElement = sizeof(status_e); + returns[0].item = &pSVCam->m_status; // must be static or class variable! + *numReturns = 1; + return true_e; + } + else + return false_e; +} + +bool_e ServerVisionCam::deinit(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns) +{ + ServerVisionCam *pSVCam = (ServerVisionCam *)arg; + VisionCam *pCam = pSVCam->m_pCam; + params = params; // remove warning + if (pCam && numParams == 0) + { + pCam->setFocusCallBack(NULL); + pSVCam->m_status = pCam->deinit(); + + returns[0].type = RPC_SOCKET_TYPE_INT32; + returns[0].numElements = 1; + returns[0].sizeElement = sizeof(status_e); + returns[0].item = &pSVCam->m_status; // must be static or class variable! + *numReturns = 1; + event_set(&pSVCam->m_wait); // signal that we're done... + return true_e; + } + else + return false_e; +} + +bool_e ServerVisionCam::setParameter(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns) +{ + ServerVisionCam *pSVCam = (ServerVisionCam *)arg; + VisionCam *pCam = pSVCam->m_pCam; + if (pCam && numParams == 2 && + params[0].numElements == 1 && params[0].sizeElement == sizeof(int32_t)) + { + VisionCamParam_e paramId = *(VisionCamParam_e *)params[0].item; + void *param = params[1].item; + uint32_t size = params[1].numElements * params[1].sizeElement; + pSVCam->m_status = pCam->setParameter(paramId, param, size); + returns[0].type = RPC_SOCKET_TYPE_INT32; + returns[0].numElements = 1; + returns[0].sizeElement = sizeof(status_e); + returns[0].item = &pSVCam->m_status; // must be static or class variable! + *numReturns = 1; + return true_e; + } + else + return false_e; +} + +bool_e ServerVisionCam::getParameter(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns) +{ + ServerVisionCam *pSVCam = (ServerVisionCam *)arg; + VisionCam *pCam = pSVCam->m_pCam; + if (pCam && numParams == 2 && + params[0].numElements == 1 && params[0].sizeElement == sizeof(int32_t) && + params[1].numElements == 1 && params[0].sizeElement == sizeof(uint32_t)) + { + VisionCamParam_e paramId = *(VisionCamParam_e *)params[0].item; + uint32_t size = *(uint32_t *)params[1].item; + + if (pSVCam->m_param) { + free(pSVCam->m_param); + pSVCam->m_param = NULL; + } + if (pSVCam->m_param == NULL) { + pSVCam->m_param = calloc(1, size); + } + + pSVCam->m_status = pCam->getParameter(paramId, pSVCam->m_param, size); + + if (paramId == VCAM_PARAM_2DBUFFER_DIM) + { + VisionCamResType *res = (VisionCamResType *)pSVCam->m_param; + + pSVCam->m_allocWidth = res->mWidth; + pSVCam->m_allocHeight = res->mHeight; + } + + returns[0].type = RPC_SOCKET_TYPE_INT32; + returns[0].numElements = 1; + returns[0].sizeElement = sizeof(status_e); + returns[0].item = &pSVCam->m_status; // must be static or class variable! + returns[1].type = RPC_SOCKET_TYPE_INT8; + returns[1].numElements = size; + returns[1].sizeElement = sizeof(uint8_t); + returns[1].item = pSVCam->m_param; // must be static or class variable! + *numReturns = 2; + return true_e; + } + else + return false_e; +} + +bool_e ServerVisionCam::sendCommand(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns) +{ + ServerVisionCam *pSVCam = (ServerVisionCam *)arg; + VisionCam *pCam = pSVCam->m_pCam; + if (pCam && numParams == 2 && + params[0].numElements == 1 && params[0].sizeElement == sizeof(int32_t)) + { + VisionCamCmd_e cmd = *(VisionCamCmd_e *)params[0].item; + void *param = params[1].item; + uint32_t size = params[1].numElements * params[1].sizeElement; + + pSVCam->m_status = pCam->sendCommand(cmd, param, size); + + returns[0].type = RPC_SOCKET_TYPE_INT32; + returns[0].numElements = 1; + returns[0].sizeElement = sizeof(status_e); + returns[0].item = &pSVCam->m_status; // must be static or class variable! + *numReturns = 1; + + return true_e; + } + else + return false_e; +} + +bool_e ServerVisionCam::useBuffers(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns) +{ + ServerVisionCam *pSVCam = (ServerVisionCam *)arg; + VisionCam *pCam = pSVCam->m_pCam; + if (pCam && numParams == 1 && + params[0].numElements == 1 && params[0].sizeElement == sizeof(VisionCamImages_t)) + { + pSVCam->m_img = *(VisionCamImages_t *)params[0].item; + if (pSVCam->m_frameData != NULL) + { + free(pSVCam->m_frameData); + pSVCam->m_numDataBytes = 0; + pSVCam->m_numImageBytes = 0; + pSVCam->m_frameData = NULL; + } + if (pSVCam->m_frameData == NULL) + { + // compute the image size + DVP_PRINT(DVP_ZONE_ALWAYS, "ServerVisionCam: w:%u h:%u c:0x%08x #:%u\n", pSVCam->m_img.width, pSVCam->m_img.height, pSVCam->m_img.color, pSVCam->m_img.count); + DVP_PRINT(DVP_ZONE_ALWAYS, "ServerVisionCam: Alloc: w:%u h:%u\n", pSVCam->m_allocWidth, pSVCam->m_allocHeight); + DVP_Image_t image; + VisionCamFrame cFrame; + + // create a dummy image + DVP_Image_Init(&image, pSVCam->m_img.width, pSVCam->m_img.height, pSVCam->m_img.color); + + // clear out the frame and assign the image then ask how big it could possibly be + cFrame.clear(); + cFrame.mFrameBuff = ℑ + + pSVCam->m_numDataBytes = cFrame.maxSerialLength(); + pSVCam->m_frameData = (uint8_t *)calloc(1, pSVCam->m_numDataBytes); + DVP_PRINT(DVP_ZONE_CAM, "ServerVisionCam: Allocated %u bytes for m_frameData %p packet [%p-%p)\n", pSVCam->m_numDataBytes, pSVCam->m_frameData, pSVCam->m_frameData, &pSVCam->m_frameData[pSVCam->m_numDataBytes]); + } + if (pSVCam->m_display_enabled) + { + pSVCam->m_display = DVP_Display_Create(pSVCam->m_img.width, + pSVCam->m_img.height, + pSVCam->m_allocWidth, + pSVCam->m_allocHeight, + DVP_DISPLAY_WIDTH, + DVP_DISPLAY_HEIGHT, + pSVCam->m_allocWidth, + pSVCam->m_allocHeight, + 0, 0, + pSVCam->m_img.color, + 0, pSVCam->m_img.count); + } + for (uint32_t i = 0; i < pSVCam->m_img.count; i++) + { + DVP_Image_Init(&pSVCam->m_pImages[i], pSVCam->m_allocWidth, pSVCam->m_allocHeight, pSVCam->m_img.color); + pSVCam->m_pImages[i].width = pSVCam->m_img.width; + pSVCam->m_pImages[i].height = pSVCam->m_img.height; + + if (pSVCam->m_display_enabled && pSVCam->m_display) + { + DVP_Display_Alloc(pSVCam->m_display, &pSVCam->m_pImages[i]); + DVP_Image_Alloc(pSVCam->m_dvp, &pSVCam->m_pImages[i], (DVP_MemType_e)pSVCam->m_pImages[i].memType); + } + else + { +#if defined(DVP_USE_TILER) + DVP_Image_Alloc(pSVCam->m_dvp, &pSVCam->m_pImages[i], DVP_MTYPE_MPUNONCACHED_2DTILED); +#else + DVP_Image_Alloc(pSVCam->m_dvp, &pSVCam->m_pImages[i], DVP_MTYPE_DEFAULT); +#endif + } + } + pSVCam->m_status = pCam->useBuffers(pSVCam->m_pImages, pSVCam->m_img.count, (VisionCamPort_e)pSVCam->m_img.port); + returns[0].type = RPC_SOCKET_TYPE_INT32; + returns[0].numElements = 1; + returns[0].sizeElement = sizeof(status_e); + returns[0].item = &pSVCam->m_status; // must be static or class variable! + *numReturns = 1; + return true_e; + } + else + return false_e; +} + +bool_e ServerVisionCam::releaseBuffers(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns) +{ + ServerVisionCam *pSVCam = (ServerVisionCam *)arg; + VisionCam *pCam = pSVCam->m_pCam; + params = params; // remove warning + if (pCam && numParams == 0) + { + pCam->disablePreviewCbk(FrameCallback); + pSVCam->m_status = pCam->releaseBuffers(); + socket_disconnect(pSVCam->m_data); + socket_deinit(pSVCam->m_data); + pSVCam->m_data = NULL; + for (uint32_t i = 0; i < pSVCam->m_img.count; i++) + { + if (pSVCam->m_display_enabled) + { + DVP_Display_Free(pSVCam->m_display, &pSVCam->m_pImages[i]); + } + else + { + DVP_Image_Free(pSVCam->m_dvp,&pSVCam->m_pImages[i]); + DVP_Image_Deinit(&pSVCam->m_pImages[i]); + } + } + if (pSVCam->m_display_enabled) + { + DVP_Display_Destroy(&pSVCam->m_display); + pSVCam->m_display_enabled = false_e; + } + free(pSVCam->m_frameData); + pSVCam->m_frameData = NULL; + pSVCam->m_numDataBytes = 0; + pSVCam->m_numImageBytes = 0; + returns[0].type = RPC_SOCKET_TYPE_INT32; + returns[0].numElements = 1; + returns[0].sizeElement = sizeof(status_e); + returns[0].item = &pSVCam->m_status; // must be static or class variable! + *numReturns = 1; + return true_e; + } + else + return false_e; +} + +bool_e ServerVisionCam::flushBuffers(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns) +{ + ServerVisionCam *pSVCam = (ServerVisionCam *)arg; + VisionCam *pCam = pSVCam->m_pCam; + params = params; // remove warning + if (pCam && numParams == 0) + { + pSVCam->m_status = pCam->flushBuffers(); + returns[0].type = RPC_SOCKET_TYPE_INT32; + returns[0].numElements = 1; + returns[0].sizeElement = sizeof(status_e); + returns[0].item = &pSVCam->m_status; // must be static or class variable! + *numReturns = 1; + return true_e; + } + else + return false_e; +} + +ServerVisionCam *ServerVisionCam::instantiate(char *hostname, VisionCam_e camType) +{ + ServerVisionCam *pSVCam = new ServerVisionCam(); + // @see VisionCamFunction_e This must match that order of functions. + rpc_server_function_f functions[] = { + ServerVisionCam::init, + ServerVisionCam::deinit, + ServerVisionCam::setParameter, + ServerVisionCam::getParameter, + ServerVisionCam::sendCommand, + ServerVisionCam::useBuffers, + ServerVisionCam::releaseBuffers, + ServerVisionCam::flushBuffers, + }; + + // instantiate the camera but don't initialize + pSVCam->m_pCam = VisionCamFactory(camType); + + // initlialize the server components + pSVCam->m_ipaddr = socket_hostname(hostname); + pSVCam->m_server = rpc_socket_server_init(hostname, VCAM_SOCKET_CMD_PORT, pSVCam, functions, dimof(functions)); + pSVCam->m_data = socket_init(pSVCam->m_ipaddr, VCAM_SOCKET_DATA_PORT, SOCKET_TCP, true_e); + + // start the server + rpc_socket_server_start(pSVCam->m_server); + + return pSVCam; +} + + +bool_e ServerVisionCam::WaitForCompletion() +{ + // WAIT until it's over + event_wait(&m_wait, EVENT_FOREVER); + + // Close up + socket_disconnect(m_data); + socket_deinit(m_data); + rpc_socket_server_stop(m_server); + rpc_socket_server_deinit(m_server); + + return true_e; +} + +void ServerVisionCam::SignalCompletion() +{ + event_set(&m_wait); +} + diff --git a/source/dvp/VisionCam/ServerVisionCam.h b/source/dvp/VisionCam/ServerVisionCam.h new file mode 100644 index 0000000..1596244 --- /dev/null +++ b/source/dvp/VisionCam/ServerVisionCam.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +class ServerVisionCam { +public: + DVP_Handle m_dvp; + bool_e m_running; + rpc_server_t *m_server; + socket_t *m_data; + VisionCam *m_pCam; + uint8_t *m_frameData; + uint32_t m_numDataBytes; + uint32_t m_numImageBytes; + DVP_Image_t *m_pImages; + status_e m_status; + void *m_param; + uint32_t m_ipaddr; + bool_e m_display_enabled; + dvp_display_t *m_display; + uint32_t m_allocWidth; + uint32_t m_allocHeight; + VisionCamImages_t m_img; + event_t m_wait; +public: + ServerVisionCam(); + ~ServerVisionCam(); + + // Main Interface (blocking) + static ServerVisionCam *instantiate(char *ipaddr, VisionCam_e camType); + bool_e WaitForCompletion(); + void SignalCompletion(); + + // Camera Interfaces + static void FrameCallback(VisionCamFrame *frame); + static void FocusCallback(int state); + + // RPC Interfaces + static bool_e init(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns); + static bool_e deinit(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns); + static bool_e useBuffers(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns); + static bool_e releaseBuffers(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns); + static bool_e flushBuffers(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns); + static bool_e sendCommand(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns); + static bool_e setParameter(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns); + static bool_e getParameter(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns); +}; + diff --git a/source/dvp/VisionCam/SocketVisionCam.cpp b/source/dvp/VisionCam/SocketVisionCam.cpp new file mode 100644 index 0000000..0e71782 --- /dev/null +++ b/source/dvp/VisionCam/SocketVisionCam.cpp @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#if defined(SOSAL_RPC_SOCKET_API) + +SocketVisionCam::SocketVisionCam() : + CThreaded(), + VisionCam(), + m_imgs(NULL), + m_data(NULL), + m_ipaddr(0), + m_frameData(NULL), + m_numDataBytes(0), + m_numImgBytes(0), + m_client(NULL) +{ + DVP_PRINT(DVP_ZONE_API, "SocketVisionCam()+\n"); + m_imgs = queue_create(VCAM_NUM_BUFFERS*VCAM_PORT_MAX, sizeof(VisionCamFrame *)); // a queue of image pointers + strncpy(m_hostname, "127.0.0.1", MAX_PATH); + memset(m_filename, 0, sizeof(m_filename)); + pFile = NULL; +} + +SocketVisionCam::~SocketVisionCam() +{ + queue_destroy(m_imgs); + if (m_client) { + rpc_socket_client_stop(m_client); + m_client = NULL; + } + if (m_data) { + socket_deinit(m_data); + m_data = NULL; + } +} + +status_e SocketVisionCam::init(void *cookie) +{ + status_e status = STATUS_SUCCESS; + m_cookie = cookie; + m_ipaddr = socket_hostname(m_hostname); + m_client = rpc_socket_client_start(m_hostname, VCAM_SOCKET_CMD_PORT); + if (m_client) + { + StartThread(this); + rpc_socket_item_t returns[] = { + {0, RPC_SOCKET_TYPE_INT32, sizeof(int32_t), 1, &status}, + }; + if (rpc_socket_client_call(m_client, VISIONCAM_FUNCTION_INIT, NULL, 0, returns, dimof(returns)) == false_e) + status = STATUS_NO_RESOURCES; + } + else + status = STATUS_NO_RESOURCES; + return status; +} + +status_e SocketVisionCam::deinit() +{ + status_e status = STATUS_SUCCESS; + rpc_socket_item_t returns[] = { + {0, RPC_SOCKET_TYPE_INT32, sizeof(int32_t), 1, &status}, + }; + if (rpc_socket_client_call(m_client, VISIONCAM_FUNCTION_DEINIT, NULL, 0, returns, dimof(returns))) + { + rpc_socket_client_stop(m_client); + m_client = NULL; + } + else + status = STATUS_NO_RESOURCES; + return status; +} + +status_e SocketVisionCam::useBuffers(DVP_Image_t * pImages, uint32_t numImages, VisionCamPort_e port = VCAM_PORT_PREVIEW) +{ + uint32_t i = 0; + status_e status = STATUS_SUCCESS; + bool_e validColor = false_e; + fourcc_t validColors[] = { + FOURCC_UYVY, + FOURCC_YUY2, + FOURCC_BGR, + FOURCC_NV12, + }; + for (i = 0; i < dimof(validColors); i++) + if (pImages[0].color == validColors[i]) + validColor = true_e; + + if (validColor && numImages < VCAM_NUM_BUFFERS) + { + DVP_Image_t image = pImages[0]; // implicit copy + VisionCamFrame frame; + frame.mFrameBuff = ℑ + + m_numDataBytes = frame.maxSerialLength(); + m_frameData = (uint8_t *)calloc(1, m_numDataBytes); + if (m_frameData == NULL) + return STATUS_NOT_ENOUGH_MEMORY; + PYUV_GetFilename(m_filename, (char *)"", (char *)"frameData", pImages[0].width, pImages[0].height, 30, pImages[0].color); + //pFile = fopen(m_filename, "w+"); + for (uint32_t i = 0; i < numImages; i++) + { + DVP_Image_t *pImage = &pImages[i]; + DVP_PrintImage(DVP_ZONE_CAM, pImage); + queue_write(m_imgs, true_e, &pImage); + } + + VisionCamImages_t img = { + pImages[0].width, + pImages[0].height, + pImages[0].color, + numImages, + port + }; + rpc_socket_item_t params[] = { + {0, RPC_SOCKET_TYPE_INT32, sizeof(VisionCamImages_t), 1, &img}, + }; + rpc_socket_item_t returns[] = { + {0, RPC_SOCKET_TYPE_INT32, sizeof(int32_t), 1, &status}, + }; + if (rpc_socket_client_call(m_client, VISIONCAM_FUNCTION_USEBUFS, params, dimof(params), returns, dimof(returns)) == false_e) + status = STATUS_NO_RESOURCES; + } + else + status = STATUS_INVALID_PARAMETER; + return status; +} + +status_e SocketVisionCam::returnFrame(VisionCamFrame *cameraFrame) +{ + status_e status = STATUS_SUCCESS; + if (m_imgs && cameraFrame) + queue_write(m_imgs, true_e, &cameraFrame); + else + status = STATUS_INVALID_PARAMETER; + return status; +} + +status_e SocketVisionCam::releaseBuffers( VisionCamPort_e port __attribute__((unused))) +{ + status_e status = STATUS_SUCCESS; + rpc_socket_item_t returns[] = { + {0, RPC_SOCKET_TYPE_INT32, sizeof(int32_t), 1, &status}, + }; + if (rpc_socket_client_call(m_client, VISIONCAM_FUNCTION_RLSBUFS, NULL, 0, returns, dimof(returns))) + { + DVP_Image_t *pImage = NULL; + StopThread(); // only stop now + if (m_running == false_e) + { + size_t l = 0; + DVP_PRINT(DVP_ZONE_CAM, "Freeing all images from queue and freeing frame data.\n"); + // read all images off the queue + queue_unpop(m_imgs); + do { + l = queue_length(m_imgs); + DVP_PRINT(DVP_ZONE_CAM, ""FMT_SIZE_T" images left on queue\n",l); + if (queue_read(m_imgs, false_e, &pImage) == true_e) + DVP_PrintImage(DVP_ZONE_CAM, pImage); + } while (l > 0); + //fclose(pFile); + DVP_PRINT(DVP_ZONE_CAM, "Freeing frame data %p\n",m_frameData); + if (m_frameData) + free(m_frameData); + m_frameData = NULL; + DVP_PRINT(DVP_ZONE_CAM, "Released Buffers\n"); + } + else + { + DVP_PRINT(DVP_ZONE_WARNING, "Attempting to release buffers while DataThread is still running!\n"); + } + } + else + status = STATUS_NO_RESOURCES; + return status; +} + +status_e SocketVisionCam::flushBuffers( VisionCamPort_e port __attribute__((unused))) +{ + status_e status = STATUS_SUCCESS; + rpc_socket_item_t returns[] = { + {0, RPC_SOCKET_TYPE_INT32, sizeof(int32_t), 1, &status}, + }; + if (rpc_socket_client_call(m_client, VISIONCAM_FUNCTION_FLUSHBUFS, NULL, 0, returns, dimof(returns)) == false_e) + status = STATUS_NO_RESOURCES; + return status; +} + +status_e SocketVisionCam::sendCommand(VisionCamCmd_e cmdId, void * param, uint32_t size, + VisionCamPort_e port __attribute__ ((unused))) +{ + status_e status = STATUS_SUCCESS; + rpc_socket_item_t params[] = { + {0, RPC_SOCKET_TYPE_INT32, sizeof(int32_t), 1, &cmdId}, + {0, RPC_SOCKET_TYPE_UINT8, 1, size, param}, + }; + rpc_socket_item_t returns[] = { + {0, RPC_SOCKET_TYPE_INT32, sizeof(int32_t), 1, &status}, + }; + if (rpc_socket_client_call(m_client, VISIONCAM_FUNCTION_SENDCMD, params, dimof(params), returns, dimof(returns)) == false_e) + status = STATUS_NO_RESOURCES; + return status; +} + +status_e SocketVisionCam::setParameter(VisionCamParam_e paramId, void * param, uint32_t size, + VisionCamPort_e port __attribute__ ((unused))) +{ + status_e status = STATUS_SUCCESS; + if ((SocketVisionCam_Param_e)paramId == SOCKETVCAM_PARAM_HOSTNAME) + { + strncpy(m_hostname, (char *)param, (size > MAX_PATH ? MAX_PATH:size)); + } + else + { + rpc_socket_item_t params[] = { + {0, RPC_SOCKET_TYPE_INT32, sizeof(int32_t), 1, ¶mId}, + {0, RPC_SOCKET_TYPE_UINT8, 1, size, param}, + }; + rpc_socket_item_t returns[] = { + {0, RPC_SOCKET_TYPE_INT32, sizeof(int32_t), 1, &status}, + }; + if (rpc_socket_client_call(m_client, VISIONCAM_FUNCTION_SETPARAMS, params, dimof(params), returns, dimof(returns)) == false_e) + status = STATUS_NO_RESOURCES; + } + return status; +} + +status_e SocketVisionCam::getParameter(VisionCamParam_e paramId, void * param, uint32_t size, + VisionCamPort_e port __attribute__ ((unused))) +{ + status_e status = STATUS_SUCCESS; + if ((SocketVisionCam_Param_e)paramId == SOCKETVCAM_PARAM_HOSTNAME) + { + strncpy((char *)param, m_hostname, (size > MAX_PATH ? MAX_PATH:size)); + } + else + { + rpc_socket_item_t params[] = { + {0, RPC_SOCKET_TYPE_INT32, sizeof(int32_t), 1, ¶mId}, + {0, RPC_SOCKET_TYPE_UINT32, sizeof(uint32_t), 1, &size}, + }; + rpc_socket_item_t returns[] = { + {0, RPC_SOCKET_TYPE_INT32, sizeof(int32_t), 1, &status}, + {0, RPC_SOCKET_TYPE_UINT8, 1, size, param}, + }; + if (rpc_socket_client_call(m_client, VISIONCAM_FUNCTION_GETPARAMS, params, dimof(params), returns, dimof(returns)) == false_e) + status = STATUS_NO_RESOURCES; + } + return status; +} + +void SocketVisionCam::Shutdown() +{ + DVP_PRINT(DVP_ZONE_CAM, "Closing RunThread()\n"); + queue_pop(m_imgs); // pop out of the queue_read +} + +thread_ret_t SocketVisionCam::RunThread() +{ + thread_ret_t ret = (thread_ret_t)-2; + VisionCamFrame frame; + + m_data = socket_init(m_ipaddr, VCAM_SOCKET_DATA_PORT, SOCKET_TCP, false_e); + if (m_data) + { + if (socket_connect(m_data) == false_e) { + thread_exit(ret); + } + + DVP_PRINT(DVP_ZONE_CAM, "SocketVisionCam RunThread Launched!\n"); + while (m_running) + { + DVP_Image_t *pImage = NULL; + + // while there's frames to read... + DVP_PRINT(DVP_ZONE_CAM, "SocketVisionCam Waiting on Image in Queue!\n"); + if (queue_read(m_imgs, true_e, &pImage) == true_e) + { + uint32_t offset = 0; + uint32_t len = 0; + + if (m_running == false_e || m_frameData == NULL) + break; + + DVP_PRINT(DVP_ZONE_CAM, "SocketVisionCam Waiting on VisionCamFrame!\n"); + if (socket_recv(m_data, (uint8_t *)&len, sizeof(uint32_t)) == false || len == 0) + break; + + if (socket_recv(m_data, &m_frameData[offset], len) == false_e) + { + DVP_PRINT(DVP_ZONE_WARNING, "Failed to read frame header, socket could be closing!\n"); + if (m_running == false_e || m_frameData == NULL) + break; + } + + // fill in the data in the frame data + frame.mFrameBuff = pImage; + frame.mCookie = m_cookie; + + // read the whole frame in + offset += frame.unserialize(&m_frameData[offset], len-offset); + + DVP_PRINT(DVP_ZONE_CAM, "SocketVisionCam Calling Callback!\n"); + + // call the client + if (m_callback) + m_callback(&frame); + + // free the meta data if it existed + if (frame.mMetadata.mAutoWBGains) { + free(frame.mMetadata.mAutoWBGains); + frame.mMetadata.mAutoWBGains = NULL; + } + if (frame.mMetadata.mManualWBGains) { + free(frame.mMetadata.mManualWBGains); + frame.mMetadata.mManualWBGains = NULL; + } + if (frame.mMetadata.mAncillary) { + free(frame.mMetadata.mAncillary); + frame.mMetadata.mAncillary = NULL; + } + } + else + { + DVP_PRINT(DVP_ZONE_WARNING, "Failed to read queue for Images. We may be exitting.\n"); + break; + } + ret = (thread_ret_t)0; + } + + socket_disconnect(m_data); + socket_deinit(m_data); + m_data = NULL; + + } + DVP_PRINT(DVP_ZONE_CAM, "SocketVisionCam Data Thread Exiting!\n"); + thread_exit(ret); +} + +#endif diff --git a/source/dvp/VisionCam/SocketVisionCam.h b/source/dvp/VisionCam/SocketVisionCam.h new file mode 100644 index 0000000..6f9f1e5 --- /dev/null +++ b/source/dvp/VisionCam/SocketVisionCam.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SOCKET_VCAM_H_ +#define _SOCKET_VCAM_H_ + +#include +#include +#include + +// we can't have the socket cam without RPC sockets +#if defined(SOSAL_RPC_SOCKET_API) + +#define VCAM_SUPPORTS_SOCKETCAM +#define VCAM_SOCKET_CMD_PORT (8501) +#define VCAM_SOCKET_DATA_PORT (8502) +#define VCAM_MAX_PACKET_SIZE (1400) +#define VCAM_HEADER_MAGIC ('G' >> 0 | 'C' >> 8 | 'A' >> 16 | 'M' >> 24) + +typedef enum _vcam_function_e { + VISIONCAM_FUNCTION_INIT, + VISIONCAM_FUNCTION_DEINIT, + VISIONCAM_FUNCTION_SETPARAMS, + VISIONCAM_FUNCTION_GETPARAMS, + VISIONCAM_FUNCTION_SENDCMD, + VISIONCAM_FUNCTION_USEBUFS, + VISIONCAM_FUNCTION_RLSBUFS, + VISIONCAM_FUNCTION_FLUSHBUFS, + VISIONCAM_FUNCTION_MAX, +} VisionCamFunction_e; + +typedef enum _socket_vcam_param_ext_t { + SOCKETVCAM_PARAM_MIN = VCAM_PARAM_MAX, + SOCKETVCAM_PARAM_HOSTNAME, +} SocketVisionCam_Param_e; + +typedef struct _vcam_image_t { + uint32_t width; + uint32_t height; + uint32_t color; + uint32_t count; + uint32_t port; +} VisionCamImages_t; + +/** + * This class sit on top of a socket and commands a remote VisionCam. + */ +class SocketVisionCam : public CThreaded, public VisionCam { +protected: + queue_t *m_imgs; /**< A queue of DVP Images */ + socket_t *m_data; /**< Socket to VisionCam server for frame data */ + uint32_t m_ipaddr; /**< The binary host address */ + uint8_t *m_frameData; + uint32_t m_numDataBytes; + uint32_t m_numImgBytes; + rpc_client_t *m_client; + char m_hostname[MAX_PATH]; + char m_filename[MAX_PATH]; + FILE *pFile; +public: + SocketVisionCam(); + virtual ~SocketVisionCam(); + + // VisionCam interface + status_e init(void *cookie); + status_e deinit(); + status_e useBuffers(DVP_Image_t *pImages, uint32_t numImages, VisionCamPort_e port ); + status_e releaseBuffers(VisionCamPort_e port); + status_e flushBuffers(VisionCamPort_e port); + status_e sendCommand(VisionCamCmd_e cmdId, void *param = NULL, uint32_t size = 0, VisionCamPort_e port = VCAM_PORT_ALL); + status_e setParameter(VisionCamParam_e paramId, void* param = NULL, uint32_t size = 0, VisionCamPort_e port = VCAM_PORT_ALL); + status_e getParameter(VisionCamParam_e paramId, void* param = NULL, uint32_t size = 0, VisionCamPort_e port = VCAM_PORT_ALL); + status_e returnFrame(VisionCamFrame *cameraFrame); + + // CThreaded + thread_ret_t RunThread(); + void Shutdown(); + +}; + +#endif // SOSAL_RPC_SOCKET_API + +#endif // _SOCKET_VCAM_H_ + diff --git a/source/dvp/VisionCam/UVCVisionCam.cpp b/source/dvp/VisionCam/UVCVisionCam.cpp new file mode 100644 index 0000000..30bcd27 --- /dev/null +++ b/source/dvp/VisionCam/UVCVisionCam.cpp @@ -0,0 +1,299 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +UVCVisionCam::UVCVisionCam() : CThreaded(), + m_frame() +{ + m_dev = NULL; + for (uint32_t i = 0; i < dimof(m_images); i++) + m_images[i] = NULL; + m_numImages = 0; + m_curImage = 0; +} +UVCVisionCam::~UVCVisionCam() +{ + if (m_dev) + v4l2_close(&m_dev); +} + +// interface methods +status_e UVCVisionCam::init(void *cookie) +{ + int device_num = 0; +#if defined(PANDA) + device_num = 1; +#endif + m_dev = v4l2_open(device_num, V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING, false_e); + m_frame.clear(); + m_frame.mCookie = cookie; + if (m_dev) + return STATUS_SUCCESS; + else + return STATUS_NO_RESOURCES; +} +status_e UVCVisionCam::deinit() +{ + if (m_dev) + v4l2_close(&m_dev); + m_frame.clear(); + return STATUS_SUCCESS; +} + +status_e UVCVisionCam::useBuffers(DVP_Image_t *prvBufArr, uint32_t numPrvBuf, VisionCamPort_e port __attribute__((unused))) +{ + status_e status = STATUS_SUCCESS; + if (numPrvBuf > 0) + { + if (m_color != prvBufArr[0].color) + { + DVP_PRINT(DVP_ZONE_ERROR, "Images are in the wrong color space!\n"); + return STATUS_INVALID_PARAMETER; + } + m_numImages = numPrvBuf; + for (uint32_t i = 0; i < m_numImages; i++) + m_images[i] = &prvBufArr[i]; + m_frame.mContext = this; + m_frame.mWidth = m_images[0]->width; + m_frame.mHeight = m_images[0]->height; + m_frame.mLength = m_images[0]->numBytes; + } + else + { + for (uint32_t i = 0; i < dimof(m_images); i++) + m_images[i] = NULL; + } + + // most UVC cameras will only support YUY2 or RGB + if (v4l2_allocate(m_dev, m_images[0]->width, m_images[0]->height, m_numImages, FOURCC_YUY2, V4L2_BUF_TYPE_VIDEO_CAPTURE) == false_e) + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to allocate V4L2 buffers!\n"); + status = STATUS_NO_RESOURCES; + } + return status; +} +status_e UVCVisionCam::releaseBuffers(VisionCamPort_e port __attribute__((unused))) +{ + if (v4l2_free(m_dev)) + return STATUS_SUCCESS; + else + return STATUS_FAILURE; +} +status_e UVCVisionCam::flushBuffers(VisionCamPort_e port __attribute__((unused))) +{ + // nothing to do? + return STATUS_SUCCESS; +} + +status_e UVCVisionCam::sendCommand(VisionCamCmd_e cmdId, void *param, uint32_t size, VisionCamPort_e port __attribute__((unused))) +{ + status_e status = STATUS_SUCCESS; + DVP_PRINT(DVP_ZONE_CAM, "UVC: CMD %u (0x%08x) %p %u\n", cmdId, cmdId, param, size); + switch (cmdId) + { + case VCAM_CMD_PREVIEW_START: + StartThread(this); + break; + case VCAM_CMD_PREVIEW_STOP: + case VCAM_CMD_QUIT: + StopThread(); + break; + case VCAM_EXTRA_DATA_START: + case VCAM_EXTRA_DATA_STOP: + break; // lie + default: + status = STATUS_NOT_IMPLEMENTED; + break; + } + return status; +} + +status_e UVCVisionCam::setParameter(VisionCamParam_e paramId, void* param, uint32_t size, VisionCamPort_e port __attribute__((unused))) +{ + status_e status = STATUS_SUCCESS; + DVP_PRINT(DVP_ZONE_CAM, "UVC: PARAM %u (0x%08x) %p %u\n", paramId, paramId, param, size); + switch (paramId) + { + case VCAM_PARAM_WIDTH: + if (size == sizeof(uint32_t)) + m_frame.mWidth = *(uint32_t *)param; + break; + case VCAM_PARAM_HEIGHT: + if (size == sizeof(uint32_t)) + m_frame.mHeight = *(uint32_t *)param; + break; + case VCAM_PARAM_COLOR_SPACE_FOURCC: + if (size == sizeof(fourcc_t)) + m_color = *(fourcc_t *)param; + break; + case VCAM_PARAM_FPS_FIXED: + if (size == sizeof(uint32_t)) + m_fps = *(uint32_t *)param; + break; + case VCAM_PARAM_EXPOSURE_ISO: + { + int value = 0; + if (size == sizeof(int)) + value = *(int *)param; + v4l2_control_set(m_dev, V4L2_CID_EXPOSURE, value); + break; + } + case VCAM_PARAM_BRIGHTNESS: + { + int value = 0; + if (size == sizeof(int)) + value = *(int *)param; + v4l2_control_set(m_dev, V4L2_CID_BRIGHTNESS, value); + break; + } + case VCAM_PARAM_CONTRAST: + { + int value = 0; + if (size == sizeof(int)) + value = *(int *)param; + v4l2_control_set(m_dev, V4L2_CID_CONTRAST, value); + break; + } + case VCAM_PARAM_SATURATION: + { + int value = 0; + if (size == sizeof(int)) + value = *(int *)param; + v4l2_control_set(m_dev, V4L2_CID_SATURATION, value); + break; + } + default: + status = STATUS_SUCCESS; + break; + } + return status; +} + +status_e UVCVisionCam::getParameter(VisionCamParam_e paramId, void* param, uint32_t size, VisionCamPort_e port __attribute__((unused))) +{ + status_e status = STATUS_NOT_IMPLEMENTED; + switch (paramId) + { + case VCAM_PARAM_2DBUFFER_DIM: + if (size == sizeof(VisionCamResType)) + { + VisionCamResType *pRes = (VisionCamResType *)param; + pRes->mWidth = m_frame.mWidth; + pRes->mHeight = m_frame.mHeight; + pRes->mResIdx = VCAM_RESOL_MAX; + for (int32_t i = 0; i < dimof(VisionCamResolutions); i++) + { + if (pRes->mWidth == VisionCamResolutions[i].mWidth && + pRes->mHeight == VisionCamResolutions[i].mHeight) + pRes->mResIdx = (VisionCamResolIdex)i; + } + status = STATUS_SUCCESS; + } + break; + default: + break; + } + return status; +} + +status_e UVCVisionCam::returnFrame(VisionCamFrame *cameraFrame) +{ + return STATUS_SUCCESS; +} + +thread_ret_t UVCVisionCam::RunThread() +{ + uint32_t index = 0xFFFFFFFF; + void *buffer = NULL; + + DVP_PRINT(DVP_ZONE_CAM, "UVC Dequeue Thread Running!\n"); + + // queue up all buffers + for (uint32_t i = 0; i < m_numImages; i++) + { + buffer = v4l2_acquire(m_dev, &index); + if (buffer) + { + if (v4l2_queue(m_dev, index, V4L2_BUF_TYPE_VIDEO_CAPTURE)) + + { + DVP_PRINT(DVP_ZONE_CAM, "UVC: Queued %p[%u] to UVC\n", buffer, index); + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to queue %p[%u]\n", buffer, index); + } + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to acquire buffer num %u\n", i); + } + } + v4l2_start(m_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE); + + index = 0xFFFFFFFF; + buffer = NULL; + + while (m_running) + { + //if (v4l2_wait(m_dev)) + { + if (v4l2_dequeue(m_dev, &index, V4L2_BUF_TYPE_VIDEO_CAPTURE) == true_e) + { + buffer = v4l2_search_index(m_dev, index); + if (buffer) + { + DVP_U08 *ptr = (DVP_U08 *)buffer; + DVP_Image_t image = *m_images[m_curImage]; // copy meta fields, pointers will be recalculated + // copy image pointer over + image.pData[0] = ptr; + image.color = FOURCC_YUY2; + + /// @todo reconstruct multi-plane formats.... + if (image.color == FOURCC_NV12) + { + image.pData[1] = &ptr[image.bufHeight * image.y_stride]; + } + + if (DVP_Image_Copy(m_images[m_curImage], &image) == DVP_TRUE) + { + m_frame.mFrameBuff = m_images[m_curImage]; + m_frame.mTimestamp = rtimer_now(); + if (m_callback) + m_callback(&m_frame); + m_curImage = (m_curImage + 1)%m_numImages; + } + } + else + { + DVP_PRINT(DVP_ZONE_CAM, "Failed to find buffer with index %u\n", index); + } + + // requeue the buffer... + v4l2_queue(m_dev, index, V4L2_BUF_TYPE_VIDEO_CAPTURE); + } + } + } + DVP_PRINT(DVP_ZONE_CAM, "UVC Dequeue Thread Exiting!\n"); + thread_exit(0); +} + +void UVCVisionCam::Shutdown() +{ + v4l2_stop(m_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE); +} + diff --git a/source/dvp/VisionCam/UVCVisionCam.h b/source/dvp/VisionCam/UVCVisionCam.h new file mode 100644 index 0000000..b86f800 --- /dev/null +++ b/source/dvp/VisionCam/UVCVisionCam.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _UVC_VISION_CAM_H_ +#define _UVC_VISION_CAM_H_ + +#if defined(LINUX) + +#include +#include +#include + +#define UVC_MAX_IMAGES (10) + +class UVCVisionCam : public CThreaded, public VisionCam +{ +protected: + v4l2_api_t *m_dev; + DVP_Image_t *m_images[UVC_MAX_IMAGES]; + uint32_t m_numImages; + uint32_t m_curImage; + VisionCamFrame m_frame; + fourcc_t m_color; + uint32_t m_fps; + +public: + UVCVisionCam(); + virtual ~UVCVisionCam(); + + // interface methods + status_e init(void * cookie); + status_e deinit(); + status_e startPreview(); + status_e stopPreview(); + status_e useBuffers(DVP_Image_t *prvBufArr, uint32_t numPrvBuf, VisionCamPort_e port=VCAM_PORT_PREVIEW); + status_e releaseBuffers(VisionCamPort_e port=VCAM_PORT_PREVIEW); + status_e flushBuffers(VisionCamPort_e port=VCAM_PORT_PREVIEW); + status_e sendCommand(VisionCamCmd_e cmdId, void *param, uint32_t size, VisionCamPort_e port=VCAM_PORT_PREVIEW); + status_e setParameter(VisionCamParam_e paramId, void* param, uint32_t size, VisionCamPort_e port=VCAM_PORT_PREVIEW); + status_e getParameter(VisionCamParam_e paramId, void* param, uint32_t size, VisionCamPort_e port=VCAM_PORT_PREVIEW); + status_e returnFrame(VisionCamFrame *cameraFrame); + + // CThreaded + thread_ret_t RunThread(); + void Shutdown(); +}; + +#endif + +#endif + diff --git a/source/dvp/VisionCam/VisionCamFactory.cpp b/source/dvp/VisionCam/VisionCamFactory.cpp new file mode 100644 index 0000000..e7e347b --- /dev/null +++ b/source/dvp/VisionCam/VisionCamFactory.cpp @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#if defined(VCAM_USE_OMX) +#include +#endif +#if defined(VCAM_USE_USB) && defined(LINUX) +#include +#endif + +extern "C" VisionCam * VisionCamFactory(VisionCam_e type) +{ + VisionCam *handle = NULL; + switch (type) + { +#if defined(VCAM_USE_OMX) + case VISIONCAM_OMX: + handle = new OMXVisionCam(); + break; +#endif +#if defined(VCAM_USE_USB) && defined(LINUX) + case VISIONCAM_USB: + handle = new UVCVisionCam(); + break; +#endif +#if defined(VCAM_SUPPORTS_SOCKETCAM) + case VISIONCAM_SOCKET: + handle = new SocketVisionCam(); + break; +#endif +#if defined(DVP_USE_FS) + case VISIONCAM_FILE: + default: + handle = new FileVisionCam(); + break; +#else + default: + break; +#endif + } + return handle; +} + +VisionCam::VisionCam() : + m_callback(NULL), + m_pack_callback(NULL), + m_focuscallback(NULL), + m_cookie(NULL), + m_frameNum(0) +{ + DVP_PRINT(DVP_ZONE_API, "VisionCam()\n"); +} + +VisionCam::~VisionCam() +{ + DVP_PRINT(DVP_ZONE_API, "~VisionCam()\n"); +} + +uint32_t VisionCam::GetFrameNumber() +{ + return m_frameNum; +} + +/** Enable frame notification callback */ +status_e VisionCam::enablePreviewCbk(FrameCallback_f callback) +{ + status_e greError = STATUS_SUCCESS; + if (m_callback == NULL) + { + DVP_PRINT(DVP_ZONE_CAM, "Enabling Callback to %p\n", callback); + m_callback = callback; + } + else + greError = STATUS_INVALID_STATE; + return greError; +} + +status_e VisionCam::enablePackedFramesCbk(FramePackCallback_f callback) +{ + status_e greError = STATUS_SUCCESS; + if (m_pack_callback == NULL) + { + DVP_PRINT(DVP_ZONE_CAM, "Enabling Pack Callback to %p\n", callback); + m_pack_callback = callback; + } + else + greError = STATUS_INVALID_STATE; + return greError; +} + + +/** disable frame notification callback */ +status_e VisionCam::disablePreviewCbk(FrameCallback_f callback) +{ + status_e greError = STATUS_SUCCESS; + if (callback == m_callback) + { + DVP_PRINT(DVP_ZONE_CAM, "Disabling Callback to %p\n", callback); + m_callback = NULL; + } + else + greError = STATUS_INVALID_STATE; + return greError; +} + +status_e VisionCam::disablePackedFramesCbk(FramePackCallback_f callback) +{ + status_e greError = STATUS_SUCCESS; + if ( callback == m_pack_callback ) + { + DVP_PRINT(DVP_ZONE_CAM, "Disabling Pack Callback to %p\n", callback); + m_pack_callback = NULL; + } + else + greError = STATUS_INVALID_STATE; + return greError; +} + +/** Allows the client to set the focus callback */ +status_e VisionCam::setFocusCallBack(FocusCallback_t callback) +{ + m_focuscallback = callback; + return STATUS_SUCCESS; +} + + +uint32_t GetImageSize(uint32_t width, uint32_t height, fourcc_t fourcc) +{ + uint32_t size = 0; + switch (fourcc) + { + case FOURCC_Y800: + size = height * width; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + case FOURCC_YVYU: + case FOURCC_VYUY: + size = height * width * 2; + break; + case FOURCC_IYUV: + case FOURCC_YV12: + size = (height * width * 3)/2; + break; + case FOURCC_YUV9: + break; + case FOURCC_BGR: + case FOURCC_RGB: + case FOURCC_RGBP: + size = height * width * 3; + break; + case FOURCC_RGBA: + case FOURCC_BGRA: + case FOURCC_ARGB: + case FOURCC_HSLP: + size = height * width * 4; + default: + break; + } + return size; +} + +VisionCamFrame::VisionCamFrame() +{ + clear(); +} + +void VisionCamFrame::clear() +{ + mContext = NULL; + mCookie = NULL; + mFrameBuff = NULL; + mExtraDataBuf = NULL; + mFrameSource = VCAM_PORT_PREVIEW; // default to the common preview port + mFd = 0; + mTimestamp = 0; + mWidth = 0; + mHeight = 0; + mOffsetX = 0; + mOffsetY = 0; + mStartX = 0; + mStartY = 0; + mLength = 0; + mExtraDataLength = 0; + mMetadata.mAncillary = NULL; + mMetadata.mAutoWBGains = NULL; + mMetadata.mManualWBGains = NULL; + mMetadata.mHistogram2D = NULL; + mMetadata.mHistogramL = NULL; + mMetadata.mHistogramR = NULL; + mMetadata.mGamma2D = NULL; + mMetadata.mGammaL = NULL; + mMetadata.mGammaR = NULL; + mMetadata.mUnsaturatedRegions = NULL; + mMetadata.mMTIS_Data = NULL; + mMetadata.mFocusRegionData = NULL; + + mDetectedFacesNum = 0; + memset(&mFaces, 0, sizeof(mFaces)); + mDetectedFacesNumRaw = 0; + memset(&mFacesRaw, 0, sizeof(mFacesRaw)); +} + diff --git a/source/dvp/VisionCam/VisionCamFrame.cpp b/source/dvp/VisionCam/VisionCamFrame.cpp new file mode 100644 index 0000000..b1f721c --- /dev/null +++ b/source/dvp/VisionCam/VisionCamFrame.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#define VCAM_META_NONE (0x0) +#define VCAM_META_AUTOWB (0x1) +#define VCAM_META_MANUALWB (0x2) +#define VCAM_META_ANCILLARY (0x4) +#define VCAM_META_HISTO_2D (0x8) +#define VCAM_META_HISTO_L (0x10) +#define VCAM_META_HISTO_R (0x20) +#define VCAM_META_FACES (0x40) +#define VCAM_META_FACES_RAW (0x80) +#define VCAM_META_UNSATURATED_REG (0x100) +#define VCAM_META_FOCUS_REG (0x200) +#define VCAM_META_MTIS (0x400) +#define VCAM_META_GAMMA_2D (0x800) +#define VCAM_META_GAMMA_L (0x1000) +#define VCAM_META_GAMMA_R (0x2000) + +typedef struct _vcam_frame_header_t { + uint32_t length; /**< The length of the entire data packet */ + uint32_t count; /**< The frame count */ + uint32_t metadata; /**< A bit field of which metadata is present */ + uint32_t numFaces; /**< A count of the number of faces detected */ +} VisionCamFrameHeader_t; + +#define CALLOC_STRUCT(ptr, type) ptr = (type *)calloc(1, sizeof(type)) + +size_t VisionCamFrame::maxSerialLength() +{ + size_t size = 0; + + size += sizeof(mFrameSource); + size += sizeof(mTimestamp); + size += sizeof(mWidth); + size += sizeof(mHeight); + size += sizeof(mOffsetX); + size += sizeof(mOffsetY); + size += sizeof(mStartX); + size += sizeof(mStartY); + size += sizeof(mLength); + size += sizeof(mExtraDataLength); + size += sizeof(VisionCamWhiteBalGains); + size += sizeof(VisionCamWhiteBalGains); + size += sizeof(VisionCamAncillary); +#if defined(VCAM_SUPPORT_HISTO_SERIALIZE) + size += sizeof(VisionCamHistogram); + size += sizeof(VisionCamHistogram); +#endif + size += sizeof(mDetectedFacesNum); + size += sizeof(mFaces); + size += sizeof(mDetectedFacesNumRaw); + size += sizeof(mFacesRaw); + size += DVP_Image_Size((DVP_Image_t *)mFrameBuff); + return size; +} + +/** This serializes all data in the frame into a flat buffer */ +size_t VisionCamFrame::serialize(uint8_t *buffer, size_t len) +{ + size_t offset = 0; + uint32_t metadata = 0; + DVP_Image_t *pImage = (DVP_Image_t *)mFrameBuff; + SERIALIZE_UNIT(buffer, offset, len, mFrameSource); + SERIALIZE_UNIT(buffer, offset, len, mTimestamp); + SERIALIZE_UNIT(buffer, offset, len, mWidth); + SERIALIZE_UNIT(buffer, offset, len, mHeight); + SERIALIZE_UNIT(buffer, offset, len, mOffsetX); + SERIALIZE_UNIT(buffer, offset, len, mOffsetY); + SERIALIZE_UNIT(buffer, offset, len, mStartX); + SERIALIZE_UNIT(buffer, offset, len, mStartY); + SERIALIZE_UNIT(buffer, offset, len, mLength); + SERIALIZE_UNIT(buffer, offset, len, mExtraDataLength); + if (mMetadata.mAutoWBGains) + metadata |= VCAM_META_AUTOWB; + if (mMetadata.mManualWBGains) + metadata |= VCAM_META_MANUALWB; + if (mMetadata.mAncillary) + metadata |= VCAM_META_ANCILLARY; + if (mMetadata.mHistogram2D) + metadata |= VCAM_META_HISTO_2D; + if (mMetadata.mHistogramL) + metadata |= VCAM_META_HISTO_L; + if (mMetadata.mHistogramR) + metadata |= VCAM_META_HISTO_R; + if (mMetadata.mGamma2D) + metadata |= VCAM_META_GAMMA_2D; + if (mMetadata.mGammaL) + metadata |= VCAM_META_GAMMA_L; + if (mMetadata.mGammaR) + metadata |= VCAM_META_GAMMA_R; + if (mMetadata.mUnsaturatedRegions > 0) + metadata |= VCAM_META_UNSATURATED_REG; + if (mMetadata.mFocusRegionData > 0) + metadata |= VCAM_META_FOCUS_REG; + if (mMetadata.mMTIS_Data > 0) + metadata |= VCAM_META_MTIS; + if (mDetectedFacesNum > 0) + metadata |= VCAM_META_FACES; + if (mDetectedFacesNumRaw > 0) + metadata |= VCAM_META_FACES_RAW; + SERIALIZE_UNIT(buffer, offset, len, metadata); + if (mMetadata.mAutoWBGains) + SERIALIZE_ARRAY(buffer, offset, len, mMetadata.mAutoWBGains, sizeof(VisionCamWhiteBalGains)); + if (mMetadata.mManualWBGains) + SERIALIZE_ARRAY(buffer, offset, len, mMetadata.mManualWBGains, sizeof(VisionCamWhiteBalGains)); + if (mMetadata.mAncillary) + SERIALIZE_ARRAY(buffer, offset, len, mMetadata.mAncillary, sizeof(VisionCamAncillary)); +#if defined(VCAM_SUPPORT_HISTO_SERIALIZE) + if (mMetadata.mHistogram2D) { + SERIALIZE_ARRAY(buffer, offset, len, mMetadata.mHistogram2D, sizeof(VisionCamHistogram)); + } + if (mMetadata.mHistogramL) { + SERIALIZE_ARRAY(buffer, offset, len, mMetadata.mHistogramL, sizeof(VisionCamHistogram)); + } + if (mMetadata.mHistogramR) { + SERIALIZE_ARRAY(buffer, offset, len, mMetadata.mHistogramR, sizeof(VisionCamHistogram)); + } +#endif + if (mMetadata.mGamma2D) { + SERIALIZE_ARRAY(buffer, offset, len, mMetadata.mGamma2D, sizeof(VisionCamGamma)); + } + if (mMetadata.mGammaL) { + SERIALIZE_ARRAY(buffer, offset, len, mMetadata.mGammaL, sizeof(VisionCamGamma)); + } + if (mMetadata.mGammaR) { + SERIALIZE_ARRAY(buffer, offset, len, mMetadata.mGammaR, sizeof(VisionCamGamma)); + } + if( mMetadata.mUnsaturatedRegions ) + SERIALIZE_ARRAY(buffer, offset, len, mMetadata.mUnsaturatedRegions, sizeof(VisionCamUnsaturatedRegions)); + if( mMetadata.mFocusRegionData ) + SERIALIZE_ARRAY(buffer, offset, len, mMetadata.mFocusRegionData, sizeof(VisionCamFocusRegion)); + if( mMetadata.mMTIS_Data ) + SERIALIZE_ARRAY(buffer, offset, len, mMetadata.mMTIS_Data, sizeof(VisionCamMTIS)); + + SERIALIZE_UNIT(buffer, offset, len, mDetectedFacesNum); + SERIALIZE_ARRAY(buffer, offset, len, mFaces, sizeof(mFaces)); + + SERIALIZE_UNIT(buffer, offset, len, mDetectedFacesNumRaw); + SERIALIZE_ARRAY(buffer, offset, len, mFacesRaw, sizeof(mFacesRaw)); + + offset += DVP_Image_Serialize(pImage, &buffer[offset], len-offset); + + return offset; +} + +/** This unserializes all the data from a flat buffer back into the instance class object */ +size_t VisionCamFrame::unserialize(uint8_t *buffer, size_t len) +{ + size_t offset = 0; + uint32_t metadata = 0; + DVP_Image_t *pImage = (DVP_Image_t *)mFrameBuff; + UNSERIALIZE_UNIT(buffer, offset, len, mFrameSource); + UNSERIALIZE_UNIT(buffer, offset, len, mTimestamp); + UNSERIALIZE_UNIT(buffer, offset, len, mWidth); + UNSERIALIZE_UNIT(buffer, offset, len, mHeight); + UNSERIALIZE_UNIT(buffer, offset, len, mOffsetX); + UNSERIALIZE_UNIT(buffer, offset, len, mOffsetY); + UNSERIALIZE_UNIT(buffer, offset, len, mStartX); + UNSERIALIZE_UNIT(buffer, offset, len, mStartY); + UNSERIALIZE_UNIT(buffer, offset, len, mLength); + UNSERIALIZE_UNIT(buffer, offset, len, mExtraDataLength); + UNSERIALIZE_UNIT(buffer, offset, len, metadata); + if (metadata & VCAM_META_AUTOWB) { + CALLOC_STRUCT(mMetadata.mAutoWBGains, VisionCamWhiteBalGains); + UNSERIALIZE_ARRAY(buffer, offset, len, mMetadata.mAutoWBGains, sizeof(VisionCamWhiteBalGains)); + } + if (metadata & VCAM_META_MANUALWB) { + CALLOC_STRUCT(mMetadata.mManualWBGains, VisionCamWhiteBalGains); + UNSERIALIZE_ARRAY(buffer, offset, len, mMetadata.mManualWBGains, sizeof(VisionCamWhiteBalGains)); + } + if (metadata & VCAM_META_ANCILLARY) { + CALLOC_STRUCT(mMetadata.mAncillary, VisionCamAncillary); + UNSERIALIZE_ARRAY(buffer, offset, len, mMetadata.mAncillary, sizeof(VisionCamAncillary)); + } +#if defined(VCAM_SUPPORT_HISTO_SERIALIZE) + if (metadata & VCAM_META_HISTO_2D) { + CALLOC_STRUCT(mMetadata.mHistogram2D, VisionCamHistogram); + UNSERIALIZE_ARRAY(buffer, offset, len, mMetadata.mHistogram2D, sizeof(VisionCamHistogram)); + } + if (metadata & VCAM_META_HISTO_L) { + CALLOC_STRUCT(mMetadata.mHistogramL, VisionCamHistogram); + UNSERIALIZE_ARRAY(buffer, offset, len, mMetadata.mHistogramL, sizeof(VisionCamHistogram)); + } + if (metadata & VCAM_META_HISTO_R) { + CALLOC_STRUCT(mMetadata.mHistogramR, VisionCamHistogram); + UNSERIALIZE_ARRAY(buffer, offset, len, mMetadata.mHistogramR, sizeof(VisionCamHistogram)); + } +#endif + if (metadata & VCAM_META_GAMMA_2D) { + CALLOC_STRUCT(mMetadata.mGamma2D, VisionCamGamma); + UNSERIALIZE_ARRAY(buffer, offset, len, mMetadata.mGamma2D, sizeof(VisionCamGamma)); + } + if (metadata & VCAM_META_GAMMA_L) { + CALLOC_STRUCT(mMetadata.mGammaL, VisionCamGamma); + UNSERIALIZE_ARRAY(buffer, offset, len, mMetadata.mGammaL, sizeof(VisionCamGamma)); + } + if (metadata & VCAM_META_GAMMA_R) { + CALLOC_STRUCT(mMetadata.mGammaR, VisionCamGamma); + UNSERIALIZE_ARRAY(buffer, offset, len, mMetadata.mGammaR, sizeof(VisionCamGamma)); + } + if (metadata & VCAM_META_UNSATURATED_REG) { + CALLOC_STRUCT(mMetadata.mUnsaturatedRegions, VisionCamUnsaturatedRegions); + UNSERIALIZE_ARRAY(buffer, offset, len, mMetadata.mUnsaturatedRegions, sizeof(VisionCamUnsaturatedRegions)); + } + if (metadata & VCAM_META_FOCUS_REG) { + CALLOC_STRUCT(mMetadata.mFocusRegionData, VisionCamFocusRegion); + UNSERIALIZE_ARRAY(buffer, offset, len, mMetadata.mFocusRegionData, sizeof(VisionCamFocusRegion)); + } + if (metadata & VCAM_META_MTIS) { + CALLOC_STRUCT(mMetadata.mMTIS_Data, VisionCamMTIS); + UNSERIALIZE_ARRAY(buffer, offset, len, mMetadata.mMTIS_Data, sizeof(VisionCamMTIS)); + } + + UNSERIALIZE_UNIT(buffer, offset, len, mDetectedFacesNum); + UNSERIALIZE_ARRAY(buffer, offset, len, mFaces, sizeof(mFaces)); + + UNSERIALIZE_UNIT(buffer, offset, len, mDetectedFacesNumRaw); + UNSERIALIZE_ARRAY(buffer, offset, len, mFacesRaw, sizeof(mFacesRaw)); + + offset += DVP_Image_Unserialize(pImage, &buffer[offset], len-offset); + + return offset; +} + diff --git a/source/dvp/VisionCam/VisionCamFrameManager.cpp b/source/dvp/VisionCam/VisionCamFrameManager.cpp new file mode 100644 index 0000000..19e43ae --- /dev/null +++ b/source/dvp/VisionCam/VisionCamFrameManager.cpp @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "VisionCam.h" + +class VisionCamFrameManager +{ +public: + enum FrameProperty_t{ + FrameBuffer_e, + FrameTimeStamp_e, + FrameNode_e + }; + + enum FrameOperation_t{ + Alloc_e = 1 << 1, + Dealloc_e = 1 << 2, + Set_e = 1 << 3, + Get_e = 1 << 4, + Add_e = 1 << 5, + Remove_e = 1 << 6 + }; + + enum OperationLock_t { + NoneLock_e = 0, + ReadLock_e = Alloc_e | Dealloc_e | Get_e | Remove_e, + WriteLock_e = Alloc_e | Dealloc_e | Set_e | Remove_e + }; + + VisionCamFrameManager(); + ~VisionCamFrameManager(); + + bool_e Alloc (VisionCamFrame*); + bool_e Dealloc (VisionCamFrame*); + bool_e Add (VisionCamFrame*); + bool_e Remove (VisionCamFrame*); + bool_e Get (VisionCamFrame*, FrameProperty_t, void*); + bool_e Set (VisionCamFrame*); + bool_e Lock (VisionCamFrame*, OperationLock_t); + bool_e Unlock (VisionCamFrame*, OperationLock_t); + +private: + void *AllocBuffer(); + bool_e DeallocBuffer(void*); + +protected: + struct FrameQueueNode_t { + VisionCamFrame *frame; + OperationLock_t lock; + }; + queue_t *qFrames; +}; + +VisionCamFrameManager::VisionCamFrameManager( int32_t numFrms) +{ + qFrames = NULL; + qFrames = queue_create( numFrms , sizeof(FrameQueueNode_t) ); +} + +VisionCamFrameManager::~VisionCamFrameManager() +{ + queue_destroy(qFrames); +} + +bool_e VisionCamFrameManager::Alloc(VisionCamFrame* frm, FrameOperation_t op) +{ + if( frm ) + { + if( !frm->mFrameBuff ) + frm->mFrameBuff = AllocBuffer(); + } +} + +bool_e VisionCamFrameManager::Dealloc(VisionCamFrame* frm) +{ + bool_e ret = false_e; + if( frm ) + { +// Lock(frm, Dealloc_e); + if( Remove(frm) ) + ret = DeallocBuffer(frm->mFrameBuff); + } + + return ret; +} + +bool_e VisionCamFrameManager::Add( VisionCamFrame* frm ) +{ + bool_e ret = false_e; + FrameQueueNode_t *fr = NULL; + + if( frm && qFrames ) + { +// Lock( frm, Alloc_e | Add_e ); + fr = new FrameQueueNode_t; + fr->frame = frm; + + ret = queue_write( qFrames, false_e, fr); + } + + return ret; +} + +bool_e VisionCamFrameManager::Remove( VisionCamFrame* frm) +{ + bool_e ret = false_e; + FrameQueueNode_t *fNode = NULL; + + if( frm ) + { + Lock(frm, ReadLock_e | WriteLock_e ); + if ( Get(frm, FrameNode_e, fNode) ) + { + delete fNode; + fNode = NULL; + } + // dont need to unlock because it won't exist anymore + } + + return ret; +} + +bool_e VisionCamFrameManager::Get(VisionCamFrame* frm, FrameProperty_t p, void* dest) +{ + bool_e ret = false_e; + FrameQueueNode_t *fr = NULL; + + if( frm && qFrames ) + { + Lock(frm, WriteLock_e ); + while( queue_length(qFrames ) ) + { + queue_read( qFrames, false_e, fr); + + if( !fr ) + continue; + + switch(p) + { + case FrameBuffer_e: + if( fr->frame == frm->mFrameBuff ) + { + dest = fr->frame;//->mFrameBuff; + ret = true_e; + } + break; + + case FrameTimeStamp_e: + if( fr->frame->mTimestamp == frm->mTimestamp ) + { + dest = fr->frame; + ret = true_e; + } + break; + + case FrameNode_e: + if(fr->frame == frm->mFrameBuff) + { + dest = fr; + ret = true_e; + } + break; + } + } + Unlock(frm, WriteLock_e ); + } + + return ret; +} + +bool_e VisionCamFrameManager::Set(VisionCamFrame *fr) +{ + bool_e ret = false_e; + FrameQueueNode_t *fNode = NULL; + if( fr && qFrames ) + { + return true_e; + Lock(frm, ReadLock_e ); + while( queue_length(qFrames ) ) + { + queue_read( qFrames, false_e, fNode); + + if( !fNode ) + continue; + + if( fNode && fNode->frame && fNode->frame->mFrameBuff == fr->mFrameBuff ) + { + memcpy(fNode->frame, fr, sizeof(VisionCamFrame));/// @todo check other possibilities + } + } + Unlock(frm, ReadLock_e ); + } + + return ret; +} + +bool_e VisionCamFrameManager::Lock(VisionCamFrame *fr, OperationLock_t lock) +{ + bool_e ret = false_e; + FrameQueueNode_t *fNode = NULL; + + if( fr && qFrames ) + { + while( queue_length(qFrames) ) + { + queue_read(qFrames, false_e, fNode); + + if( fNode && fNode->frame && fNode->frame== fr ) + { + fNode->lock |= lock; + ret = true_e; + } + } + } + + return ret; +} + +bool_e VisionCamFrameManager::Unlock(VisionCamFrame*, OperationLock_t lock) +{ + bool_e ret = false_e; + FrameQueueNode_t *fNode = NULL; + if( fr && qFrames ) + { + while( queue_length(qFrames) ) + { + queue_read(qFrames, false_e, fNode); + + if( fNode && fNode->frame == fr ) + { + fNode->lock ^= lock; + ret = true_e; + } + } + } + return ret; +} + +void* VisionCamFrameManager::AllocBuffer() +{ + return NULL; +} + +bool_e VisionCamFrameManager::DeallocBuffer(void*) +{ + bool_e ret = false_e; + + return ret; +} diff --git a/source/dvp/VisionCam/VisionCamServer.cpp b/source/dvp/VisionCam/VisionCamServer.cpp new file mode 100644 index 0000000..19a20b9 --- /dev/null +++ b/source/dvp/VisionCam/VisionCamServer.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#if defined(LINUX) +#include +#endif +#include + +static ServerVisionCam *f_pSVCam; + +#if defined(LINUX) +static void signal_handler(int sig) +{ + signal(sig, NULL); + if (sig == SIGTERM || + sig == SIGINT) + f_pSVCam->SignalCompletion(); + signal(sig, signal_handler); +} +#endif + +int main(int argc, char *argv[]) +{ + VisionCam_e camType = VISIONCAM_OMX; + char ipaddr[MAX_PATH]; + strcpy(ipaddr, "127.0.0.1"); + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + +#if defined(DVP_RUNTIME_DEBUG) + debug_get_zone_mask("DVP_ZONE_MASK", &dvp_zone_mask); +#endif + +#if defined(LINUX) + signal(SIGTERM, signal_handler); + signal(SIGINT, signal_handler); +#endif + + if (argc > 1) + strncpy(ipaddr, argv[1], MAX_PATH); + if (argc > 2) + camType = (VisionCam_e)atoi(argv[2]); + + DVP_PRINT(DVP_ZONE_CAM, "Serving on %s VisionCam Type %u\n", ipaddr, camType); + f_pSVCam = ServerVisionCam::instantiate(ipaddr, camType); + if (f_pSVCam) + { + f_pSVCam->WaitForCompletion(); + delete f_pSVCam; + return 0; + } +#if defined(LINUX) + else + return ENAVAIL; +#else + else + return -1; +#endif +} diff --git a/source/dvp/VisionCam/VisionCamSimpleTest.cpp b/source/dvp/VisionCam/VisionCamSimpleTest.cpp new file mode 100644 index 0000000..919477a --- /dev/null +++ b/source/dvp/VisionCam/VisionCamSimpleTest.cpp @@ -0,0 +1,468 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief This is a simple, dumbed down version of the vcam_test which only uses + * command line paramters and simple settings in order to test out system + * connectivity, this is *not* intended to replace the more complicated + * VisionCamTest.cpp. + * \author Erik Rainey + */ + +#include +#include +#include +#include +#include +#include + +#define CAMERA_NAME MODULE_NAME("vcam") +int32_t width; +int32_t height; +int32_t allocWidth; +int32_t allocHeight; +int32_t fps; +uint32_t color; +char fourcc_str[5]; +int32_t type; +int32_t numImages; +int32_t recvFrames; +int32_t numFrames; +int32_t sensor; +int32_t frameLock; +int32_t focusDepth; +int32_t mode; +int32_t camera_rotation; +uint32_t screen_rotation; +uint32_t dw,sw; +uint32_t dh,sh; +int32_t subsample; +bool_e topBottom; +char filename[MAX_PATH]; +char name[MAX_PATH]; +uint32_t numTimeouts; +profiler_t capPerf; +uint32_t white; +uint32_t brightness; +uint32_t iso; +uint32_t exposure; +bool_e manual; +uint32_t repeats; +option_t opts[] = { + {OPTION_TYPE_INT, &width, sizeof(width), "-w", "--width", "Width of Image"}, + {OPTION_TYPE_INT, &height, sizeof(height), "-h", "--height", "Height of Image"}, + {OPTION_TYPE_INT, &dw, sizeof(dw), "-dw", "--dispwidth", "Width of Display"}, + {OPTION_TYPE_INT, &dh, sizeof(dh), "-dh", "--dispheight", "Height of Display"}, + {OPTION_TYPE_INT, &sw, sizeof(sw), "-sw", "--scaleWidth", "Scaled Width of Display"}, + {OPTION_TYPE_INT, &sh, sizeof(sh), "-sh", "--scaleHeight", "Scaled Height of Display"}, + {OPTION_TYPE_INT, &fps, sizeof(fps), "-f", "--fps", "Frame Rate"}, + {OPTION_TYPE_BOOL, &topBottom, sizeof(topBottom), "-tb", "--topbottom", "Orient the stereo image as top/bottom"}, + {OPTION_TYPE_STRING, &fourcc_str, sizeof(fourcc_str), "-c", "--fourcc", "FOURCC Code as string (UYVY) "}, + {OPTION_TYPE_INT, &type, sizeof(type), "-t", "--type", "Determines the type of GestureCam instantiated"}, + {OPTION_TYPE_STRING, name, sizeof(name), "-n", "--name", "Name of file to read"}, + {OPTION_TYPE_INT, &numImages, sizeof(numImages), "-i", "--images", "Number of images to use"}, + {OPTION_TYPE_INT, &numFrames, sizeof(numFrames), "-#", "--frames", "Number of frames to process"}, + {OPTION_TYPE_INT, &sensor, sizeof(sensor), "-s", "--sensor", "Selects the sensor (0,1,2)"}, + {OPTION_TYPE_INT, &frameLock, sizeof(frameLock), "-l", "--lock-after", "Locks AE/AWB after specified frame count"}, + {OPTION_TYPE_INT, &focusDepth, sizeof(focusDepth), "-fd", "--focus-depth", "Specific Focus Depth [0-150]"}, + {OPTION_TYPE_INT, &mode, sizeof(mode), "-p", "--mode", "Capture Mode"}, + {OPTION_TYPE_INT, &camera_rotation, sizeof(camera_rotation),"-cr", "--camera_rotation", "Rotates the captured image in the camera"}, + {OPTION_TYPE_INT, &screen_rotation, sizeof(screen_rotation),"-sr", "--screen_rotation", "Rotates the display image"}, + {OPTION_TYPE_INT, &subsample, sizeof(subsample), "-sb", "--subsample", "Subsampled ratio, defaults to 1"}, + {OPTION_TYPE_STRING, &filename, sizeof(filename), "-o", "--out", "File to write captured frames to"}, + {OPTION_TYPE_BOOL, &manual, sizeof(manual), "-m", "--manual", "Use manual settings"}, + {OPTION_TYPE_INT, &white, sizeof(white), "-wb", "--white", "White Balance Mode"}, + {OPTION_TYPE_INT, &brightness, sizeof(brightness), "-br", "--bright", "Brightness Value"}, + {OPTION_TYPE_INT, &iso, sizeof(iso), "-is", "--iso", "ISO Value"}, + {OPTION_TYPE_INT, &exposure, sizeof(exposure), "-ex", "--exposure", "Manual Exposure Value"}, + {OPTION_TYPE_INT, &numTimeouts, sizeof(numTimeouts), "-to", "--timeouts", "Set the number of frame timeout which can occur before the camera halts"}, + {OPTION_TYPE_INT, &repeats, sizeof(repeats), "-r", "--repeat", "Sets the number of repeat iterations, default is 1."}, +}; +void VisionCamTestCallback(VisionCamFrame * cameraFrame) +{ + DVP_Image_t *pImage = (DVP_Image_t *)cameraFrame->mFrameBuff; + queue_t *frameq = (queue_t *)cameraFrame->mCookie; + + DVP_PRINT(DVP_ZONE_CAM, "Frame has an offset of %ux%u\n", cameraFrame->mOffsetX, cameraFrame->mOffsetY); + profiler_stop(&capPerf); + DVP_PRINT(DVP_ZONE_PERF, "Last Capture for Frame %u took %lf sec Average: %lf\n", recvFrames, rtimer_to_sec(capPerf.tmpTime), rtimer_to_sec(capPerf.avgTime)); + profiler_start(&capPerf); + DVP_PRINT(DVP_ZONE_CAM, "Writing Frame %p into Queue %p\n", pImage, frameq); + DVP_PrintImage(DVP_ZONE_CAM, pImage); + if (queue_write(frameq, true_e, &cameraFrame) == false_e) + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to write frame to queue\n"); + } +} + +int main(int argc, char *argv[]) +{ + uint32_t r = 0; + int32_t i = 0; + VisionCamSensorSelection sensorIndex = VCAM_SENSOR_SECONDARY; + VisionCamCaptureMode capmode = VCAM_VIDEO_NORMAL; + VisionCamFlickerType flicker = FLICKER_60Hz; + VisionCamFocusMode focus = VCAM_FOCUS_CONTROL_AUTO; + VisionCamStereoInfo info; + VisionCamResType res; + ImageDebug_t imgdbg; + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + +#if defined(DVP_RUNTIME_DEBUG) + debug_get_zone_mask("DVP_ZONE_MASK", &dvp_zone_mask); +#endif + + // default values + white = VCAM_WHITE_BAL_CONTROL_AUTO; + brightness = 50; // [0-200] + iso = 100; // [100-1600] + exposure = 50; // [0-100] + manual = false_e; + recvFrames = 0; + width = 320; + height = 240; + fps = 30; + color = FOURCC_NV12; + strcpy(fourcc_str, "NV12"); + strcpy(name, "car"); + numImages = DVP_DISPLAY_NUM_BUFFERS; + sensor = 1; + numFrames = 100; + frameLock = 0xFFFFFFFF; + focusDepth = -1; + mode = VCAM_VIDEO_NORMAL; + camera_rotation = 0; + screen_rotation = 0; + dw = DVP_DISPLAY_WIDTH; + dh = DVP_DISPLAY_HEIGHT; + sw = 0; + sh = 0; + type = VISIONCAM_OMX; + topBottom = true_e; + subsample = 1; + memset(filename, 0, sizeof(filename)); + numTimeouts = 10; + repeats = 1; + + profiler_clear(&capPerf); + + option_process(argc, argv, opts, dimof(opts)); + + // check for bad input + if (width <= 0) width = 160; + if (height <= 0) height = 120; + if (dw <= 0) dw = DVP_DISPLAY_WIDTH; + if (dh <= 0) dh = DVP_DISPLAY_HEIGHT; + if (sw <= 0) sw = width; + if (sh <= 0) sh = height; + if (numImages <= 2) numImages = 2; + if (fps <= 15) fps = 15; + if (numFrames <= 100) numFrames = 100; + if (frameLock > numFrames) frameLock = -1; + if (focusDepth > 150) focusDepth = 75; + if (mode >= VCAM_CAP_MODE_MAX) mode = VCAM_GESTURE_MODE; + if (sensor > 2) sensor = 2; + if (camera_rotation != 0 && camera_rotation != 90 && camera_rotation != 180 && camera_rotation != 270) + camera_rotation = 0; + else if (camera_rotation == 90 || camera_rotation == 270) + { + uint32_t t = sw; + sw = sh; + sh = t; + } + if (type >= VISIONCAM_MAX || type < 0) + type = VISIONCAM_OMX; + if (subsample <= 0 || subsample > 4) + subsample = 1; + if (brightness > 200) + brightness = 200; + if (iso < 100) iso = 100; + if (iso > 1600) iso = 1600; + if (exposure > 100) exposure = 100; + if (repeats == 0) + repeats = 1; + + color = strtofourcc(fourcc_str); + + DVP_PRINT(DVP_ZONE_ALWAYS, "Requested Color %08x\n", color); + + DVP_PRINT(DVP_ZONE_ALWAYS, "Type %d requested!\n", type); + + // different types of cameras have different restrictions... + if (type == VISIONCAM_SOCKET) + { + // don't let the network latency kill the connection. + numTimeouts = 0xFFFFFFFF; + // if stereo mode, modify the variables + if (mode == VCAM_STEREO_MODE || sensorIndex == VCAM_SENSOR_STEREO) + { + DVP_PRINT(DVP_ZONE_ALWAYS, "Enabling Stereo Use Case!\n"); + sensorIndex = VCAM_SENSOR_STEREO; + mode = VCAM_STEREO_MODE; + memset(&info, 0, sizeof(info)); + if (topBottom) + info.layout = VCAM_STEREO_LAYOUT_TOPBOTTOM; + else + info.layout = VCAM_STEREO_LAYOUT_LEFTRIGHT; + info.subsampling = subsample; + color = FOURCC_NV12; // only NV12 is supported during stereo capture. + } + } + else if (type == VISIONCAM_USB) + { + // USB may take a few hundred ms to initialize, don't let it exit early + if (numTimeouts < 100) + numTimeouts = 100; + } + else if (type == VISIONCAM_OMX) // this only really applies to local OMX cameras, remote cameras or USB will not mess with this. + { + switch (sensor) + { +#ifndef SDP + case 2: + DVP_PRINT(DVP_ZONE_ALWAYS, "Enabling Stereo Use Case!\n"); + sensorIndex = VCAM_SENSOR_STEREO; + mode = VCAM_STEREO_MODE; + memset(&info, 0, sizeof(info)); + if (topBottom) + info.layout = VCAM_STEREO_LAYOUT_TOPBOTTOM; + else + info.layout = VCAM_STEREO_LAYOUT_LEFTRIGHT; + info.subsampling = subsample; + color = FOURCC_NV12; // only NV12 is supported during stereo capture. + break; + case 1: + DVP_PRINT(DVP_ZONE_ALWAYS, "Enabling Vision Mode on Front Camera!\n"); +#ifdef PLAYBOOK + sensorIndex = VCAM_SENSOR_PRIMARY; +#else + sensorIndex = VCAM_SENSOR_SECONDARY; +#endif +#if defined(DUCATI_1_5) || defined(DUCATI_2_0) + mode = VCAM_GESTURE_MODE; +#else +# if defined(__QNX__) + mode = VCAM_VIEWFINDER_MODE; +# else + mode = VCAM_VIDEO_NORMAL; +# endif +#endif + break; + case 0: +#endif + default: sensorIndex = VCAM_SENSOR_PRIMARY; break; + } + } + capmode = (VisionCamCaptureMode)mode; + allocWidth = width; + allocHeight = height; + + // using 1 to <= so prints will make sense + for (r = 1; r <= repeats; r++) + { + DVP_PRINT(DVP_ZONE_ALWAYS, "Iteration %u of %u\n", r, repeats); + recvFrames = 0; +#ifdef VCAM_AS_SHARED + module_t mod = module_load(CAMERA_NAME); + if (mod) + { + VisionCamFactory_f factory = (VisionCamFactory_f)module_symbol(mod, "VisionCamFactory"); + if (factory) + { + VisionCam *pCam = factory((VisionCam_e)type); + if (pCam) + { +#else + VisionCam *pCam = VisionCamFactory((VisionCam_e)type); + if (pCam) + { +#endif + queue_t *frameq = queue_create(numImages * VCAM_PORT_MAX, sizeof(VisionCamFrame *)); + DVP_Image_t *images = (DVP_Image_t *)calloc(numImages, sizeof(DVP_Image_t)); + + if (images) + { + VisionCamFrame *cameraFrame = NULL; + DVP_Image_t *pImage = NULL; + status_e greError = STATUS_SUCCESS; +#if defined(VCAM_SUPPORTS_SOCKETCAM) + // set the hostname before we connect. + if (type == VISIONCAM_SOCKET) + pCam->setParameter((VisionCamParam_e)SOCKETVCAM_PARAM_HOSTNAME, name, sizeof(name)); +#endif + VCAM_RETURN_IF_FAILED(greError, pCam->init(frameq)); + VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_WIDTH, &width, sizeof(width))); + VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_HEIGHT, &height, sizeof(height))); + VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_COLOR_SPACE_FOURCC, &color, sizeof(color))); + // Can't set ROTATION here, see below + VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_FPS_FIXED, &fps, sizeof(fps))); + VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_CAP_MODE, &capmode, sizeof(capmode))); + VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_SENSOR_SELECT, &sensorIndex, sizeof(sensorIndex))); + if (capmode == VCAM_STEREO_MODE) + { + VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_STEREO_INFO, &info, sizeof(info))); + } + + memset(&res, 0, sizeof(res)); + // VCAM_PARAM_2DBUFFER_DIM should only be called after resolutions, color space, cap mode, and + // optionally stereo information is set. + VCAM_COMPLAIN_IF_FAILED(greError, pCam->getParameter(VCAM_PARAM_2DBUFFER_DIM, &res, sizeof(res))); + // if the camera requires a bigger buffer than the requrested resolution ... + if (res.mHeight != (uint32_t)height || res.mWidth != (uint32_t)width) + { + allocWidth = res.mWidth; + allocHeight = res.mHeight; + } + + dvp_display_t *dvpd = DVP_Display_Create(width, height, allocWidth, allocHeight, dw, dh, allocWidth, allocHeight, 0, 0, color, screen_rotation, numImages); + if(dvpd) + { + VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_FLICKER, &flicker, sizeof(flicker))); + VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_AWB_MODE, &white, sizeof(white))); + if (manual) + { + VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_BRIGHTNESS, &brightness, sizeof(brightness))); + VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_EXPOSURE_ISO, &iso, sizeof(iso))); + VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_MANUAL_EXPOSURE, &exposure, sizeof(exposure))); + } + VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_NAME, name, sizeof(name))); + + for (i = 0; i < numImages; i++) + { + DVP_Image_Init(&images[i], allocWidth, allocHeight, color); + // The image dimentions may be smaller than the buffer dimentions + images[i].width = width; + images[i].height = height; + DVP_Display_Alloc(dvpd, &images[i]); + } + // tell the camera to use all the camera index buffers + VCAM_COMPLAIN_IF_FAILED(greError, pCam->useBuffers(images, numImages)); + + /** @todo Since the OMX Camera is probably being used by + the VCAM_SIMPLE test, we have to understand that + the OMX-CAMERA has a bug in the camera_rotation when used + during LOADED state. We have to wait until IDLE + (post useBuffers) or EXECUTING (post PREVIEW) + before rotating. */ + /** @todo Additionally, OMX-CAMERA STEREO mode can't handle the rotation values! */ + if (capmode != VCAM_STEREO_MODE) + VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_ROTATION, &camera_rotation, sizeof(camera_rotation))); + + // register the engine callback with the camera + VCAM_COMPLAIN_IF_FAILED(greError, pCam->enablePreviewCbk(VisionCamTestCallback)); + profiler_start(&capPerf); + VCAM_COMPLAIN_IF_FAILED(greError, pCam->sendCommand(VCAM_CMD_PREVIEW_START)); + + if (focusDepth == -1) { // begin auto-focus + VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_DO_AUTOFOCUS, &focus, sizeof(focus))); + } + + if (filename[0] != '\0') { + DVP_Image_t local; + local = images[0]; + ImageDebug_Init(&imgdbg, &local, "raw"PATH_DELIM, filename); + ImageDebug_Open(&imgdbg, 1); + } + + thread_msleep(1000/fps); // wait 1 frame period. + if (greError == STATUS_SUCCESS) + { + uint32_t timeouts = 0; + DVP_PRINT(DVP_ZONE_CAM, "VisionCam is initialized, entering queue read loop!\n"); + // read from the queue and display the images + do { + bool_e ret = queue_read(frameq, false_e, &cameraFrame); + if (ret == true_e && cameraFrame != NULL) + { + pImage = (DVP_Image_t *)cameraFrame->mFrameBuff; + timeouts = 0; + DVP_Display_Render(dvpd, pImage); + if (filename[0] != '\0') { + DVP_Image_t copy = *pImage; + imgdbg.pImg = © + ImageDebug_Write(&imgdbg, 1); + } + pCam->returnFrame(cameraFrame); + recvFrames++; + if (recvFrames > numFrames) + break; + if (focusDepth >= 0) { + if (recvFrames == fps) { // after 1 second + VCAM_COMPLAIN_IF_FAILED(greError, pCam->setParameter(VCAM_PARAM_DO_MANUALFOCUS, &focusDepth, sizeof(focusDepth))); + } + } + if (frameLock > 0) { + if (recvFrames == frameLock) { + bool_e lock = true_e; + VCAM_COMPLAIN_IF_FAILED(greError, pCam->sendCommand(VCAM_CMD_LOCK_AE, &lock, sizeof(lock))); + VCAM_COMPLAIN_IF_FAILED(greError, pCam->sendCommand(VCAM_CMD_LOCK_AWB, &lock, sizeof(lock))); + } + } + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Timedout waiting for buffer from Camera!\n"); + timeouts++; + thread_msleep(1000/fps); + } + } while (timeouts < numTimeouts); + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "VCAM_TEST Failed during initialization (greError = %d, 0x%08x)!\n", greError, greError); + } + + if (filename[0] != '\0') + ImageDebug_Close(&imgdbg, 1); + + // destroy the camera + VCAM_COMPLAIN_IF_FAILED(greError, pCam->sendCommand(VCAM_CMD_PREVIEW_STOP)); + VCAM_COMPLAIN_IF_FAILED(greError, pCam->disablePreviewCbk(VisionCamTestCallback)); + VCAM_COMPLAIN_IF_FAILED(greError, pCam->releaseBuffers()); + VCAM_COMPLAIN_IF_FAILED(greError, pCam->deinit()); + + // free the images + for (i = 0; i < numImages; i++) + DVP_Display_Free(dvpd, &images[i]); + + DVP_Display_Destroy(&dvpd); + } + free(images); + } + + delete pCam; + pCam = NULL; + + queue_destroy(frameq); + frameq = NULL; +#ifdef VCAM_AS_SHARED + } + } + module_unload(mod); + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Could not find %s\n", CAMERA_NAME); + } +#else + } +#endif +} + return 0; +} diff --git a/source/dvp/VisionCam/VisionCamTest.cpp b/source/dvp/VisionCam/VisionCamTest.cpp new file mode 100644 index 0000000..edfd946 --- /dev/null +++ b/source/dvp/VisionCam/VisionCamTest.cpp @@ -0,0 +1,1486 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "VisionCamTestData.h" + +#if defined(WIN32) || defined(UNDER_CE) + #include +#else + #include + #include + #include + #include + #include + #include + #include + #include +#endif + +#include +#include + +#define here {printf("\n======> %s <======> %d <======\n", __FILE__, __LINE__);fflush(stdout);} + +// #define EXTRA_DATA_CTL_BYTE 15 +// #define EXTRA_DATA_CTL_FLAG 0x7F +#define EXTRA_DATA_FILE_LENGHT 12332 + +#define MODULE_TO_LOAD MODULE_NAME("vcam") +#define SYMBOL_TO_LOAD "VisionCamFactory" +#define VIDEO_DEVICE "/dev/video1" +#include + +const int32_t max_video_port_resolution = VCAM_RES_VGA; +static DVP_Image_t *dvpBuffsDisp = NULL, *dvpBuffsImg = NULL; + +#if !defined(ICS) && !defined(JELLYBEAN) +static DVP_Handle hDVP = 0; +#endif + +/// Display stuff +static dvp_display_t *dvpd[VCAM_PORT_MAX] = { NULL }; +static queue_t *frameQ[VCAM_PORT_MAX] = { NULL }; +//thread_ret_t retFrameThread( void *arg ); + +int main() +{ + VisionCam * gCam = NULL; + entryIndex index = 0; + module_t handle = NULL; + status_e ret = STATUS_SUCCESS; + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + +#if defined(DVP_RUNTIME_DEBUG) + debug_get_zone_mask("DVP_ZONE_MASK", &dvp_zone_mask); +#endif + + handle = initModule( &gCam ); +#ifdef VCAM_AS_SHARED + if( handle == NULL ) + return -1; +#endif + + if( gCam ) + { + setInitialValues( gCam ); + ret = startServices( gCam ); + } + else + { + ret = STATUS_CATASTROPHIC; + } + + if( ret != STATUS_SUCCESS ) + { + ret = deinitModule( handle, &gCam ); + } + else + { + while( 1 ) + { + index = Menu( menu ); + if( index == -1 ) + { + continue; + } + + /// 'q' button (quit) is pressed + if( menu[ index ]->ID == VCAM_CMD_QUIT ) + { + index = getEntryIndex( menu , KEY_PREVIEW_STOP ); + ret = executeEntry( menu[ index ], gCam ); + break; + } + ret = executeEntry( menu[ index ] , gCam ); + } + ret = stopServices( gCam ); + ret = deinitModule( handle, &gCam ); + } + + printf("\tvcam_test exiting with %d.\n", ret); + + if( STATUS_SUCCESS != ret ) + puts("\tTerminating application."); + + return ret; +} + +#ifdef CAP_FRAME +void capFrame(void *input __attribute__ ((unused))) +{ + recNextFrame = !recNextFrame; + + if( recNextFrame ) + puts("Very next frame will be recorded."); +} +#endif // CAP_FRAME + +status_e allocPreviewPortBuffers(VisionCam *vCam, uint32_t width, uint32_t height) +{ + status_e ret = STATUS_SUCCESS; + + VisionCamResType res; + res.mHeight = VisionCamResolutions[prevResIdx].mHeight; + res.mWidth = VisionCamResolutions[prevResIdx].mWidth; + res.mResIdx = (VisionCamResolIdex)prevResIdx; + + vCam->getParameter(VCAM_PARAM_2DBUFFER_DIM, &res, sizeof(res), VCAM_PORT_PREVIEW); + + if( !dvpd[VCAM_PORT_PREVIEW] ) + { + dvpd[VCAM_PORT_PREVIEW] = DVP_Display_Create(width, height, + res.mWidth, res.mHeight, + DVP_DISPLAY_WIDTH, DVP_DISPLAY_HEIGHT, + res.mWidth, res.mHeight, + 0 , 0, + colorSpacePeview, 0, NUM_BUFFERS); + } + + if (dvpd[VCAM_PORT_PREVIEW]) + { + dvpBuffsDisp = (DVP_Image_t *)calloc(NUM_BUFFERS, sizeof(DVP_Image_t)); + + for ( int i = 0; i < NUM_BUFFERS; i++) + { + DVP_Image_Init( &dvpBuffsDisp[i], res.mWidth, res.mHeight, colorSpacePeview ); + + if( !DVP_Display_Alloc(dvpd[VCAM_PORT_PREVIEW], &dvpBuffsDisp[i]) ) + { + printf("Error allocating preview port buffers.\n"); + deallocDislayBufers(); + ret = STATUS_NOT_ENOUGH_MEMORY; + break; + } + } + } + else + { + printf("Error creating display. No buffers were allocated.\n"); + ret = STATUS_FAILURE; + } + + if( STATUS_SUCCESS == ret ) + frameQ[VCAM_PORT_PREVIEW] = queue_create(NUM_BUFFERS, sizeof(DVP_Image_t *)); + + return ret; +} + +void deallocDislayBufers() +{ + if( dvpBuffsDisp ) + { + for (int i = 0; i < NUM_BUFFERS; i++) + { + DVP_Display_Free(dvpd[VCAM_PORT_PREVIEW], &dvpBuffsDisp[i]); + DVP_Image_Deinit(&dvpBuffsDisp[i]); + } + + free( dvpBuffsDisp ); + dvpBuffsDisp = NULL; + } + + if( dvpd[VCAM_PORT_PREVIEW] ) + { + DVP_Display_Destroy(&dvpd[VCAM_PORT_PREVIEW]); + dvpd[VCAM_PORT_PREVIEW] = 0; + } + + if( frameQ[VCAM_PORT_PREVIEW] ) + { + queue_destroy(frameQ[VCAM_PORT_PREVIEW]); + frameQ[VCAM_PORT_PREVIEW] = NULL; + } +} +#if defined(ICS) || defined(JELLYBEAN) +status_e allocVideoPortBuffers(VisionCam *vCam, uint32_t width, uint32_t height) +{ + status_e ret = STATUS_SUCCESS; + + VisionCamResType res; + if( VisionCamResolutions[max_video_port_resolution].mHeight < height + || VisionCamResolutions[max_video_port_resolution].mWidth < width) + { + res.mHeight = VisionCamResolutions[max_video_port_resolution].mHeight; + res.mWidth = VisionCamResolutions[max_video_port_resolution].mWidth; + res.mResIdx = (VisionCamResolIdex)max_video_port_resolution; + } + else + { + res.mHeight = height; + res.mWidth = width; + res.mResIdx = (VisionCamResolIdex)prevResIdx; + } + + vCam->getParameter(VCAM_PARAM_2DBUFFER_DIM, &res, sizeof(res), VCAM_PORT_VIDEO); + + if( !dvpd[VCAM_PORT_VIDEO] ) + { + dvpd[VCAM_PORT_VIDEO] = DVP_Display_Create(width, height, + res.mWidth, res.mHeight, + DVP_DISPLAY_WIDTH, DVP_DISPLAY_HEIGHT, + res.mWidth, res.mHeight, + 0 , 0, + colorSpaceVideo, 0, NUM_BUFFERS); + } + + if( dvpd[VCAM_PORT_VIDEO] ) + { + dvpBuffsImg = (DVP_Image_t *)calloc(NUM_BUFFERS, sizeof(DVP_Image_t)); + + for ( int i = 0; i < NUM_BUFFERS; i++) + { + DVP_Image_Init( &dvpBuffsImg[i], res.mWidth, res.mHeight, colorSpaceVideo ); + + if( !DVP_Display_Alloc(dvpd[VCAM_PORT_VIDEO], &dvpBuffsImg[i]) ) + { + printf("Error allocating video display buffers.\n"); + deallocImageBufers(); + ret = STATUS_NOT_ENOUGH_MEMORY; + break; + } + } + } + else + { + printf("Error creating display. No buffers were allocated.\n"); + ret = STATUS_FAILURE; + } + + if( STATUS_SUCCESS == ret ) + frameQ[VCAM_PORT_VIDEO] = queue_create(NUM_BUFFERS, sizeof(DVP_Image_t *)); + + return ret; +} + +void deallocImageBufers() +{ + if( dvpBuffsImg ) + { + for (int i = 0; i < NUM_BUFFERS; i++) + { + + if( DVP_Display_Free( dvpd[VCAM_PORT_VIDEO], &dvpBuffsImg[i]) ) + { + DVP_Image_Deinit(&dvpBuffsImg[i]); + } + } + + free( dvpBuffsImg ); + dvpBuffsImg = NULL; + } + + if( dvpd[VCAM_PORT_VIDEO] ) + { + DVP_Display_Destroy(&dvpd[VCAM_PORT_VIDEO]); + dvpd[VCAM_PORT_VIDEO] = 0; + } + + if( frameQ[VCAM_PORT_PREVIEW] ) + { + queue_destroy(frameQ[VCAM_PORT_VIDEO]); + frameQ[VCAM_PORT_VIDEO] = NULL; + } +} +#else +status_e allocVideoPortBuffers(VisionCam *vCam, uint32_t width, uint32_t height) +{ + status_e ret = STATUS_SUCCESS; + + hDVP = DVP_KernelGraph_Init(); + + if ( hDVP ) + { + dvpBuffsImg = (DVP_Image_t *)calloc(NUM_BUFFERS, sizeof(DVP_Image_t)); + for ( int i = 0; i < NUM_BUFFERS; i++) + { + DVP_Image_Init( &dvpBuffsImg[i], + width, + height, + colorSpaceVideo); + + if( !DVP_Image_Alloc( hDVP, &dvpBuffsImg[i], DVP_MTYPE_MPUNONCACHED_2DTILED ) ) + { + printf("Error allocating image buffers.\n"); + deallocImageBufers(); + + ret = STATUS_NOT_ENOUGH_MEMORY; + break; + } + printf("vid biffs: w x h ; %d x %d\n", dvpBuffsImg[0].height, dvpBuffsImg[0].width); + } + } + else + { + printf("Error getting DVP handle No buffers were allocated.\n"); + ret = STATUS_FAILURE; + } + + if( STATUS_SUCCESS == ret ) + frameqImg = queue_create( NUM_BUFFERS, sizeof(DVP_Image_t *) ); + + return ret; +} + +void deallocImageBufers() +{ + if( dvpBuffsImg ) + { + for (int i = 0; i < NUM_BUFFERS; i++) + { + DVP_Image_Free( hDVP, &dvpBuffsImg[i]); + DVP_Image_Deinit(&dvpBuffsImg[i]); + } + + free( dvpBuffsImg ); + dvpBuffsImg = NULL; + } + + if( hDVP ) + { + DVP_KernelGraph_Deinit(hDVP); + hDVP = 0; + } + + if( frameqImg ) + { + queue_destroy(frameqImg); + frameqImg = NULL; + } +} + +#endif // ICS + +status_e startServices( VisionCam * vCam ) +{ + status_e ret = STATUS_SUCCESS; + + if( vCam != NULL) + { + VisionCamResType resPreview, resVideo; + + resPreview.mHeight = VisionCamResolutions[prevResIdx].mHeight; + resPreview.mWidth = VisionCamResolutions[prevResIdx].mWidth; + resPreview.mResIdx = (VisionCamResolIdex)prevResIdx; + + // Check required resolution and change the video port resolution to its maxumum, in case it is higher + if( VisionCamResolutions[prevResIdx].mHeight > VisionCamResolutions[VCAM_RES_VGA].mHeight || + VisionCamResolutions[prevResIdx].mWidth > VisionCamResolutions[VCAM_RES_VGA].mWidth ) + { + resVideo.mHeight = VisionCamResolutions[VCAM_RES_VGA].mHeight; + resVideo.mWidth = VisionCamResolutions[VCAM_RES_VGA].mWidth; + resVideo.mResIdx = VCAM_RES_VGA; + } + else + { + resVideo.mHeight = VisionCamResolutions[prevResIdx].mHeight; + resVideo.mWidth = VisionCamResolutions[prevResIdx].mWidth; + resVideo.mResIdx = (VisionCamResolIdex)prevResIdx; + } + // allocate and register Preview Port buffers + + if( !dvpBuffsDisp && ret == STATUS_SUCCESS ) + { + ret = allocPreviewPortBuffers( vCam, resPreview.mWidth, resPreview.mHeight); + if(ret == STATUS_SUCCESS ) + ret = vCam->useBuffers( dvpBuffsDisp, NUM_BUFFERS, VCAM_PORT_PREVIEW); + else + printf("allocPreviewPortBuffers() returned %d (ox%x)\n", ret, ret); + } + + // allocate and register Video Port buffers + if( !dvpBuffsImg && ret == STATUS_SUCCESS ) + { + ret = allocVideoPortBuffers( vCam, resVideo.mWidth, resVideo.mHeight ); + if( ret == STATUS_SUCCESS ) + ret = vCam->useBuffers( dvpBuffsImg, NUM_BUFFERS, VCAM_PORT_VIDEO ); + else + printf("allocVideoPortBuffers() returned %d (ox%x)\n", ret, ret); + } + + if( ret == STATUS_SUCCESS ) + { + bool_e use = ( usePackaging ? true_e : false_e); + ret = vCam->sendCommand(VCAM_CMD_PACK_FRAMES, &use, sizeof(bool_e), VCAM_PORT_ALL); + } + + if( ret == STATUS_SUCCESS ) + ret = vCam->enablePackedFramesCbk(receiveFramePackage); + + if( ret == STATUS_SUCCESS ) + ret = vCam->enablePreviewCbk( sendBufferTo_V4L ); + + // enable all notifications + if( ret == STATUS_SUCCESS ) + ret = vCam->sendCommand(VCAM_CMD_SET_CLIENT_NOTIFICATION_CALLBACK, (void*)notificationHandler ); + } + else + ret = STATUS_FAILURE; + + return ret; +} + +status_e stopServices( VisionCam * vCam ) +{ + status_e result = STATUS_SUCCESS; + result = vCam->releaseBuffers(VCAM_PORT_ALL); + + if( dvpBuffsDisp ) + { + deallocDislayBufers(); + } + + if( dvpBuffsImg ) + deallocImageBufers(); + + if( STATUS_SUCCESS == result ) + result = vCam->disablePreviewCbk(sendBufferTo_V4L); + + if( STATUS_SUCCESS == result ) + result = vCam->disablePackedFramesCbk(receiveFramePackage); + + if( STATUS_SUCCESS == result ) /// disable all notifications + result = vCam->sendCommand(VCAM_CMD_SET_CLIENT_NOTIFICATION_CALLBACK, NULL ); + + return result; +} + +void *notificationHandler( VisionCamClientNotifier::VisionCamClientNotificationMsg msg ) +{ + void *ret = NULL; + + switch( msg ) + { + case VisionCamClientNotifier::VCAM_MESSAGE_ALLOCATE_V4L2_BUFFERS: + { + break; + } + case VisionCamClientNotifier::VCAM_MESSAGE_PREEMPT_SUSPEND_ACTIVITY: + { + break; + } + + case VisionCamClientNotifier::VCAM_MESSAGE_PREEMPT_RESUME_ACTIVITY: + { + break; + } + + case VisionCamClientNotifier::VCAM_MESSAGE_PREEMPT_WAIT_RESOURCES: + { + break; + } + + case VisionCamClientNotifier::VCAM_MESSAGE_PREAMPT_RESOURCES_READY: + { + break; + } + + case VisionCamClientNotifier::VCAM_MESSAGE_MAX: + case VisionCamClientNotifier::VCAM_MESSAGE_EMPTY: + { + break; + } + case VisionCamClientNotifier::VCAM_MESSAGE_STOP_STREAMING: + { + break; + } + + default: + { + ret = NULL; + break; + } + } + + return ret; +} + +#ifdef VCAM_AS_SHARED +module_t initModule(VisionCam ** gCam ) +{ + module_t handle; + VisionCamFactory_f factory; + + handle = module_load( (char*)MODULE_TO_LOAD ); + + if (handle != NULL) + { + module_error(); + factory = (VisionCamFactory_f)module_symbol( handle, (char*)SYMBOL_TO_LOAD ); + + *gCam = factory(); + + if (gCam == NULL) + { + printf("Error getting handle to Vision Camera.\n"); + handle = NULL; + } + else + { + (*gCam)->init(frameq); + + } + } + else + { + printf("error while opening gesture cam library.\n"); + handle = NULL; + } + return handle; +} + +status_e deinitModule( module_t handle, VisionCam ** gCam) +{ + status_e ret = STATUS_SUCCESS; + + if( gCam != NULL ) + { + ret = (*gCam)->deinit(); + } + + if( ret == STATUS_SUCCESS ) + { + delete (*gCam); + } + else + { + printf("gesture cam not deinitialized !!!\n"); + } + + if( handle ) + { + module_unload( handle ); + } + + return ret; +} +#else +module_t initModule(VisionCam ** gCam ) +{ + VisionCam *pCam = NULL; + status_e initErr = STATUS_SUCCESS; + *gCam = NULL; + pCam = VisionCamFactory(VISIONCAM_OMX); + if (pCam) + { + initErr = pCam->init(frameQ[VCAM_PORT_PREVIEW]); + + if( initErr != STATUS_SUCCESS ) + *gCam = NULL; + else + *gCam = pCam; + } + return NULL; +} +status_e deinitModule(module_t handle __attribute__ ((unused)) , + VisionCam * * gCam) +{ + if (*gCam) + { + (*gCam)->deinit(); + delete *gCam; + *gCam = NULL; + } + return STATUS_SUCCESS; +} +#endif + +status_e executeEntry( const menuEnrty *choice, VisionCam * gCam ) +{ + status_e result = STATUS_SUCCESS; + switch( choice->type ) + { + case commandEntry: + { + int val = 0; + printf("Command: \"%s\" ( ID = %d )\n", choice->itemDescriptor, choice->ID); + val = getValue( choice ); + result = gCam->sendCommand( (VisionCamCmd_e)choice->ID, (void *)&val, sizeof(int) , currentPort); + break; + } + case paramEntry_set: + { + int val = getValue( choice ); + result = gCam->setParameter( (VisionCamParam_e)choice->ID, (void *)&val, sizeof(int) , currentPort); + break; + } + case paramEntry_get: + { + int32_t index = 0; + int32_t paramVal = (uint32_t)(-1); + int32_t paramID = getValue( choice ); + + result = gCam->getParameter( (VisionCamParam_e)paramID, (void *)¶mVal, sizeof(int32_t) , currentPort); + + if( STATUS_SUCCESS == result ) + { + while( ((subMenuEnrty*)choice->subMenu)->keyValue[index] != paramID ) + index++; + + if( index <= choice->defVal.max ) + printf("\n%s is set to %d (0x%x) on preview port\n", ((subMenuEnrty*)choice->subMenu)->optString[index], paramVal, paramVal); + } + else + printf("Couldn't get this param."); + + break; + } + case functionalEntry: + { + subMenuFn executor = (subMenuFn)(choice->subMenu); + if( executor ) + executor( gCam ); + else + { + printf("VisionCamTest error: NULL function pointer passed.\n"); + printf("Request cancelled.\n"); + } + break; + } + case neutralEntry: + { + getValue( choice ); + break; + } + default: + { + printf("executeEntry: wrong param %d", choice->type ); + result = STATUS_INVALID_PARAMETER; + break; + } + } + + return result; +} + +void setInitialValues( VisionCam * gCam ) +{ + int index = 0; + bool_e setManualInitValues = false_e; + + if( setManualInitValues ) + printf("Please set first these values.\n"); + + while( setManualInitValues ) + { + index = Menu( menu_Primary ); + + if( index < 0 ) + continue; + + /// 'q' button (quit) is pressed + if( menu_Primary[ index ]->ID == VCAM_CMD_QUIT ) + break; + + executeEntry( menu_Primary[ index ] , gCam ); + } + + for ( int i = 0 ; menu_Primary[i]->ID != VCAM_CMD_QUIT ; i++ ) + { + if( menu_Primary[i]->ID < VCAM_PARAM_MAX && menu_Primary[i]->ID > VCAM_PARAM_MIN ) + gCam->setParameter((VisionCamParam_e)menu_Primary[i]->ID, + menu_Primary[i]->localValue, + sizeof(int), + currentPort + ); + } + +} + +entryIndex Menu( const menuEnrty ** menu ) +{ + entryIndex index = 0; + char choice [64]; + + printf("\n\n"); + printf("\t###========================================================###\n"); + printf("\t# Vision Camera Test Menu #\n"); + printf("\t###========================================================###\n"); + printf("\n\n"); + /// print the main menu + while( menu[ index ] != NULL ) + { + printf("\t\t%-2s. %s\n", menu[ index ]->menuKey, menu[ index ]->itemDescriptor); + index++; + } + + scanf( "%s", choice ); + printf("\nChoosen: %s\n", choice ); + + index = getEntryIndex( menu , (entryKey)choice ); + + if( index == -1 ) + printf("Incorrect Input: %s", choice ); + + return index; +} + +entryIndex getEntryIndex( const menuEnrty ** menu , entryKey desc ) +{ + /// get the index of item choosen + entryIndex index = 0; + while( menu[ index ] != NULL ) + { + if( strcmp( ( entryKey )desc, menu[ index ]->menuKey ) == 0 ) + { + break; + } + index++; + } + + if ( menu[ index ] == NULL ) + index = -1; + + return index; +} + +bool checkValue( const definitionValues * defVal, int value) +{ + bool isExeption = false; + + if( defVal->exeptions ) + for( int i = 0; i < defVal->exeptions->numValues && isExeption == false; i++) + isExeption = ( defVal->exeptions->values[i] == value ); + + return (value >= defVal->min && value <= defVal->max) || isExeption; +} + +int getValue( const menuEnrty *choice ) +{ + int value; + bool isCorrect = false; + + if( choice->subMenu ) + { + for( int i = 0; i <= choice->defVal.max - choice->defVal.min; i++ ) + printf("%d.\t%s\n", i , (( subMenuEnrty* )(choice->subMenu))->optString[ i ] ); + } + else + { + if (choice->defVal.min == choice->defVal.max) + return choice->defVal.min; + + printf("%s\n", choice->itemDescriptor ); + printf("enter a numer between %d and %d\n", choice->defVal.min, choice->defVal.max ); + } + + for(;;) + { + fflush(stdin); + scanf( "%d", &value ); + + isCorrect = checkValue( &choice->defVal , value ); + + if( isCorrect ) + { + if( choice->subMenu ) + value = (( subMenuEnrty* )(choice->subMenu))->keyValue[ value ]; + + if( choice->localValue ) + memcpy( choice->localValue, &value, sizeof(value) ); + break; + } + + printf("incorrect input"); + printf("possible values are in the range of: %d and %d\n", choice->defVal.min, choice->defVal.max); + } + + printf("value = %d (0x%x)\n", value, value); + + return value; +} + +void setCropParams( void * input ) +{ + char descr[32]; + + menuEnrty crop = { + 0, + neutralEntry, + VCAM_PARAM_CROP, + descr, + { 0 , 0, NULL }, + NULL, + NULL + }; + + descr[0] = 0; + + crop.defVal.min = 0; + crop.defVal.max = VisionCamResolutions[prevResIdx].mWidth; + crop.itemDescriptor = "\nset crop left offset:"; + cropParams.mLeft = getValue( &crop ); + + crop.defVal.min = 0; + crop.defVal.max = VisionCamResolutions[prevResIdx].mHeight; + crop.itemDescriptor = "\nset crop top offset: "; + cropParams.mTop = getValue( &crop ); + + crop.defVal.min = 10; /// @todo define proper value + crop.defVal.max = VisionCamResolutions[prevResIdx].mWidth - cropParams.mLeft; + crop.itemDescriptor = "\nset crop width: "; + cropParams.mWidth = getValue( &crop ); + + crop.defVal.min = 10; /// @todo define proper value + crop.defVal.max = VisionCamResolutions[prevResIdx].mHeight - cropParams.mTop; + crop.itemDescriptor = "\nset crop height: "; + cropParams.mHeight = getValue( &crop ); + + ((VisionCam*)input)->setParameter( (VisionCamParam_e)crop.ID, (void *)&cropParams, sizeof(VisionCamRectType) ); +} + +void setVariableFrameRate( void * input ) +{ + menuEnrty minFrate, maxFrate; + + minFrate.itemDescriptor = "min frame rate"; + minFrate.defVal.min = 0; + minFrate.defVal.max = 30; + minFrate.defVal.exeptions = NULL; + minFrate.type = paramEntry_set; + minFrate.localValue = NULL;///varFrate.mMin; + minFrate.subMenu = NULL; + + maxFrate.itemDescriptor = "max frame rate"; + maxFrate.defVal.min = 1; + maxFrate.defVal.max = 30; + maxFrate.defVal.exeptions = NULL; + maxFrate.type = paramEntry_set; + maxFrate.localValue = NULL;///varFrate.mMax; + maxFrate.subMenu = NULL; + + varFrate.mMin = getValue( &minFrate ); + varFrate.mMax = getValue( &maxFrate ); + + ((VisionCam*)input)->setParameter( (VisionCamParam_e)frameRate_variable.ID , + (void *)&varFrate , + sizeof( VisionCamVarFramerateType ) + ); +} + +uint32_t getQ16Value(const char * itemDescriptor, uint16_t min, uint16_t max) +{ + uint32_t retVal = 0; + uint32_t test_value; + int i, cnt_f, cnt_i, frac; + bool isValid; + char in[64]; + char subin_frac[64]; + char subin_int[64]; + + if(min >= max) { + printf("ERROR: min: %d max: %d\n", min, max); + return 0; + } + + isValid = false; + for(; !isValid;) { + printf("%s [%d, %d]:\n", itemDescriptor, min, max); + fflush(stdin); + scanf( "%s", in ); + + i = 0; + frac = 0; + cnt_f = 0; + cnt_i = 0; + isValid = true; + while(in[i] != '\0') + { + if(in[i] == '.') { + i++; + frac++; + continue; + } + + if(in[i] < '0' || in[i] > '9') { + isValid = false; + break; + } + + if(frac == 0) { + subin_int[cnt_i++] = in[i]; + } else if(frac == 1) { + subin_frac[cnt_f++] = in[i]; + } else { + isValid = false; + break; + } + + i++; + } + + subin_int[cnt_i] = '\0'; + subin_frac[cnt_f] = '\0'; + + if((cnt_i == 0) || (isValid == false)) { + isValid = false; + continue; + } + + test_value = atoi(subin_int); + retVal = test_value << 16; + if(cnt_f) { + int dev; + for(dev = 1, i = 0; i < cnt_f; i++) { + dev *= 10; + } + retVal |= (atoi(subin_frac) * (uint32_t)0xFFFF) / dev; + if(atoi(subin_frac)) { + test_value++; + } + } + + if(test_value < min || test_value > max) { + printf("Value %s.%s is not in range [%d, %d]", subin_int, subin_frac, min, max); + isValid = false; + continue; + } + } + + return retVal; +} + +void setImagePyramid( void * input ) +{ + VisionCamImagePyramidType imagePyramid; + menuEnrty LevelsCount; + + LevelsCount.itemDescriptor = "Image pyramid levels"; + LevelsCount.defVal.min = 0; + LevelsCount.defVal.max = 16; + LevelsCount.defVal.exeptions = NULL; + LevelsCount.type = paramEntry_set; + LevelsCount.localValue = NULL; + LevelsCount.subMenu = NULL; + + imagePyramid.mLevelsCount = getValue( &LevelsCount ); + + imagePyramid.mScalingFactor = 1 << 16; + if (imagePyramid.mLevelsCount > 1) { + imagePyramid.mScalingFactor = getQ16Value("Image pyramid scaling factor [1-16] (for example: 1.5)", 1, 16); + } + + ((VisionCam*)input)->setParameter( (VisionCamParam_e)setImgPyramid.ID, + (void *)&imagePyramid, + sizeof( VisionCamImagePyramidType ), + VCAM_PORT_VIDEO + ); +} + +void setPreviewResolution( void * input ) +{ + VisionCam* vcam = (VisionCam*)input; + int32_t result = STATUS_SUCCESS; + int res; + bool_e restartPreview = false_e; + + /// choose new resolution + /// stop preview if running + /// release buffers + /// set new resolution + /// alloc new buffers + /// start preview if it was previously running + do { + for(int i = 0; i < VCAM_RESOL_MAX; i++ ) + printf("%d.\t%d x %d\n", i, VisionCamResolutions[i].mWidth, VisionCamResolutions[i].mHeight ); + + scanf("%d", &res); + + if( res < 0 && res >= VCAM_RESOL_MAX ) + printf("incorrect input; possible values are between %d and %d\n", 0, VCAM_RESOL_MAX - 1); + + } while ( res < 0 && res >= VCAM_RESOL_MAX ); + + result = vcam->setParameter( VCAM_PARAM_RESOLUTION , (void*)&res, sizeof(int), currentPort ); + if( STATUS_INVALID_STATE == result) + { + if STATUS_PASSED(vcam->sendCommand( VCAM_CMD_PREVIEW_STOP , 0, 0, currentPort) ) + { + restartPreview = true_e; + result = vcam->setParameter( VCAM_PARAM_RESOLUTION , (void*)&res, sizeof(int), currentPort); + } + } + + if( STATUS_SUCCESS == result ) { + result = stopServices( vcam ); + } + + if( STATUS_SUCCESS == result ) + { + prevResIdx = res; + result = startServices( vcam ); + } + else + { + printf("Error setting preview resolution"); + } + + if( restartPreview && STATUS_SUCCESS == result ) + result = vcam->sendCommand(VCAM_CMD_PREVIEW_START, 0, 0, currentPort); +} + +void setFaceDetect( void * input ) +{ + VisionCam* vcam = (VisionCam*)input; + faceDetectEnabled = !faceDetectEnabled; + bool_e en = ( faceDetectEnabled ? true_e : false_e); + vcam->sendCommand( VCAM_CMD_FACE_DETECTION, &en, sizeof(bool_e) ); + vcam->sendCommand( VCAM_CMD_FACE_DETECTION_RAW, &en, sizeof(bool_e) ); +} + +#ifndef EXPORTED_3A + +void whiteBalGains( void * input ) +{ + VisionCam* vcam = (VisionCam*)input; + VisionCamWhiteBalGains gainValues; + menuEnrty wbColorGains = wbGains; + + wbColorGains.subMenu = NULL; + + wbColorGains.itemDescriptor = "\nEnter gain for RED color"; + gainValues.mRed = getValue((const menuEnrty*)&wbColorGains); + + wbColorGains.itemDescriptor = "\nEnter gain for GREEN RED color"; + gainValues.mGreen_r = getValue((const menuEnrty*)&wbColorGains); + + wbColorGains.itemDescriptor = "\nEnter gain for GREEN BLUE color"; + gainValues.mGreen_b = getValue((const menuEnrty*)&wbColorGains); + + wbColorGains.itemDescriptor = "\nEnter gain for BLUE color"; + gainValues.mBlue = getValue((const menuEnrty*)&wbColorGains); + + vcam->setParameter( (VisionCamParam_e)wbGains.ID, + (void *)&gainValues, + sizeof(VisionCamWhiteBalGains) + ); +} + +void whiteBalGains_get( void * input ) +{ + int ret = STATUS_SUCCESS; + VisionCam* vcam = (VisionCam*)input; + VisionCamWhiteBalGains wbGains; + memset(&wbGains, 0, sizeof(VisionCamWhiteBalGains)); + + ret = vcam->getParameter((VisionCamParam_e)wbGains_get.ID , + (void *)&wbGains, + sizeof(VisionCamWhiteBalGains)); + if( STATUS_SUCCESS == ret ) + { + printf("gain red = %d\n", wbGains.mRed ); + printf("gain green red = %d\n", wbGains.mGreen_r); + printf("gain green blue = %d\n", wbGains.mGreen_b); + printf("gain blue = %d\n", wbGains.mBlue ); + } + else + printf("Error getting WB gains. Error = %d\n", ret); +} + +void gammaTablesTest( void * input ) +{ + VisionCam* vcam = (VisionCam*)input; + VisionCamGammaTableType gTable; + static unsigned int a = 3; + + vcam->getParameter((VisionCamParam_e)gammaTbl_test.ID, + (void*)&gTable, + sizeof(VisionCamGammaTableType)); + + if( a%2 ) + memset(gTable.mRedTable, 0, gTable.mTableSize); + else + gTable.mRedTable = NULL;/// this will cause gamma reset + + a++; + vcam->setParameter((VisionCamParam_e)gammaTbl_test.ID, + (void*)&gTable, + sizeof(VisionCamGammaTableType)); +} +#endif // EXPORTED_3A + +void setStereoLayout( void * input ) +{ + VisionCam * vcam = (VisionCam*)input; + menuEnrty lout; + + lout.ID = stereoLayout.ID; +// lout.defVal = stereoLayout.defVal; +// lout.itemDescriptor = stereoLayout.itemDescriptor; +// lout.menuKey = stereoLayout.menuKey; +// lout.type = neutralEntry; +// lout.localValue = &layout.layout; +// lout.subMenu = (void*)&stereoLayoutSubMenu; + +// layout.layout = (VisionCamStereoLayout)getValue( &lout ); + + VisionCamStereoInfo l; + l.layout = VCAM_STEREO_LAYOUT_TOPBOTTOM; + l.subsampling = 1; + + int i = vcam->setParameter((VisionCamParam_e)lout.ID, &l, sizeof(l), currentPort); + if( i != STATUS_SUCCESS ) printf("error set stsreo layout: %d \n", i); + +} + +void enableFramePack( void *input ) +{ + input = input; + usePackaging = !usePackaging; + if( usePackaging ) puts("\tframe pack enabled"); + else puts("\tframe pack disabled"); +} + +bool save2Dimage( VisionCamFrame *fr) +{ + bool success = true; + DVP_Image_t *pImage = NULL; + static int cur = -1; + unsigned char *pos = NULL; + char filename[33]; + FILE *outFile = NULL; + + cur++; + if( cur%10 ) + return false; + + sprintf(filename, "/sdcard/vcam_frame_%05d.yuv", cur); + outFile = fopen( filename, "wb"); + + if( outFile ) + { + pImage = (DVP_Image_t *)fr->mFrameBuff; + pos = pImage->pData[0] + fr->mOffsetY * pImage->y_stride + + fr->mOffsetX * pImage->x_stride; + size_t widthInBytes = pImage->width * pImage->x_stride; + + for( uint32_t h = 0; h < fr->mHeight; h++ , pos += pImage->y_stride ) + { + if( widthInBytes != fwrite(pos, 1, widthInBytes, outFile) ) + { + success = false; + break; + } + } + if( success ) + printf("%s written !\n", filename); + + fclose(outFile); + } + else + success = false; + + return success; +} + +void setDislpayableFrame(void *vCam __attribute__((unused))) +{ + menuEnrty e; + memcpy(&e, &setDispFrame, sizeof(menuEnrty)); + e.type = paramEntry_set; + e.subMenu = (void*)&dispFrameSubmenu; + /**((int*)e.localValue) = */getValue(&e); +} + +static void sendBufferTo_V4L(VisionCamFrame *cameraFrame) +{ + DVP_Image_t *pImage = (DVP_Image_t *)cameraFrame->mFrameBuff; + static int32_t frameCount[VCAM_PORT_MAX - VCAM_PORT_MIN] = {0}; + + if( displayedFrame == cameraFrame->mFrameSource ) + { + if( frameQ[displayedFrame] ) + { + queue_write(frameQ[displayedFrame], true_e, &pImage); + if( pImage != NULL && queue_read(frameQ[displayedFrame], true_e, &pImage) ) + DVP_Display_Render(dvpd[displayedFrame], pImage); + } + } + + ++frameCount[cameraFrame->mFrameSource - VCAM_PORT_MIN]; + +//#define PRINT_FACE_COORDS +#ifdef PRINT_FACE_COORDS + printf("\rfaces caught : %d , %d", cameraFrame->mDetectedFacesNum, cameraFrame->mDetectedFacesNumRaw); + for(int i = 0; i < cameraFrame->mDetectedFacesNum; i++) + { + printf("\nface %d [T,L,W,H]:%d,%d,%d,%d\n", i/*cameraFrame->mDetectedFacesNum*/, + cameraFrame->mFaces[i].mFacesCoordinates.mTop, + cameraFrame->mFaces[i].mFacesCoordinates.mLeft, + cameraFrame->mFaces[i].mFacesCoordinates.mWidth, + cameraFrame->mFaces[i].mFacesCoordinates.mHeight + ); + + } + for(int i = 0; i < cameraFrame->mDetectedFacesNumRaw ; i++) + { + printf("\nface RAW %d [T,L,W,H]:%d,%d,%d,%d\n", i/*cameraFrame->mDetectedFacesNumRaw*/, + cameraFrame->mFacesRaw[i].mFacesCoordinates.mTop, + cameraFrame->mFacesRaw[i].mFacesCoordinates.mLeft, + cameraFrame->mFacesRaw[i].mFacesCoordinates.mWidth, + cameraFrame->mFacesRaw[i].mFacesCoordinates.mHeight + ); + + } + +#endif +#define PRINT_WB_DATA +#ifdef PRINT_WB_DATA + if( cameraFrame->mMetadata.mAutoWBGains) + { + printf("Auto WB [R,Gr,Gb,B]:%10d,%10d,%10d,%10d\n", + cameraFrame->mMetadata.mAutoWBGains->mRed, + cameraFrame->mMetadata.mAutoWBGains->mGreen_r, + cameraFrame->mMetadata.mAutoWBGains->mGreen_b, + cameraFrame->mMetadata.mAutoWBGains->mBlue + ); + } + + if( cameraFrame->mMetadata.mManualWBGains) + { + printf("Manual WB [R,Gr,Gb,B]:%10d,%10d,%10d,%10d\n", + cameraFrame->mMetadata.mManualWBGains->mRed, + cameraFrame->mMetadata.mManualWBGains->mGreen_r, + cameraFrame->mMetadata.mManualWBGains->mGreen_b, + cameraFrame->mMetadata.mManualWBGains->mBlue + ); + } +#endif +#define PRINT_ANCILLARY +#ifdef PRINT_ANCILLARY + if( cameraFrame->mMetadata.mAncillary) + { + printf("Ancillary [Fr#,Exp,Ag,ISO]:%10d,%10d,%10d,%10d\n", + cameraFrame->mMetadata.mAncillary->nFrameNumber, + cameraFrame->mMetadata.mAncillary->nExposureTime, + cameraFrame->mMetadata.mAncillary->nAnalogGainValue, + cameraFrame->mMetadata.mAncillary->nCurrentISO + ); + } +#endif +//#define PRINT_HISTOGRAM +#ifdef PRINT_HISTOGRAM + if( cameraFrame->mMetadata.mHistogram2D) + { + printf("Histogram2D [#Bins, Type]:%d,%d\n", + cameraFrame->mMetadata.mHistogram2D->nBins, + cameraFrame->mMetadata.mHistogram2D->eComponentType + ); + for(uint32_t i = 0; i < cameraFrame->mMetadata.mHistogram2D->nBins; i++) + printf("%3d,", cameraFrame->mMetadata.mHistogram2D->data[i]); + } +#endif + +#define PRINT_HISTOGRAM_GAMMA +#ifdef PRINT_HISTOGRAM_GAMMA + if( 0 && 100 == frameCount[cameraFrame->mFrameSource - VCAM_PORT_MIN] ) + {here + if( cameraFrame->mMetadata.mGammaL) + { + printf("Gamma L [#items]:%d\n", + cameraFrame->mMetadata.mGammaL->nItems/*, + cameraFrame->mMetadata.mGammaL*/ + ); + for(uint32_t i = 0; i < ( cameraFrame->mMetadata.mGammaL->nItems ) / 16 ; i+=16) + { + puts(""); + for(int j = 0; j < 16; j++) + printf("%3d, ", cameraFrame->mMetadata.mGammaL->data[i + j]); + } + } + if( cameraFrame->mMetadata.mGammaR) + { + printf("Gamma R [#items]:%d\n", cameraFrame->mMetadata.mGammaR->nItems); + for(uint32_t i = 0; i < ( cameraFrame->mMetadata.mGammaR->nItems ) / 16 ; i+=16) + { + puts(""); + for(int j = 0; j < 16; j++) + printf("%3d, ", cameraFrame->mMetadata.mGammaR->data[i + j]); + } + } + if( cameraFrame->mMetadata.mGamma2D) + {here + printf("Gamma 2D [#items]:%d\n",cameraFrame->mMetadata.mGamma2D->nItems); + for(uint32_t i = 0; i < ( cameraFrame->mMetadata.mGamma2D->nItems ) / 16 ; i+=16) + { + puts(""); + for(int j = 0; j < 16; j++) + printf("%3d, ", cameraFrame->mMetadata.mGamma2D->data[i + j]); + } + } + } +#endif + +#ifdef GRE_DEBUG_FILEOUT + if( cameraFrame->mExtraDataBuf ) + { + static int cur = 1; + char filename[33]; + sprintf(filename, "gre_cam_fr_%05d.edt", cur); + FILE * XtraDataFile = fopen(filename, "wb"); + fwrite( prvFrame->mExtraDataBuf , EXTRA_DATA_FILE_LENGHT , 1 , XtraDataFile ); +// printf("\r gre_cam_fr_%05d.edt written", cur); + cur++; + } +#endif + fprintf(stdout, "\r total frames: video - %d, preview - %d, (diff: %d)", + frameCount[VCAM_PORT_VIDEO - VCAM_PORT_MIN], + frameCount[VCAM_PORT_PREVIEW - VCAM_PORT_MIN], + ( frameCount[VCAM_PORT_PREVIEW - VCAM_PORT_MIN] - frameCount[VCAM_PORT_VIDEO - VCAM_PORT_MIN] ) + ); + + fflush(stdout); + ((VisionCam *)cameraFrame->mContext)->returnFrame(cameraFrame); +} + +static void receiveFramePackage(VisionCamFramePack *pack) +{ + VisionCamFrame *frame = NULL; + DVP_Image_t *pImage = NULL; + + static int32_t packs = 0; + + for( int32_t i = VCAM_PORT_ALL + 1; i < VCAM_PORT_MAX; i++ ) + { + if( pack->mExpectedFrames[i] ) + { + frame = pack->mFrame[i]; + if( frame ) + { + pImage = (DVP_Image_t *)frame->mFrameBuff; + ((VisionCam *)frame->mContext)->returnFrame(frame); + } + } + } + packs++; + fprintf(stdout, "\rtotal frames: %d", packs ); + fflush(stdout); +} + +void drawFaceBox(VisionCamFrame *cameraFrame) +{ + unsigned char * pos = NULL; + unsigned int bottom; + DVP_Image_t *pFrame = (DVP_Image_t *)cameraFrame->mFrameBuff; + + for(uint32_t face = 0; face < cameraFrame->mDetectedFacesNum; face++ ) + { + uint32_t top = cameraFrame->mFaces[face].mFacesCoordinates.mTop; + uint32_t left = cameraFrame->mFaces[face].mFacesCoordinates.mLeft; + uint32_t width = cameraFrame->mFaces[face].mFacesCoordinates.mWidth; + uint32_t height = cameraFrame->mFaces[face].mFacesCoordinates.mHeight; + + if (width > cameraFrame->mWidth - left) + { + width = cameraFrame->mWidth - left; + } + + if (height > cameraFrame->mHeight - top) + { + height = cameraFrame->mHeight - top; + } + bottom = (unsigned int)(pFrame->pData[0]+(cameraFrame->mOffsetY + top + height)*pFrame->y_stride); + + /// calculate top left posotion + pos = pFrame->pData[0] + (cameraFrame->mOffsetY + top) * pFrame->y_stride + + (cameraFrame->mOffsetX + left) * pFrame->x_stride; + + /// draw two lines - horizontal border, top + memset(pos, 0 , width*pFrame->x_stride); + + pos += pFrame->y_stride; + if( (unsigned int)pos > bottom ) + pos -= pFrame->y_stride; + + memset(pos, 0 , width*pFrame->x_stride); + + pos += pFrame->y_stride; + if( (unsigned int)pos > bottom ) + pos -= pFrame->y_stride; + + /// draw vertical border + for( ; (unsigned int)pos < bottom - 2 ; pos += pFrame->y_stride) + { + pos[0] = 0; + pos[1] = 0; + pos[width*pFrame->x_stride + 0] = 0; + pos[width*pFrame->x_stride + 1] = 0; + } + /// draw two lines - horizontal border, bottom + memset(pos, 0 , width*pFrame->x_stride); + + pos += pFrame->y_stride; + if( (unsigned int)pos > bottom ) + pos -= pFrame->y_stride; + + memset(pos, 0 , width*pFrame->x_stride); + } +} + +void setFormat( void * input ) +{ + VisionCam *vcam = (VisionCam *)input; + menuEnrty subFormat; + int tempColorSpace; + int result = STATUS_SUCCESS; + + memcpy( &subFormat, &format, sizeof(menuEnrty)); + + subFormat.type = paramEntry_set; + subFormat.subMenu = (void*)&colorFormatSubMenu; + + if( VCAM_PORT_PREVIEW == currentPort ) + subFormat.localValue = &colorSpacePeview; + else if( VCAM_PORT_VIDEO == currentPort ) + subFormat.localValue = &colorSpaceVideo; + else + subFormat.localValue = &colorSpacePeview; + + tempColorSpace = getValue( &subFormat ); + + if( STATUS_INVALID_STATE == vcam->setParameter( (VisionCamParam_e)format.ID , (void*)&tempColorSpace, sizeof(int), currentPort)) + { + bool restartPreview[VCAM_PORT_MAX] = { false };// one flag for each port, so we'd know which to start again + + if STATUS_PASSED(vcam->sendCommand( VCAM_CMD_PREVIEW_STOP, NULL, 0, VCAM_PORT_PREVIEW ) ) + restartPreview[VCAM_PORT_PREVIEW] = true; + + if STATUS_PASSED(vcam->sendCommand( VCAM_CMD_PREVIEW_STOP, NULL, 0, VCAM_PORT_VIDEO ) ) + restartPreview[VCAM_PORT_VIDEO] = true; + + result = stopServices( vcam ); + + if( STATUS_SUCCESS == result ) + { + if STATUS_FAILED( vcam->setParameter( (VisionCamParam_e)format.ID, (void *)&tempColorSpace, sizeof(int), currentPort) ) + printf("Error setting color format."); + } + + if( STATUS_SUCCESS == result ) + { + *((int32_t*)subFormat.localValue) = tempColorSpace; + result = startServices(vcam); + } + + if( restartPreview[VCAM_PORT_VIDEO] && STATUS_SUCCESS == result ) + result = vcam->sendCommand(VCAM_CMD_PREVIEW_START, NULL, 0, VCAM_PORT_VIDEO); + + if( restartPreview[VCAM_PORT_PREVIEW] && STATUS_SUCCESS == result ) + result = vcam->sendCommand(VCAM_CMD_PREVIEW_START, NULL, 0, VCAM_PORT_PREVIEW); + } +} diff --git a/source/dvp/VisionCam/VisionCamTestData.h b/source/dvp/VisionCam/VisionCamTestData.h new file mode 100644 index 0000000..e0dae9e --- /dev/null +++ b/source/dvp/VisionCam/VisionCamTestData.h @@ -0,0 +1,1093 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __VCAM_TEST_DATA__ +#define __VCAM_TEST_DATA__ +#include "VisionCamTestTypes.h" + +void setCropParams( void * input ); +void setVariableFrameRate( void * input ); +void setPreviewResolution( void * input ); +void setFaceDetect( void * input ); +void setImagePyramid( void * input ); + +#ifndef EXPORTED_3A + void whiteBalGains( void * input ); + void whiteBalGains_get( void * input ); + void gammaTablesTest( void * input ); +#endif // EXPORTED_3A + +void setFormat( void * input ); +void setStereoLayout( void * input ); +void enableFramePack( void *input ); + +#ifdef EXPORTED_3A + void startExported3A_Menu( void * input ); +#endif // EXPORTED_3A + +#define CAP_FRAME +#ifdef CAP_FRAME +void capFrame( void *input ); +#endif // CAP_FRAME + +void setDislpayableFrame(void *input); + +static bool usePackaging = false; +static int32_t displayedFrame = VCAM_PORT_PREVIEW; +static int prevResIdx = VCAM_RES_QVGA; +static int colorSpacePeview = FOURCC_NV12; +static int colorSpaceVideo = FOURCC_NV12; +static int operatingMode = /*VCAM_GESTURE_DUAL_SENSOR_MODE;//*/VCAM_GESTURE_MODE;//VCAM_VIDEO_NORMAL; +static int currSensor = VCAM_SENSOR_PRIMARY;//VCAM_SENSOR_SECONDARY; +//static int layout = VCAM_STEREO_LAYOUT_TOPBOTTOM; +static VisionCamStereoInfo layout = {VCAM_STEREO_LAYOUT_TOPBOTTOM, 1}; +static VisionCamPort_e currentPort = VCAM_PORT_ALL; +//static bool dumpExtraDataEnabled = false; +static bool faceDetectEnabled = false; +static VisionCamVarFramerateType varFrate; + +//static VisionCamPort_e framesDisplayed = VCAM_PORT_PREVIEW; +static bool recNextFrame = false; + +static VisionCamRectType cropParams = { + 0, + 0, + VisionCamResolutions[prevResIdx].mWidth, + VisionCamResolutions[prevResIdx].mHeight +}; + +/** Values for the menu input + * entered by user + */ +entryKey KEY_PREVIEW_START = "p"; +entryKey KEY_PREVIEW_STOP = "r"; +entryKey KEY_PORT = "port"; +// entryKey KEY_ETRA_DATA_Rx = "e"; +// entryKey KEY_ETRA_DATA_STOP_Rx = "f"; +entryKey KEY_EXTRA_DATA_START = "e"; +entryKey KEY_EXTRA_DATA_STOP = "es"; +entryKey KEY_BRIGHTNESS = "br"; +entryKey KEY_CONTRAST = "co"; +entryKey KEY_SHARPNESS = "sh"; +entryKey KEY_SATURATION = "sa"; +entryKey KEY_FLICKER = "fl"; +entryKey KEY_CROP = "cr"; +entryKey KEY_FRAME_RATE_FIXED = "fr"; +entryKey KEY_FRAME_RATE_VAR = "fv"; +entryKey KEY_CAPTURE_MODE = "cm"; +entryKey KEY_COLOR_FORMAT_MODE = "cf"; +entryKey KEY_SENSOR_SELECTION = "se"; +entryKey KEY_FOCUS = "fo"; +entryKey KEY_FOCUS_MANUAL = "mf"; +entryKey KEY_MANUAL_EXPOSURE = "ex"; +entryKey KEY_EXPOSURE_ISO = "so"; +entryKey KEY_EXPOSURE_COMPENSATION = "ec"; +entryKey KEY_AE_LOCK = "le"; +entryKey KEY_AWB_MODE = "wb"; +entryKey KEY_AWB_LOCK = "lb"; +entryKey KEY_COLOR_TEMPERATURE = "ct"; +entryKey KEY_RESOLUTION = "re"; +entryKey KEY_FACE_DETECTION = "fd"; +entryKey KEY_GET_PARAMETER = "gp"; +entryKey KEY_WB_GAINS = "cg"; +entryKey KEY_WB_GAINS_GET = "gg"; +entryKey KEY_WB_GAMMA_TBL = "gt"; +entryKey KEY_MIRROR = "mi"; +entryKey KEY_ROTATION = "ro"; +entryKey KEY_AWB_MIN_DELAY_TIME = "wbd"; +entryKey KEY_GESTURES_INFO = "gfo"; +entryKey KEY_AGC_MIN_DELAY_TIME = "gd"; +entryKey KEY_AGC_LOW_TH = "gmax"; +entryKey KEY_AGC_HIGH_TH = "gmin"; +entryKey KEY_FREEZE_AGC_PARAMS = "fgain"; +entryKey KEY_FREEZE_AWB_PARAMS = "fbal"; +entryKey KEY_STEREO_LAYOUT = "lout"; +entryKey KEY_PACK_FRAMES = "pack"; +entryKey KEY_HOLD_EXPORTED_3A = "3ahold"; +entryKey KEY_SET_EXPORTED_3A = "3aset"; +entryKey KEY_SET_DISPLAYED_FRM = "disp"; +entryKey KEY_IMAGE_PYRAMID = "ip"; + +#ifdef CAP_FRAME +entryKey KEY_CAP_FRAME = "cap"; +#endif // CAP_FRAME + +entryKey KEY_QUIT = "q"; + +#if TIME_PROFILE + entryKey KEY_DUMP_TIMES = "du"; +#endif + +const int portOpts[] = { + VCAM_PORT_PREVIEW, + VCAM_PORT_VIDEO, + VCAM_PORT_ALL +}; + +const char * portStrings[] = { + "preview port", + "video port", + "all ports" +}; + +const subMenuEnrty portSubMenu = { + portOpts, + portStrings +}; + +const int extraDataOpts[] = { + VCAM_EXTRA_DATA_NONE, +// VCAM_EXIF_ATTRIBUTES, + VCAM_ANCILLARY_DATA, + VCAM_WHITE_BALANCE, + VCAM_UNSATURATED_REGIONS, + VCAM_FACE_DETECTION, +// VCAM_BARCODE_DETECTION, +// VCAM_FRONT_OBJECT_DETECTION, +// VCAM_MOTION_ESTIMATION, + VCAM_MTIS_TYPE, +// VCAM_DISTANCE_ESTIMATION, + VCAM_HISTOGRAM, + VCAM_FOCUS_REGION, +// VCAM_EXTRA_DATA_PAN_AND_SCAN, +// VCAM_RAW_FORMAT, +// VCAM_SENSOR_TYPE, +// VCAM_SENSOR_CUSTOM_DATA_LENGTH, +// VCAM_SENSOR_CUSTOM_DATA + VCAM_MANUAL_WHITE_BALANCE, + VCAM_FACE_DETECTION_RAW, + VCAM_HMS_GAMMA +}; + +const char * extraDataStrings[] = { + "disable all", +// "exif attributes", + "ancillary data", + "white balance", + "unsaturated regions", + "face detection", +// "barcode detection", +// "front object detection", +// "motion estimation", + "mtis type", +// "distance estimation", + "histogram", + "focus region", +// "extra data Pan and Scan", +// "RAW format", +// "sensor type", +// "sensor custom data length", +// "sensor custom data" + "manual white balance data", + "gamma (calculated hms gamma)" +}; + +const subMenuEnrty extraDataSubMenu = { + extraDataOpts, + extraDataStrings +}; + +const int flickerOpts[] = { + FLICKER_OFF, + FLICKER_AUTO, + FLICKER_50Hz, + FLICKER_60Hz, + FLICKER_100Hz, + FLICKER_120Hz +}; + +const char * flickerStrings[] = { + "off - flicker", + "auto - flicker", + "50Hz flicker", + "60Hz flicker", + "100Hz flicker", + "120Hz flicker" +}; + +const subMenuEnrty flickerSubMenu = { + flickerOpts, + flickerStrings +}; + +const int captureModeOpts[] = { + VCAM_VIDEO_NORMAL, + VCAM_VIDEO_HIGH_SPEED, + VCAM_GESTURE_MODE, + VCAM_STEREO_GEST_MODE, + VCAM_STEREO_MODE, + VCAM_GESTURE_DUAL_SENSOR_MODE +}; + +const char * captureModeStrings[] ={ + "Video normal ( default )", + "Video high speed ( 120 fps )", + "Gesture Operating Mode", + "Stereo Gesture", + "Stereo Normal", + "Dual Sensor Gesture Mode" +}; + +const subMenuEnrty captureModeSubMenu = { + captureModeOpts, + captureModeStrings +}; + +const int colorFormatOpts[] = { + FOURCC_UYVY, + FOURCC_NV12, + FOURCC_RGB565, + FOURCC_BGR565 +}; + +const char * colorFormatStrings[] = { + "format UYVY", + "format NV12", + "format RGB 565", + "format BGR 565" +}; + +const subMenuEnrty colorFormatSubMenu = { + colorFormatOpts, + colorFormatStrings +}; + + +const int sensorSelOpts[] = { + VCAM_SENSOR_PRIMARY, + VCAM_SENSOR_SECONDARY, + VCAM_SENSOR_STEREO, +}; + +const char * sensorSelStrings[] = { + "Primary Sensor", + "Secondary Sensor", + "Stereo Sensors" +}; + +const subMenuEnrty sensorSelSubMenu = { + sensorSelOpts, + sensorSelStrings +}; + +const int focusOpts[] = { + VCAM_FOCUS_CONTROL_ON, + VCAM_FOCUS_CONTROL_OFF, + VCAM_FOCUS_CONTROL_AUTO, + VCAM_FOCUS_CONTROL_AUTO_LOCK, + /// TI extensions follow + VCAM_FOCUS_CONTRO_AUTO_MACRO, + VCAM_FOCUS_CONTROL_AUTO_INFINITY, + VCAM_FOCUS_FACE_PRIORITY_MODE, + VCAM_FOCUS_REGION_PRIORITY_MODE, + VCAM_FOCUS_CONTROL_HYPERFOCAL, + VCAM_FOCUS_CONTROL_PORTRAIT, + VCAM_FOCUS_CONTROL_EXTENDED, + VCAM_FOCUS_CONTROL_CONTINOUS_NORMAL, + VCAM_FOCUS_CONTROL_CONTINOUS_EXTENDED, + VCAM_FOCUS_FACE_PRIORITY_CONTINOUS_MODE, + VCAM_FOCUS_REGION_PRIORITY_CONTINOUS_MODE +}; + +const char *focusStrings[] = { + "on", + "off", + "auto", + "auto lock", + "auto macro", + "auto infinity", + "face priority mode", + "region priority mode", + "hyperfocal", + "portrait", + "extended", + "continous normal", + "continous extended", + "priority continous mode", + "region priority continous mode" +}; +const subMenuEnrty focusSubMenu = { + focusOpts, + focusStrings +}; + +const int lockOpts[] = { + UNLOCKED, + LOCKED +}; + +const char * lockStrings[] = { + "Unlock", + "Lock" +}; + +const subMenuEnrty lockSubMenu = { + lockOpts, + lockStrings +}; + +const int whiteBalOpts [] = { + VCAM_WHITE_BAL_CONTROL_OFF, + VCAM_WHITE_BAL_CONTROL_AUTO, + VCAM_WHITE_BAL_CONTROL_SUNLIGHT, + VCAM_WHITE_BAL_CONTROL_CLOUDY, + VCAM_WHITE_BAL_CONTROL_SHADE, + VCAM_WHITE_BAL_CONTROL_TUNGSTEN, + VCAM_WHITE_BAL_CONTROL_FLUORESCENT, + VCAM_WHITE_BAL_CONTROL_INCANDESCENT, + VCAM_WHITE_BAL_CONTROL_FLASH, + VCAM_WHITE_BAL_CONTROL_HORIZON, + VCAM_WHITE_BAL_CONTROL_FACEPRIORITYMODE +}; + +const char * whiteBalStrings[] = { + "off", + "auto", + "sunlight", + "cloudy", + "shade", + "tungsten", + "fluorescent", + "incandescent", + "flash", + "horizon", + "face priority mode" +}; + +const subMenuEnrty wbSubMenu = { + whiteBalOpts, + whiteBalStrings +}; + +const int mirrorOpts [] = { + VCAM_MIRROR_NONE, + VCAM_MIRROR_VERTICAL, + VCAM_MIRROR_HORIZONTAL, + VCAM_MIRROR_BOTH, +}; + +const char * mirrorStrings[] = { + "No Mirroring", + "Vertical", + "Horizontal", + "Horizontal and Vertical" +}; + +const subMenuEnrty mirrorSubMenu = { + mirrorOpts, + mirrorStrings +}; + +const int getParamIDs[] = { + VCAM_PARAM_DO_AUTOFOCUS, + VCAM_PARAM_DO_MANUALFOCUS, + VCAM_PARAM_CONTRAST, + VCAM_PARAM_SHARPNESS, + VCAM_PARAM_BRIGHTNESS, + VCAM_PARAM_SATURATION, + VCAM_PARAM_HEIGHT, + VCAM_PARAM_WIDTH, + VCAM_PARAM_FPS_FIXED, + VCAM_PARAM_FPS_VAR, + VCAM_PARAM_COLOR_SPACE_FOURCC, + VCAM_PARAM_FLICKER, + VCAM_PARAM_CROP, + VCAM_PARAM_CAP_MODE, + VCAM_PARAM_SENSOR_SELECT, + VCAM_PARAM_EXPOSURE_COMPENSATION, + VCAM_PARAM_RESOLUTION, + VCAM_PARAM_MANUAL_EXPOSURE, + VCAM_PARAM_AWB_MODE, + VCAM_PARAM_COLOR_TEMP, + VCAM_PARAM_EXPOSURE_ISO, + VCAM_PARAM_MIRROR, +}; + +const char * getParamstrings[] = { + "focus mode", + "manual focus distance", + "contrast", + "sharpness", + "brightness", + "saturation", + "height", + "width", + "fps fixed", + "fps var", + "color space", + "flicker", + "crop", + "cap mode", + "sensor select", + "exporure compensation", + "resolution", + "manual exposure", + "awb mode", + "color temp", + "exposure iso", + "get mirroring" +}; + +const subMenuEnrty getParamSubMenu = { + getParamIDs, + getParamstrings +}; + +const int stereloLayoutIDs[] = { + VCAM_STEREO_LAYOUT_TOPBOTTOM, + VCAM_STEREO_LAYOUT_LEFTRIGHT +}; + +const char * stereoLayoutStrings[] = { + "Top - Bottom", + "Side by Side" +}; + +const subMenuEnrty stereoLayoutSubMenu = { + stereloLayoutIDs, + stereoLayoutStrings +}; + +const menuEnrty startPreview = { + KEY_PREVIEW_START, + commandEntry, + VCAM_CMD_PREVIEW_START, + "Start preview", + { 0, 0, NULL }, + NULL, + NULL +}; + +const menuEnrty stopPreview = { + KEY_PREVIEW_STOP, + commandEntry, + VCAM_CMD_PREVIEW_STOP, + "Stop preview", + { 0, 0, NULL }, + NULL, + NULL +}; + +const menuEnrty portUsage = { + KEY_PORT, + neutralEntry, + 0xFFFFFFFF, + "Port", + { 0, ARR_SIZE(portOpts) - 1, NULL }, + ¤tPort, + (void*)&portSubMenu +}; + +const menuEnrty extraDataStart = { + KEY_EXTRA_DATA_START, + commandEntry, + VCAM_EXTRA_DATA_START, + "Extra data start (asks for data type).", + { 0, ARR_SIZE(extraDataOpts) - 1, NULL }, + NULL, + (void*)&extraDataSubMenu +}; + +const menuEnrty extraDataStop = { + KEY_EXTRA_DATA_STOP, + commandEntry, + VCAM_EXTRA_DATA_STOP, + "Extra data stop (asks for data type).", + { 0, ARR_SIZE(extraDataOpts) - 1, NULL }, + NULL, + (void*)&extraDataSubMenu +}; + +const menuEnrty brightness = { + KEY_BRIGHTNESS, + paramEntry_set, + VCAM_PARAM_BRIGHTNESS, + "Brightness.", + { 0 , 200, NULL }, + NULL, + NULL +}; + +const menuEnrty contrast = { + KEY_CONTRAST, + paramEntry_set, + VCAM_PARAM_CONTRAST, + "Contrast.", + { -100 , 100, NULL }, + NULL, + NULL +}; + +const menuEnrty sharpness = { + KEY_SHARPNESS, + paramEntry_set, + VCAM_PARAM_SHARPNESS, + "Sharpness.", + { -100 , 100, NULL }, + NULL, + NULL +}; + +const menuEnrty saturation = { + KEY_SATURATION, + paramEntry_set, + VCAM_PARAM_SATURATION, + "Saturation.", + { -100 , 100, NULL }, + NULL, + NULL +}; + +const menuEnrty flicker = { + KEY_FLICKER, + paramEntry_set, + VCAM_PARAM_FLICKER, + "Flicker", + { 0, ARR_SIZE(flickerOpts) - 1 , NULL }, + NULL, + (void*)&flickerSubMenu +}; + +const menuEnrty crop = { + KEY_CROP, + functionalEntry, + VCAM_PARAM_CROP, + "Crop", + { 0 , 0, NULL }, + &cropParams, + (void*)( (subMenuFn)setCropParams ) +}; + +const menuEnrty frameRate_variable = { + KEY_FRAME_RATE_VAR, + functionalEntry, + VCAM_PARAM_FPS_VAR, + "Frame rate - variable", + { 0 , 0, NULL }, + NULL, + (void*)( (subMenuFn)setVariableFrameRate ) +}; + +const menuEnrty frameRate_fixed = { + KEY_FRAME_RATE_FIXED, + paramEntry_set, + VCAM_PARAM_FPS_FIXED, + "Frame rate ( 0 for auto )", + { 0 , 30, NULL }, + NULL, + NULL +}; + +const menuEnrty captureMode = { + KEY_CAPTURE_MODE, + paramEntry_set, + VCAM_PARAM_CAP_MODE, + "Capture mode", + { 0 , ARR_SIZE(captureModeOpts) - 1, NULL }, + &operatingMode, + (void*)&captureModeSubMenu +}; + +const menuEnrty format = { + KEY_COLOR_FORMAT_MODE, + functionalEntry, //paramEntry_set, + VCAM_PARAM_COLOR_SPACE_FOURCC, + "Color format", + { 0 , (ARR_SIZE(colorFormatOpts) - 1), NULL }, + &colorSpacePeview, + (void*)((subMenuFn)setFormat) +}; + +const menuEnrty sensor = { + KEY_SENSOR_SELECTION, + paramEntry_set, + VCAM_PARAM_SENSOR_SELECT, + "Sensor select", + { 0 , ARR_SIZE(sensorSelOpts ) - 1, NULL }, + &currSensor, + (void*)&sensorSelSubMenu +}; + +const menuEnrty expCompensation = { + KEY_EXPOSURE_COMPENSATION, + paramEntry_set, + VCAM_PARAM_EXPOSURE_COMPENSATION, + "Exposure Compensation ( *10 )", + { -20 , 20, NULL }, + NULL, + NULL +}; + +const menuEnrty focus = { + KEY_FOCUS, + paramEntry_set, + VCAM_PARAM_DO_AUTOFOCUS, + "Focus type (not all listed are available)", + { VCAM_FOCUS_CONTROL_ON , ( VCAM_FOCUS_CONTROL_MAX - 1 ), NULL }, + NULL, + (void *)&focusSubMenu +}; + +const menuEnrty focusManual = { + KEY_FOCUS_MANUAL, + paramEntry_set, + VCAM_PARAM_DO_MANUALFOCUS, + "Focus - manual ( in millimeters )", + { 0 , 100, NULL }, + NULL, + NULL +}; + +const menuEnrty manualExp = { + KEY_MANUAL_EXPOSURE, + paramEntry_set, + VCAM_PARAM_MANUAL_EXPOSURE, + "Exposure - manual ( changes frame rate; 0 - auto)", + { 0, 100, NULL }, + NULL, + NULL +}; + +const int isoGainEx[] = { 0 }; + +const exeptionValues expISO_exeptios = { + isoGainEx, + ARR_SIZE(isoGainEx) +}; + +const menuEnrty expISO_Gain = { + KEY_EXPOSURE_ISO, + paramEntry_set, + VCAM_PARAM_EXPOSURE_ISO, + "ISO / Gain ( gain = ISO / 100 )", + { 100, 1600, &expISO_exeptios }, + NULL, + NULL +}; + +const menuEnrty expLock = { + KEY_AE_LOCK, + commandEntry, + VCAM_CMD_LOCK_AE, + "Lock Exposure", + { UNLOCKED , LOCKED, NULL }, + NULL, + ( void *)&lockSubMenu +}; + +const menuEnrty awbLock = { + KEY_AWB_LOCK, + commandEntry, + VCAM_CMD_LOCK_AWB, + "Lock White Balance", + { UNLOCKED , LOCKED, NULL }, + NULL, + ( void *)&lockSubMenu +}; + +const menuEnrty awbMode = { + KEY_AWB_MODE, + paramEntry_set, + VCAM_PARAM_AWB_MODE, + "White Balance Mode", + { VCAM_WHITE_BAL_CONTROL_OFF , (ARR_SIZE( whiteBalOpts) - 1), NULL }, + NULL, + ( void *)&wbSubMenu +}; + +const int colorTempEx[] = { 0 }; + +const exeptionValues colorTempExeption = { + colorTempEx, + ARR_SIZE(colorTempEx) +}; + +const menuEnrty colorTemp = { + KEY_COLOR_TEMPERATURE, + paramEntry_set, + VCAM_PARAM_COLOR_TEMP, + "Corlor Temp ( Kelvins )", + { 2020 , 7100, &colorTempExeption }, + NULL, + NULL +}; + +const menuEnrty prvRes = { + KEY_RESOLUTION, + functionalEntry, + VCAM_PARAM_RESOLUTION, + "Resolution change", + { 0 , ( VCAM_RESOL_MAX - 1 ), NULL }, + &prevResIdx, + (void*)( (subMenuFn)setPreviewResolution ) +}; + +#if TIME_PROFILE +const menuEnrty dumpTimes = { + KEY_DUMP_TIMES, + commandEntry, + VCAM_DUMP_TIMES, + "Get measured times.", + { 0 , 0, NULL }, + NULL, + NULL +}; +#endif + +const menuEnrty faceDet = { + KEY_FACE_DETECTION, + functionalEntry, + VCAM_CMD_FACE_DETECTION, + "Enable/Disable face detection", + { 0 , 0, NULL }, + &faceDetectEnabled, + (void*)( (subMenuFn)setFaceDetect ) +}; + +const menuEnrty getParam = { + KEY_GET_PARAMETER, + paramEntry_get, + (unsigned)(-1), + "Get parameter value", + { 0 , ARR_SIZE(getParamIDs) - 1, NULL }, + NULL, + ( void *)&getParamSubMenu +}; + +const int wbGainEx[] = { 0 }; + +const exeptionValues wbGainExeptions = { + wbGainEx, + ARR_SIZE(wbGainEx) +}; +#ifndef EXPORTED_3A +const menuEnrty wbGains = { + KEY_WB_GAINS, + functionalEntry, + VCAM_PARAM_WB_COLOR_GAINS, + "Set color gains (white balance color gains)", + { 512 , 2048, &wbGainExeptions }, + NULL, + (void*)( (subMenuFn)whiteBalGains) +}; + +const menuEnrty wbGains_get = { + KEY_WB_GAINS_GET, + functionalEntry, + VCAM_PARAM_WB_COLOR_GAINS, + "Get color gains (white balance color gains)", + { 0 , 0, NULL }, + NULL, + (void*)( (subMenuFn)whiteBalGains_get) +}; + +const menuEnrty gammaTbl_test = { + KEY_WB_GAMMA_TBL, + functionalEntry, + VCAM_PARAM_GAMMA_TBLS, + "Gamma test ( test passed if review goes negative )", + { 0 , 0, NULL }, + NULL, + (void*)( (subMenuFn)gammaTablesTest) +}; +#endif // EXPORTED_3A + +const menuEnrty mirroring = { + KEY_MIRROR, + paramEntry_set, + VCAM_PARAM_MIRROR, + "Mirror", + { 0 , ARR_SIZE( mirrorOpts ) - 1 , NULL }, + NULL, + (void*)&mirrorSubMenu +}; + +const menuEnrty rotation = { + KEY_ROTATION, + paramEntry_set, + VCAM_PARAM_ROTATION, + "Rotation (0 | 90 | 180 | 270)", + { 0 , 270 , NULL }, /// @todo create a table with possible values !!! + NULL, + NULL +}; + +const menuEnrty awbMinDelayTime = { + KEY_AWB_MIN_DELAY_TIME, + paramEntry_set, + VCAM_PARAM_AWB_MIN_DELAY_TIME, + "AWB minimun delay time [ms]", + { 0, 10000, NULL }, + NULL, + NULL +}; + +const menuEnrty agcMinDelayTime = { + KEY_AGC_MIN_DELAY_TIME, + paramEntry_set, + VCAM_PARAM_AGC_MIN_DELAY_TIME, + "AGC (AE) minimun delay time [ms]", + { 0, 10000, NULL }, + NULL, + NULL +}; + +const menuEnrty agcLowTh = { + KEY_AGC_LOW_TH, + paramEntry_set, + VCAM_PARAM_AGC_LOW_TH, + "AGC (AE) low threshold", + { 0, 10000, NULL }, + NULL, + NULL +}; + +const menuEnrty agcHighTh = { + KEY_AGC_HIGH_TH, + paramEntry_set, + VCAM_PARAM_AGC_HIGH_TH, + "AGC (AE) high threshold", + { 0, 10000, NULL }, + NULL, + NULL +}; + +const menuEnrty gestureInfo = { + KEY_GESTURES_INFO, + functionalEntry, + VCAM_PARAM_GESTURES_INFO, + "Gestures info", + { 0, 0, NULL }, + NULL, + NULL +}; + +const menuEnrty freezeAWBparams = { + KEY_FREEZE_AWB_PARAMS, + commandEntry, + VCAM_CMD_FREEZE_AWB_PARAMS, + "Freeze AWB params", + { 0, 10000, NULL }, + NULL, + NULL +}; + +const menuEnrty freezeAGCparams = { + KEY_FREEZE_AGC_PARAMS, + commandEntry, + VCAM_CMD_FREEZE_AGC_PARAMS, + "Freeze AGC (AE) params", + { 0, 10000, NULL }, + NULL, + NULL +}; + +const menuEnrty stereoLayout = { + KEY_STEREO_LAYOUT, + functionalEntry, + VCAM_PARAM_STEREO_INFO, + "Layout (stereo layout)", + { stereloLayoutIDs[0], (ARR_SIZE(stereloLayoutIDs) - 1), NULL }, + (void*)&layout, + (void*)( (subMenuFn)setStereoLayout ) +}; + +const menuEnrty packFrames = { + KEY_PACK_FRAMES, + functionalEntry, + VCAM_PARAM_MAX, + "Pack frames", + { 0, 0, NULL }, + NULL, + (void*)( (subMenuFn)enableFramePack ) +}; + +#ifdef CAP_FRAME +const menuEnrty recordFrame = { + KEY_CAP_FRAME, + functionalEntry, + VCAM_PARAM_MAX, + "Capture Frame (only next one)", + { 0, 0, NULL }, + (void*)recNextFrame, + (void*)( (subMenuFn)capFrame ) +}; +#endif + +const menuEnrty quit = { + KEY_QUIT, + neutralEntry, + VCAM_CMD_QUIT, + "Quit.", + { 0 , 0, NULL }, + NULL, + NULL +}; + +#ifdef EXPORTED_3A +const menuEnrty hold3AmanualSettings = { + KEY_HOLD_EXPORTED_3A, + paramEntry_set, + VCAM_PARAM_EXPORTED_3A_HOLD, + "Start (hold) manual 3A configuration.", + { 0 , 0, NULL }, + NULL, + NULL +}; + +const menuEnrty set3AmanualSettings = { + KEY_SET_EXPORTED_3A, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Set 3A configuration.", + { 0 , 0, NULL }, + NULL, + (void*)( (subMenuFn)startExported3A_Menu ) +}; + +const menuEnrty apply3AmanualSettings = { + KEY_APPLY_EXPORTED_3A, + paramEntry_set, + VCAM_PARAM_EXPORTED_3A_APPLY, + "Apply manual 3A configuration.", + { 0 , 0, NULL }, + NULL, + NULL +}; +#endif // EXPORTED_3A + +const int dispFrameOpts[] = { VCAM_PORT_PREVIEW, VCAM_PORT_VIDEO }; +const char *dispFrameStrings[] = { "Preview port frames" , "Video port frames" }; +const subMenuEnrty dispFrameSubmenu = { dispFrameOpts, dispFrameStrings }; + +const menuEnrty setDispFrame = { + KEY_SET_DISPLAYED_FRM, + functionalEntry, + VCAM_PARAM_MIN, + "Displayed frame.", + { 0 , ARR_SIZE(dispFrameOpts) - 1, NULL }, + &displayedFrame, + (void*)( (subMenuFn)setDislpayableFrame ) +}; + +const menuEnrty setImgPyramid = { + KEY_IMAGE_PYRAMID, + functionalEntry, + VCAM_PARAM_IMAGE_PYRAMID, + "Set Image Pyramid properties. Image pyramid level > 1 will enable this functionality.", + { 0 , 0, NULL }, + NULL, + (void*)( (subMenuFn)setImagePyramid ) +}; + +const menuEnrty *menu[] = +{ + &startPreview, + &stopPreview, + &portUsage, +// &extraData, +// &startExtraDataTransfer, +// &stopExtraDataTransfer, + &extraDataStart, + &extraDataStop, + &brightness, + &contrast, + &sharpness, + &saturation, + &flicker, + &crop, + &frameRate_fixed, + &frameRate_variable, + &captureMode, + &format, + &sensor, + &focus, + &focusManual, + &manualExp, + &expISO_Gain, + &expCompensation, + &expLock, + &awbMode, + &colorTemp, + &awbLock, + &prvRes, + +#if TIME_PROFILE + &dumpTimes, +#endif + + &faceDet, + &getParam, + +#ifndef EXPORTED_3A + &wbGains, + &wbGains_get, + &gammaTbl_test, +#endif // EXPORTED_3A + + &mirroring, + &rotation, + &awbMinDelayTime, + &agcMinDelayTime, + &agcLowTh, + &agcHighTh, + &gestureInfo, + &freezeAGCparams, + &freezeAWBparams, + &stereoLayout, + +#ifdef EXPORTED_3A + &hold3AmanualSettings, + &set3AmanualSettings, + &apply3AmanualSettings, +#endif // EXPORTED_3A + +#ifdef CAP_FRAME + &recordFrame, +#endif // CAP_FRAME + + &setDispFrame, + &setImgPyramid, + + &quit, + NULL +}; + +const menuEnrty ok = { + KEY_QUIT, + neutralEntry, + VCAM_CMD_QUIT, + "OK ( use default if nothing is set )", + { 0 , 0, NULL }, + NULL, + NULL +}; + +const menuEnrty *menu_Primary[] = +{ + &packFrames, + &portUsage, + &format, + &sensor, + &stereoLayout, + &captureMode, + &prvRes, + &ok, + + NULL +}; + +#endif /// __VCAM_TEST_DATA__ diff --git a/source/dvp/VisionCam/VisionCamTestTypes.h b/source/dvp/VisionCam/VisionCamTestTypes.h new file mode 100644 index 0000000..c0c2b58 --- /dev/null +++ b/source/dvp/VisionCam/VisionCamTestTypes.h @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __VCAM_TEST_TYPES__ + +#define __VCAM_TEST_TYPES__ + +#include +#include +#include +#include + +#if !defined(WIN32) && !defined(UNDER_CE) + #include +#endif + +#define ARR_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) + +static int NUM_BUFFERS = 5; +const int NUM_BUFFERS_MAX = 8; + +/** Menu entry used in menuEntries + * value containing the index + * for each menu option + */ +typedef int entryIndex; + +/** entryKey is used to specify + * which string must be entered + * to invoke a proper command + */ +typedef const char * entryKey; + +/** subMenuFn - pointer to a void function(void*) + * This may be used for some menu functionalities + * that need more complicated actions + * than just sending a command and etc. + */ +typedef void (* subMenuFn)( void * ); + +typedef enum{ + neutralEntry, + commandEntry, + paramEntry_set, + paramEntry_get, + functionalEntry, + + entryMax +}entryType; + +/** Structure defining the allocated buffers. + * + */ +struct bufferProperties{ + int previewLength; + unsigned int *previewBufs[ NUM_BUFFERS_MAX ]; + unsigned int * previewOffsets[ NUM_BUFFERS_MAX ]; +}; + +/** Struct that will contain + * values, meaningful for given setting + * but outside of its defunition values + * @param array containing exeption values + * @param should equals size of the array + * pointed by values + */ +struct exeptionValues{ + const int *values; + const int numValues; +}; +/* Structure that will help validating values entered. + * + */ +struct definitionValues{ + int min; + int max; + const exeptionValues *exeptions; +}; + +/* Structure defining a submenu entry. + * Only non scalar options ( enumerated ) + * will need this. + */ +struct subMenuEnrty { + const int * keyValue; + const char ** optString; +}; + +/* Main menu entry type + * + */ +struct menuEnrty { + entryKey menuKey; /// this is the user input + entryType type; /// basicaly - what's this all about + int ID; /// ID of the option, which will be send to GRE component + const char * itemDescriptor; /// string for the main menu + definitionValues defVal; /// gives the range of possible values + void * localValue; /// Saves the last value chosen by user + void *subMenu; /// a sub menu structure, or a pointer to the function that will do the job +}; + +/** + * Prototypes +*/ +module_t initModule(VisionCam ** gCam ); +status_e deinitModule( module_t handle, VisionCam ** gCam ); + +status_e allocPreviewPortBuffers(VisionCam *vCam, uint32_t width, uint32_t height); +void deallocDislayBufers(); + +status_e allocVideoPortBuffers(VisionCam *vCam, uint32_t width, uint32_t height); +void deallocImageBufers(); + +status_e startServices( VisionCam * gCam ); +status_e stopServices( VisionCam * gCam ); + +static void *notificationHandler(VisionCamClientNotifier::VisionCamClientNotificationMsg); + +void setInitialValues( VisionCam * gCam ); +entryIndex Menu( const menuEnrty ** menu ); +entryIndex getEntryIndex( const menuEnrty ** menu , entryKey desc ); +status_e executeEntry( const menuEnrty *choice, VisionCam * gCam ); +bool checkValue( const definitionValues * defVal, int value); +int getValue( const menuEnrty *choice ); + +static void sendBufferTo_V4L(VisionCamFrame *cameraFrame); +static void receiveFramePackage(VisionCamFramePack *pack); +void drawFaceBox(VisionCamFrame *cameraFrame); +int getBytesPerPixel(); +#endif /// __VCAM_TEST_TYPES__ diff --git a/source/dvp/VisionCam/VisionCamTest_3A_Data.h b/source/dvp/VisionCam/VisionCamTest_3A_Data.h new file mode 100644 index 0000000..86006d0 --- /dev/null +++ b/source/dvp/VisionCam/VisionCamTest_3A_Data.h @@ -0,0 +1,636 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _VISION_CAM_TEST_3A_DATA_ +#define _VISION_CAM_TEST_3A_DATA_ + +#include "VisionCamTestTypes.h" +#include + +entryKey KEY_3A_SENSOR_SELECTION = "se"; +entryKey KEY_3A_LSC_2D = "lsc-2d"; +entryKey KEY_3A_CLAMP = "clamp"; +entryKey KEY_3A_GAIN_OFFSET = "gain-offs"; +entryKey KEY_3A_VLDC = "vldc"; +entryKey KEY_3A_NF1 = "nf-1"; +entryKey KEY_3A_NF2 = "nf-2"; +entryKey KEY_3A_GIC = "gic"; +entryKey KEY_3A_WB = "wb"; +entryKey KEY_3A_CFA = "cfa"; +entryKey KEY_3A_GAMMA = "gamma"; +entryKey KEY_3A_RGB_to_RGB_1 = "rgb2rgb-1"; +entryKey KEY_3A_RGB_to_RGB_2 = "rgb2rgb-2"; +entryKey KEY_3A_RGB_to_YUV = "rgb2yuv"; +entryKey KEY_3A_GBCE = "gbce"; +entryKey KEY_3A_YUV_to_YUV = "yuv2yuv"; +entryKey KEY_3A_EE = "edge"; +entryKey KEY_3A_CAR = "car"; +entryKey KEY_3A_LSC = "lsc"; +entryKey KEY_3A_HISTOGRAM = "hist"; +entryKey KEY_3A_BOXCAR = "boxcar"; +entryKey KEY_3A_BSC = "bsc"; +entryKey KEY_3A_3DCC = "3dcc"; +entryKey KEY_3A_DPC_OTF = "dpc-otf"; +entryKey KEY_3A_DPC_LUT = "dpc-lut"; +entryKey KEY_3A_CGS = "cgs"; +entryKey KEY_3A_DFS = "dfs"; +entryKey KEY_3A_DPC_1 = "dpc-1"; +entryKey KEY_3A_DPC_2 = "dpc-2"; +entryKey KEY_3A_DPCM = "dpcm"; +entryKey KEY_3A_HLpf = "h-lpf"; +entryKey KEY_3A_VLpf = "v-lpf"; +entryKey KEY_3A_H3A_AEWB_PARAMS = "h3a-wb"; +entryKey KEY_3A_H3A_AF_PARAMS = "h3a-af"; +entryKey KEY_3A_H3A_COMMON_PARAMS = "h3a-comm"; +entryKey KEY_3A_EXP_GAIN_CONTROL = "exp-ctrl"; +entryKey KEY_3A_ZERO_NEXT = "zero"; +entryKey KEY_3A_QUIT = "q"; + +//typedef const char * fileName_t; + +//fileName_t FILE_3A_LSC_2D = ""; +//fileName_t FILE_3A_CLAMP = ""; +//fileName_t FILE_3A_GAIN_OFFSET = ""; +//fileName_t FILE_3A_VLDC = ""; +//fileName_t FILE_3A_NF1 = ""; +//fileName_t FILE_3A_NF2 = ""; +//fileName_t FILE_3A_GIC = ""; +//fileName_t FILE_3A_WB = ""; +//fileName_t FILE_3A_CFA = ""; +//fileName_t FILE_3A_GAMMA = ""; +//fileName_t FILE_3A_RGB_to_RGB_1 = ""; +//fileName_t FILE_3A_RGB_to_RGB_2 = ""; +//fileName_t FILE_3A_RGB_to_YUV = ""; +//fileName_t FILE_3A_GBCE = ""; +//fileName_t FILE_3A_YUV_to_YUV = ""; +//fileName_t FILE_3A_EE = ""; +//fileName_t FILE_3A_CAR = ""; +//fileName_t FILE_3A_LSC = ""; +//fileName_t FILE_3A_HISTOGRAM = ""; +//fileName_t FILE_3A_BOXCAR = ""; +//fileName_t FILE_3A_BSC = ""; +//fileName_t FILE_3A_3DCC = ""; +//fileName_t FILE_3A_DPC_OTF = ""; +//fileName_t FILE_3A_DPC_LUT = ""; +//fileName_t FILE_3A_CGS = ""; +//fileName_t FILE_3A_DFS = ""; +//fileName_t FILE_3A_DPC_1 = ""; +//fileName_t FILE_3A_DPC_2 = ""; +//fileName_t FILE_3A_HLpf = ""; +//fileName_t FILE_3A_VLpf = ""; +//fileName_t FILE_3A_H3A_AEWB_PARAMS = ""; +//fileName_t FILE_3A_H3A_AF_PARAMS = ""; +//fileName_t FILE_3A_H3A_COMMON_PARAMS = ""; +//fileName_t FILE_3A_EXP_GAIN_CONTROL = ""; + +bool_e getData(void *data, size_t size, const char *testFileName ); +void getData(void*out, void* in, size_t size); + +void man3AsensorFunc(void*); +void lsc2dFunc(void*); +void clampFunc(void*); +void gainOffsetFunc(void *); +void vldcFunc(void*); +void nf1Func(void *); +void nf2Func(void*); +void gicFunc(void *); +void wbFunc(void*); +void cfaFunc(void*); +void gammaFunc(void*); +void rgb2rgb1Func(void*); +void rgb2rgb2Func(void*); +void rgb2yuvFunc(void*); +void gbceFunc(void*); +void yuv2yuvFunc(void*); +void edgeEnhFunc(void*); +void carFunc(void*); +void lscFunc(void*); +void histogramFunc(void*); +void boxcarFunc(void*); +void bscFunc(void*); +void f3DccFunc(void*); +void dpcOtfFunc(void*); +void dpcLutFunc(void*); +void cgsFunc(void*); +void dfsFunc(void*); +void dpc1Func(void*); +void dpc2Func(void*); +void dpcmFunc(void *input); +void horLPFfunc(void*); +void verLPFfunc(void*); +void h3aAFfunc(void*); +void h3aAewbFunc(void*); +void h3aComFunc(void*); +void expGainCtrlFunc(void*); +void zeroAllStructs(void*); + +static VisionCamSensorSelection eSensor = VCAM_SENSOR_PRIMARY; +static VisionCam_3A_2D_LscConfig_t lsc2DCfgLocal; +static VisionCam_3A_Clamp_t clampLocal; +static VisionCam_3A_GainOffset_t gainOffst; +static VisionCam_3A_VDLC_t vldcLocal; +static VisionCam_3A_NoiseFilterConfig_t nf1Local; +static VisionCam_3A_NoiseFilterConfig_t nf2Local; +static VisionCam_3A_GIC_Config_t gicLocal; +static VisionCam_3A_WB_Config_t wbLocal; +static VisionCam_3A_CFA_Config_t cfaLocal; +static VisionCam_3A_GammaTableConfig_t gammaLocal; +static VisionCam_3A_RGB2RGB_t rgb2rgb_1_Local; +static VisionCam_3A_RGB2RGB_t rgb2rgb_2_Local; +static VisionCam_3A_RGB2YUV_t rgb2yuvLocal; +static VisionCam_3A_GBCE_Config_t gbceLocal; +static VisionCam_3A_Yuv444_toYuv422_Config_t yuv2yuvLocal; +static VisionCam_3A_EdgeEnhancement_config_t edgeEnhLocal; +static VisionCam_3A_CAR_config_t carCfgLocal; +static VisionCam_3A_LscConfig_t lscLocal; +static VisionCam_3A_HistogramConfig_t histogramLocal; +static VisionCam_3A_BoxCarConfig_t boxCarLocal; +static VisionCam_3A_BscConfig_t bscCfgLocal; +static VisionCam_3A_3DCC_config_t m3DccLocal; +static VisionCam_3A_DpcOtfConfig_t dpcOtfLocal; +static VisionCam_3A_DPC_Lut_t dpcLutLocal; +static VisionCam_3A_CGS_Config_t cgsLocal; +static VisionCam_3A_DfsConfig_t dfsLocal; +static VisionCam_3A_DpcConfig_t dpc1Local; +static VisionCam_3A_DpcConfig_t dpc2Local; +static VisionCam_3A_DPCM_Config_t dpcmLocal; +static VisionCam_3A_ResizerLowPassFilter_t horizLPFlocal; +static VisionCam_3A_ResizerLowPassFilter_t vertLPFlocal; +static VisionCam_3A_H3A_AutoFocusParam_t h3aAFlocal; +static VisionCam_3A_AEWB_config_t h3aAEWB_Local; +static VisionCam_3A_H3A_CommonConfig_t h3aCommonLocal; +static VisionCam_3A_ExpGainControl_t expGainLocal; +static bool_e bZero = false_e; + +const int man3AsensorSelOpts[] = { + VCAM_SENSOR_PRIMARY, + VCAM_SENSOR_SECONDARY, + VCAM_SENSOR_STEREO, +}; + +const char * man3AsensorSelStrings[] = { + "Primary Sensor", + "Secondary Sensor", + "Stereo Sensors" +}; + +const subMenuEnrty man3AsensorSelSubMenu = { + man3AsensorSelOpts, + man3AsensorSelStrings +}; + +const menuEnrty man3Asensor = { + KEY_3A_SENSOR_SELECTION, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Sensor (on which configurations will be allpied).", + { 0 , ARR_SIZE(man3AsensorSelOpts ) - 1, NULL }, + &eSensor, + (void*)( (subMenuFn)man3AsensorFunc) +}; + +const menuEnrty lsc2D= { + KEY_3A_LSC_2D, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "LSC 2d", + { 0, 0, NULL }, + (void*)&lsc2DCfgLocal, + (void*)( (subMenuFn)lsc2dFunc) +}; + +const menuEnrty clamp= { + KEY_3A_CLAMP, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Clamp", + { 0, 0, NULL }, + (void*)&clampLocal, + (void*)( (subMenuFn)clampFunc) +}; + +const menuEnrty gainOffset = { + KEY_3A_GAIN_OFFSET, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Gain Offset", + { 0, 0, NULL }, + (void*)&gainOffst, + (void*)( (subMenuFn)gainOffsetFunc) +}; + +const menuEnrty vldc = { + KEY_3A_VLDC, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "VLDC", + { 0, 0, NULL }, + (void*)&vldcLocal, + (void*)( (subMenuFn)vldcFunc) +}; + +const menuEnrty nf1 = { + KEY_3A_NF1, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Noise Filter 1", + { 0, 0, NULL }, + (void*)&nf1Local, + (void*)( (subMenuFn)nf1Func) +}; + +const menuEnrty nf2 = { + KEY_3A_NF2, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Noise Filter 2", + { 0, 0, NULL }, + (void*)&nf2Local, + (void*)( (subMenuFn)nf2Func) +}; + +const menuEnrty gic = { + KEY_3A_GIC, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Gic", + { 0, 0, NULL }, + (void*)&gicLocal, + (void*)( (subMenuFn)gicFunc) +}; + +const menuEnrty wb = { + KEY_3A_WB, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "White Balance", + { 0, 0, NULL }, + (void*)&wbLocal, + (void*)( (subMenuFn)wbFunc) +}; + +const int cfaOpts[] = { + VCAM_IPIPE_CFA_MODE_2DIR, + VCAM_IPIPE_CFA_MODE_2DIR_DA, + VCAM_IPIPE_CFA_MODE_DAA +}; + +const char * cfaStrings[] = { + "2DIR mode", + "2DIR \"DA\" mode", + "DAA mode" +}; + +const subMenuEnrty cfaSubMenu = { + cfaOpts, + cfaStrings +}; + +const menuEnrty cfa = { + KEY_3A_CFA, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "CFA", + { 0, ARR_SIZE(cfaOpts), NULL }, + (void*)&cfaLocal, + (void*)( (subMenuFn)cfaFunc) +}; + +const menuEnrty manualGamma = { + KEY_3A_GAMMA, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Gamma Table", + { 0, 0, NULL }, + (void*)&gammaLocal, + (void*)( (subMenuFn)gammaFunc) +}; + +const menuEnrty rgb2rgb_1 = { + KEY_3A_RGB_to_RGB_1, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "RGB 2 RGB matrix 1", + { 0, 0, NULL }, + (void*)&rgb2rgb_1_Local, + (void*)( (subMenuFn)rgb2rgb1Func) +}; + +const menuEnrty rgb2rgb_2 = { + KEY_3A_RGB_to_RGB_2, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "RGB 2 RGB matrix 2", + { 0, 0, NULL }, + (void*)&rgb2rgb_2_Local, + (void*)( (subMenuFn)rgb2rgb2Func) +}; + +const menuEnrty rgb2yuv = { + KEY_3A_RGB_to_YUV, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "RGB 2 YUV", + { 0, 0, NULL }, + (void*)&rgb2yuvLocal, + (void*)( (subMenuFn)rgb2yuvFunc) +}; + +const menuEnrty gbce = { + KEY_3A_GBCE, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "GBCE", + { 0, 0, NULL }, + (void*)&gbceLocal, + (void*)( (subMenuFn)gbceFunc) +}; + +const menuEnrty yuv2yuv = { + KEY_3A_YUV_to_YUV, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "yuv 2 yuv matrix", + { 0, 0, NULL }, + (void*)&yuv2yuvLocal, + (void*)( (subMenuFn)yuv2yuvFunc) +}; + +const menuEnrty edgeEnh = { + KEY_3A_EE, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Edge Enhancement Method", + { 0, 0, NULL }, + (void *)&edgeEnhLocal, + (void*)( (subMenuFn)edgeEnhFunc) +}; + +const menuEnrty car = { + KEY_3A_CAR, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Car", + { 0, 0, NULL }, + (void*)&carCfgLocal, + (void*)( (subMenuFn)carFunc) +}; + +const menuEnrty lsc = { + KEY_3A_LSC, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Lens Shading Correction", + { 0, 0, NULL }, + (void*)&lscLocal, + (void*)( (subMenuFn)lscFunc) +}; + +const menuEnrty histogram = { + KEY_3A_HISTOGRAM, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Histogram", + { 0, 0, NULL }, + (void*)&histogramLocal, + (void*)( (subMenuFn)histogramFunc) +}; + +const menuEnrty boxCar = { + KEY_3A_BOXCAR, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Boxcar", + { 0, 0, NULL }, + (void*)&boxCarLocal, + (void*)( (subMenuFn)boxcarFunc) +}; + +const menuEnrty bsc = { + KEY_3A_BSC, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Bsc", + { 0, 0, NULL }, + (void*)&bscCfgLocal, + (void*)( (subMenuFn)bscFunc) +}; + +const menuEnrty m3Dcc = { + KEY_3A_3DCC, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "3D cc", + { 0, 0, NULL }, + (void*)&m3DccLocal, + (void*)( (subMenuFn)f3DccFunc) +}; + +const menuEnrty dpcOtf = { + KEY_3A_DPC_OTF, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "DPC Otf", + { 0, 0, NULL }, + (void*)&dpcOtfLocal, + (void*)( (subMenuFn)dpcOtfFunc) +}; + +const menuEnrty dpcLut = { + KEY_3A_DPC_LUT, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "DPC Lut", + { 0, 0, NULL }, + (void*)&dpcLutLocal, + (void*)( (subMenuFn)dpcLutFunc) +}; + +const menuEnrty cgs = { + KEY_3A_CGS, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "CGS", + { 0, 0, NULL }, + (void*)&cgsLocal, + (void*)( (subMenuFn)cgsFunc) +}; + +const menuEnrty dfs = { + KEY_3A_DFS, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "DFS", + { 0, 0, NULL }, + (void*)&dfsLocal, + (void*)( (subMenuFn)dfsFunc) +}; + +const menuEnrty dpc1 = { + KEY_3A_DPC_1, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "DPC 1", + { 0, 0, NULL }, + (void*)&dpc1Local, + (void*)( (subMenuFn)dpc1Func) +}; + +const menuEnrty dpc2 = { + KEY_3A_DPC_2, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "DPC 2", + { 0, 0, NULL }, + (void*)&dpc2Local, + (void*)( (subMenuFn)dpc2Func) +}; + +const menuEnrty dpcm = { + KEY_3A_DPCM, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "DPCM", + { 0, 0, NULL }, + (void*)&dpcmLocal, + (void*)( (subMenuFn)dpcmFunc) +}; + +const menuEnrty horLPF = { + KEY_3A_HLpf, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Horiz Low Pass Filter", + { 0, 0, NULL }, + (void*)&horizLPFlocal, + (void*)( (subMenuFn)horLPFfunc) +}; + +const menuEnrty verLPF = { + KEY_3A_VLpf, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Vertical Low Pass Filter", + { 0, 0, NULL }, + (void*)&vertLPFlocal, + (void*)( (subMenuFn)verLPFfunc) +}; + +const menuEnrty h3aAF = { + KEY_3A_H3A_AF_PARAMS, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "H3a AF params", + { 0, 0, NULL }, + (void*)&h3aAFlocal, + (void*)( (subMenuFn)h3aAFfunc) +}; + +const menuEnrty h3aAewb = { + KEY_3A_H3A_AEWB_PARAMS, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "H3a AEWB params", + { 0, 0, NULL }, + (void*)&h3aAEWB_Local, + (void*)( (subMenuFn)h3aAewbFunc) +}; + +const menuEnrty h3aCom = { + KEY_3A_H3A_COMMON_PARAMS, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "H3a common params", + { 0, 0, NULL }, + (void*)&h3aCommonLocal, + (void*)( (subMenuFn)h3aComFunc) +}; + +const menuEnrty expGainCtrl = { + KEY_3A_EXP_GAIN_CONTROL, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Exposure & Gain Control", + { 0, 0, NULL }, + (void*)&expGainLocal, + (void*)( (subMenuFn)expGainCtrlFunc) +}; + +const menuEnrty zeroStructs = { + KEY_3A_ZERO_NEXT, + functionalEntry, + VCAM_PARAM_EXPORTED_3A_SET, + "Zero/Unzero Next Values", + { 0, 0, NULL }, + (void*)&bZero, + (void*)( (subMenuFn)zeroAllStructs) +}; + +/// Used to exit Manual 3A submenu and return to main test app menu. +const menuEnrty quit = { + KEY_3A_QUIT, + neutralEntry, + VCAM_CMD_QUIT, + "Quit.", + { 0 , 0, NULL }, + NULL, + NULL +}; + +const menuEnrty * MenuManual3A[] = { + &man3Asensor, + &lsc2D, + &clamp, + &gainOffset, + &vldc, + &nf1, + &nf2, + &gic, + &wb, + &cfa, + &manualGamma, + &rgb2rgb_1, + &rgb2rgb_2, + &rgb2yuv, + &gbce, + &yuv2yuv, + &edgeEnh, + &car, + &lsc, + &histogram, + &boxCar, + &bsc, + &m3Dcc, + &dpcOtf, + &dpcLut, + &cgs, + &dfs, + &dpc1, + &dpc2, + &dpcm, + &horLPF, + &verLPF, + &h3aAF, + &h3aAewb, + &h3aCom, + &expGainCtrl, + &zeroStructs, + + &quit, + NULL +}; + +#endif // _VISION_CAM_TEST_3A_DATA_ diff --git a/source/dvp/VisionCam/VisionCamTest_3A_Export.cpp b/source/dvp/VisionCam/VisionCamTest_3A_Export.cpp new file mode 100644 index 0000000..84ac182 --- /dev/null +++ b/source/dvp/VisionCam/VisionCamTest_3A_Export.cpp @@ -0,0 +1,737 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +void startExported3A_Menu( void *input) +{ + VisionCam *vCam = (VisionCam*)input; + entryIndex index = -1; + + if( vCam ) + { + while( 1 ) + { + index = Menu( MenuManual3A ); + if( index == -1 ) + { + continue; + } + + /// 'q' button (quit) is pressed + if( MenuManual3A[ index ]->ID == VCAM_CMD_QUIT ) + { + break; + } + executeEntry( MenuManual3A[ index ] , vCam ); + } + } +} + +void getData(void *out, void *in, size_t size) +{ + if( out && in && size ) + { + if( bZero ) + { + memset(out, 0, size ); + puts("\nZeroing ENABLED !!!"); + } + else + { + puts("\nZeroing DISABLED !!!"); + memcpy(out, in, size ); + } + } +} + +bool_e getData(void *data, size_t size, const char *testFileName ) +{ + bool_e ret = false_e; + + FILE *f = NULL; + f = fopen(testFileName, "rb"); + if( f ) + { + size_t fSize = 0; + fseek(f, 0L, SEEK_END); + fSize = (size_t)ftell(f); + fseek(f, 0L, SEEK_SET); + + if( size == fSize ) + { + fread(data, 1, fSize, f); + ret = true_e; + } + fclose(f); + } + else + { + puts(__FILE__); + printf("ERROR: file %s does not exist ! \n", testFileName); + ret = false_e; + } + + return ret; +} + +void man3AsensorFunc(void *input __attribute__((unused)) ) +{ + int sensorSelOpts[] = { + VCAM_SENSOR_PRIMARY, + VCAM_SENSOR_SECONDARY, + VCAM_SENSOR_STEREO, + }; + + const char * sensorSelStrings[] = { + "Primary Sensor", + "Secondary Sensor", + "Stereo Sensors" + }; + + subMenuEnrty sensorSelSubMenu = { + sensorSelOpts, + sensorSelStrings + }; + + menuEnrty sen; + memcpy(&sen, &man3Asensor, sizeof(menuEnrty)); + sen.subMenu = (void*)&sensorSelSubMenu; + + eSensor = (VisionCamSensorSelection)getValue((const menuEnrty*)&sen); +} + +void lsc2dFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_2D_LscConfig_t*)lsc2D.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_2D_LscConfig_t*)lsc2D.localValue)->m2D_LscConfig), + (void*)&lsc2dDump, + sizeof(VCAM_3ASKIP_ISIF_2DLSC_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Lsc2D; + param.pData = lsc2D.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param) ); +} + +void clampFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_Clamp_t*)(clamp.localValue))->eSensor = eSensor; + getData( &(((VisionCam_3A_Clamp_t*)(clamp.localValue))->mClamp), + (void*)&clampDump, + sizeof(VCAM_3ASKIP_ISIF_CLAMP_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Clamp; + param.pData = clamp.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void gainOffsetFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_GainOffset_t*)(gainOffset.localValue))->eSensor = eSensor; + getData( &(((VisionCam_3A_GainOffset_t*)(gainOffset.localValue))->mGainOffset), + (void*)&gainOffsetDump, + sizeof(VCAM_3ASKIP_ISIF_GAINOFFSET_CFGTYPE) + ); + + param.eParamType = VCAM_3A_GainOffset; + param.pData = gainOffset.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void vldcFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_VDLC_t*)vldc.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_VDLC_t*)vldc.localValue)->mVLDC), + (void*)&vldcDump, + sizeof(VCAM_3ASKIP_ISIF_VLDC_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Vldc; + param.pData = vldc.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void nf1Func(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_NoiseFilterConfig_t*)nf1.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_NoiseFilterConfig_t*)nf1.localValue)->eNoiseFilterConfig), + (void*)&nf1Dump, + sizeof(VCAM_3ASKIP_IPIPE_NOISE_FILTER_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Nf1; + param.pData = nf1.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void nf2Func(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_NoiseFilterConfig_t*)nf2.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_NoiseFilterConfig_t*)nf2.localValue)->eNoiseFilterConfig), + (void*)&nf2Dump, + sizeof(VCAM_3ASKIP_IPIPE_NOISE_FILTER_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Nf2; + param.pData = nf2.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void gicFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_GIC_Config_t*)gic.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_GIC_Config_t*)gic.localValue)->mGIC_config), + (void*)&gicDump, + sizeof(VCAM_3ASKIP_IPIPE_GIC_CFGTYPE) + ); + + param.eParamType = VCAM_3A_GIC; + param.pData = gic.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void wbFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_WB_Config_t*)wb.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_WB_Config_t*)wb.localValue)->eWB_config), + (void*)&wbDump, + sizeof(VCAM_3ASKIP_IPIPE_WB_CFGTYPE) + ); + + param.eParamType = VCAM_3A_WB; + param.pData = wb.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void cfaFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_CFA_mode_t*)cfa.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_CFA_Config_t*)cfa.localValue)->mCFA_config), + (void*)&cfaDump, + sizeof(VCAM_3ASKIP_IPIPE_CFA_CFGTYPE) + ); + + param.eParamType = VCAM_3A_CFA; + param.pData = cfa.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void gammaFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_GammaTableConfig_t*)manualGamma.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_GammaTableConfig_t*)manualGamma.localValue)->mGammaTable), + &gammaDump, + sizeof(VCAM_3ASKIP_IPIPE_GAMMA_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Gamma; + param.pData = manualGamma.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void rgb2rgb1Func(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_RGB2RGB_t*)rgb2rgb_1.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_RGB2RGB_t*)rgb2rgb_1.localValue)->mRGB_config), + &rgb2rgb1Dump, + sizeof(VCAM_3ASKIP_IPIPE_RGBRGB_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Rgb2Rgb1; + param.pData = rgb2rgb_1.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void rgb2rgb2Func(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_RGB2RGB_t*)rgb2rgb_2.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_RGB2RGB_t*)rgb2rgb_2.localValue)->mRGB_config), + &rgb2rgb2Dump, + sizeof(VCAM_3ASKIP_IPIPE_RGBRGB_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Rgb2Rgb2; + param.pData = rgb2rgb_2.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void rgb2yuvFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_RGB2YUV_t*)rgb2yuv.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_RGB2YUV_t*)rgb2yuv.localValue)->mRGB2YUV), + &rgb2yuvDump, + sizeof(VCAM_3ASKIP_IPIPE_RGBYUV_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Rgb2Yuv; + param.pData = rgb2yuv.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void gbceFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_GBCE_Config_t*)gbce.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_GBCE_Config_t*)gbce.localValue)->mGBCE_config), + &gbceDump, + sizeof(VCAM_3ASKIP_IPIPE_GBCE_CFGTYPE) + ); + + param.eParamType = VCAM_3A_GBCE; + param.pData = gbce.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void yuv2yuvFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_Yuv444_toYuv422_Config_t*)yuv2yuv.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_Yuv444_toYuv422_Config_t*)yuv2yuv.localValue)->mYuvToYuv_config), + &yuv2yuvDump, + sizeof(VCAM_3ASKIP_IPIPE_YUV444YUV422_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Yuv2Yuv; + param.pData = yuv2yuv.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void edgeEnhFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_EdgeEnhancement_config_t*)edgeEnh.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_EdgeEnhancement_config_t*)edgeEnh.localValue)->eEdgeEnhConfig), + &edgeEnhDump, + sizeof(VCAM_3ASKIP_IPIPE_EE_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Ee; + param.pData = edgeEnh.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void carFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_CAR_config_t*)car.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_CAR_config_t*)car.localValue)->mCar), + &carDump, + sizeof(VCAM_3ASKIP_IPIPE_CAR_CFGTYPE) + ); + + param.eParamType =VCAM_3A_Car; + param.pData = car.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void lscFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_LscConfig_t*)lsc.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_LscConfig_t*)lsc.localValue)->mLsc), + &lscDump, + sizeof(VCAM_3ASKIP_IPIPE_LSC_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Lsc; + param.pData = lsc.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void histogramFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_HistogramConfig_t*)histogram.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_HistogramConfig_t*)histogram.localValue)->mHistogramConfig), + &histDump, + sizeof(VCAM_3ASKIP_IPIPE_HIST_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Histogram; + param.pData = histogram.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void boxcarFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_BoxCarConfig_t*)boxCar.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_BoxCarConfig_t*)boxCar.localValue)->eBoxCarConfig), + &boxCarDump, + sizeof(VCAM_3ASKIP_IPIPE_BOXCAR_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Boxcar; + param.pData = boxCar.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void bscFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_BscConfig_t*)bsc.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_BscConfig_t*)bsc.localValue)->mBscConfig), + &bscDump, + sizeof(VCAM_3ASKIP_IPIPE_BSC_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Bsc; + param.pData = bsc.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void f3DccFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_3DCC_config_t*)m3Dcc.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_3DCC_config_t*)m3Dcc.localValue)->m3dccConfig), + &t3dccDump, + sizeof(VCAM_3ASKIP_IPIPE_3DCC_CFGTYPE) + ); + + param.eParamType = VCAM_3A_3Dcc; + param.pData = m3Dcc.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void dpcOtfFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; +{ + dpcOtfDump.nEnable = 0; + dpcOtfDump.eType = (VCAM_3ASKIP_IPIPE_DPC_OTFTYPE)1; + dpcOtfDump.eAlgo = (VCAM_3ASKIP_IPIPE_DPC_ALGOTYPE)1; + dpcOtfDump.tDpcData.tDpc2Params.thr_cor_r = 8; + dpcOtfDump.tDpcData.tDpc2Params.thr_cor_gr = 8; + dpcOtfDump.tDpcData.tDpc2Params.thr_cor_gb = 8; + dpcOtfDump.tDpcData.tDpc2Params.thr_cor_b = 8; + dpcOtfDump.tDpcData.tDpc2Params.thr_det_r = 8; + dpcOtfDump.tDpcData.tDpc2Params.thr_det_gr = 8; + dpcOtfDump.tDpcData.tDpc2Params.thr_det_gb = 8; + dpcOtfDump.tDpcData.tDpc2Params.thr_det_b = 8; + dpcOtfDump.tDpcData.tDpc3Params.eShift = 1; + dpcOtfDump.tDpcData.tDpc3Params.eOtfCorr.nDThr = 8; + dpcOtfDump.tDpcData.tDpc3Params.eOtfCorr.nDSlp = 8; + dpcOtfDump.tDpcData.tDpc3Params.eOtfCorr.nDMin = 8; + dpcOtfDump.tDpcData.tDpc3Params.eOtfCorr.nDMax = 8; + dpcOtfDump.tDpcData.tDpc3Params.eOtfDett.nDThr = 8; + dpcOtfDump.tDpcData.tDpc3Params.eOtfDett.nDSlp = 8; + dpcOtfDump.tDpcData.tDpc3Params.eOtfDett.nDMin = 8; + dpcOtfDump.tDpcData.tDpc3Params.eOtfDett.nDMax = 8; +} + ((VisionCam_3A_DpcOtfConfig_t*)dpcOtf.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_DpcOtfConfig_t*)dpcOtf.localValue)->mDPC), + &dpcOtfDump, + sizeof(VCAM_3ASKIP_IPIPE_DPCOTF_CFGTYPE) + ); + + param.eParamType = VCAM_3A_DpcOtf; + param.pData = dpcOtf.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void dpcLutFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_DPC_Lut_t*)dpcLut.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_DPC_Lut_t*)dpcLut.localValue)->mDPC_lut), + &dpcLutDump, + sizeof(VCAM_3ASKIP_IPIPE_DPCLUT_CFGTYPE) + ); + + param.eParamType = VCAM_3A_DpcLut; + param.pData = dpcLut.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void cgsFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_CGS_Config_t*)cgs.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_CGS_Config_t*)cgs.localValue)->mCgs), + &cgsDump, + sizeof(VCAM_3ASKIP_IPIPE_CGS_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Cgs; + param.pData = cgs.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void dfsFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_DfsConfig_t*)dfs.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_DfsConfig_t*)dfs.localValue)->mDfsConfig), + &dfsDump, + sizeof(VCAM_3ASKIP_IPIPEIF_DFS_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Dfs; + param.pData = dfs.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void dpc1Func(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_DpcConfig_t*)dpc1.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_DpcConfig_t*)dpc1.localValue)->mDpcConfig), + &dpc1Dump, + sizeof(VCAM_3ASKIP_IPIPEIF_DPC_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Dpc1; + param.pData = dpc1.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void dpc2Func(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_DpcConfig_t*)dpc2.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_DpcConfig_t*)dpc2.localValue)->mDpcConfig), + &dpc2Dump, + sizeof(VCAM_3ASKIP_IPIPEIF_DPC_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Dpc2; + param.pData = dpc2.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void dpcmFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_DPCM_Config_t*)dpcm.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_DPCM_Config_t*)dpcm.localValue)->mDPCM), + &dpcmDump, + sizeof(VCAM_3ASKIP_IPIPEIF_DPCM_CFGTYPE) + ); + + param.eParamType = VCAM_3A_Dpcm; + param.pData = dpcm.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void horLPFfunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_ResizerLowPassFilter_t*)horLPF.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_ResizerLowPassFilter_t*)horLPF.localValue)->mRszLpfConfig), + &hlpfDump, + sizeof(VCAM_3ASKIP_RSZ_LPF_CFGTYPE) + ); + + param.eParamType = VCAM_3A_HLpf; + param.pData = horLPF.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void verLPFfunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_ResizerLowPassFilter_t*)verLPF.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_ResizerLowPassFilter_t*)verLPF.localValue)->mRszLpfConfig), + &vlpDump, + sizeof(VCAM_3ASKIP_RSZ_LPF_CFGTYPE) + ); + + param.eParamType = VCAM_3A_VLpf; + param.pData = verLPF.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void h3aAFfunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_H3A_AutoFocusParam_t*)h3aAF.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_H3A_AutoFocusParam_t*)h3aAF.localValue)->mH3A_AutoFocusParam), + &h3aAfDump, + sizeof(VCAM_3ASKIP_H3A_AF_PARAMTYPE) + ); + + param.eParamType = VCAM_3A_H3aAfParams; + param.pData = h3aAF.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void h3aAewbFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_AEWB_config_t*)h3aAewb.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_AEWB_config_t*)h3aAewb.localValue)->mAEWB_config), + &h3aAewbDump, + sizeof(VCAM_3ASKIP_H3A_AEWB_PARAMTYPE) + ); + + param.eParamType = VCAM_3A_H3aAewbParams; + param.pData = h3aAewb.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void h3aComFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_H3A_CommonConfig_t*)h3aCom.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_H3A_CommonConfig_t*)h3aCom.localValue)->mH3A_CommonConfig), + &h3aCommonDump, + sizeof(VCAM_3ASKIP_H3A_COMMON_CFGTYPE) + ); + + param.eParamType = VCAM_3A_H3aCommonParams; + param.pData = h3aCom.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void expGainCtrlFunc(void *input) +{ + VisionCam *vCam = (VisionCam*)input; + VisionCam_3Asettings_Base_t param; + + ((VisionCam_3A_ExpGainControl_t*)expGainCtrl.localValue)->eSensor = eSensor; + getData( &(((VisionCam_3A_ExpGainControl_t*)expGainCtrl.localValue)->mExpGainControl), + &expCtrlDump, + sizeof(VCAM_3ASKIP_CAM_CONTROL_EXPGAINTYPE) + ); + + param.eParamType = VCAM_3A_CamControlExpGain; + param.pData = expGainCtrl.localValue; + + vCam->setParameter(VCAM_PARAM_EXPORTED_3A_SET, (void*)¶m, sizeof(param)); +} + +void zeroAllStructs( void* input __attribute__((unused)) ) +{ + bZero = (bool_e)!bZero; +} diff --git a/source/dvp/VisionCam/VisionCamUtils.cpp b/source/dvp/VisionCam/VisionCamUtils.cpp new file mode 100644 index 0000000..8af9909 --- /dev/null +++ b/source/dvp/VisionCam/VisionCamUtils.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +void flushList(list_t *list ) +{ + node_t *node = list_pop( list ); + + while( node ) + { + free( (void*)(node->data) ); + free(node); + + node = NULL; + node = list_pop( list ); + } +} + +/** @fn DataBuffer_t::DataBuffer_t(size_t allocSize ) + * Constructor. + * Allocate ION (other allocator) mapped memory. + * + * @param size_t allocSize - required size in bytes. +*/ +DataBuffer_t::DataBuffer_t(size_t allocSize ) +{ +#ifndef DVP_USE_ION + pData = calloc(1, allocSize); + if ( pData) + nBuffSize = allocSize; + bytesWritten = 0; +#else // DVP_USE_ION + + mutex_init(&mBuffLock); + + pAllocator = allocator_init(); + if( pAllocator ) + { + dims[0].img.bpp = 1; + dims[0].img.width = allocSize; + dims[0].img.height = 1; + dims[0].dim.x = allocSize; + dims[0].dim.y = 1; + dims[0].dim.z = 1; + + memset((void*)handles, 0, sizeof(handles)); + + if( false_e == allocator_calloc( pAllocator, ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED, 1, + 1, dims, &pData, handles, &strides ) ) + { + pData = NULL; + } + + if ( pData ) + nBuffSize = allocSize; + else + nBuffSize = 0; + + bytesWritten = 0; + } +#endif // DVP_USE_ION +} + +/** @fn DataBuffer_t::~DataBuffer_t() +*/ +DataBuffer_t::~DataBuffer_t() +{ + + mutex_deinit(&mBuffLock); + +#ifndef DVP_USE_ION + FREE_IF_PRESENT( pData ) +#else + allocator_free(pAllocator, ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED, 1, &pData, handles); + allocator_deinit(&pAllocator); +#endif // DVP_USE_ION +} + +/** @fn void *DataBuffer_t::getData() + * Return the user-side address of allocated buffer. +*/ +void *DataBuffer_t::getData() +{ + SOSAL::AutoLock lock( &mBuffLock ); + return pData; +} + +/** @fn size_t DataBuffer_t::getSize() + * Returns the size in bytes of allocated memory. +*/ +size_t DataBuffer_t::getSize() +{ + SOSAL::AutoLock lock( &mBuffLock ); + return nBuffSize; +} + +/** @fn status_e DataBuffer_t::push(void* data, size_t size) + * Copies data, pointed by 'data' with a size 'size' to the shared buffer. + * + * @param void *data - the data to be cpied. + * @param size_t size - the size in bytes of this data. +*/ +status_e DataBuffer_t::push(void* data, size_t size) +{ + status_e ret = STATUS_SUCCESS; + + SOSAL::AutoLock lock( &mBuffLock ); + + if( (bytesWritten + size) <= nBuffSize ) + { + memcpy((int8_t*)pData + bytesWritten, data, size); + bytesWritten += size; + } + else + { + ret = STATUS_NO_RESOURCES; + DVP_PRINT(DVP_ZONE_CAM, "Error: DataBuffer_t::push() - requested size is bigger than possible.\n"); + DVP_PRINT(DVP_ZONE_CAM, "Error: DataBuffer_t::push() - requested memcpy of %d bytes, buffer available are %d bytes.\n", + size, (nBuffSize - bytesWritten)); + } + return ret; +} + diff --git a/source/dvp/VisionCam/VisionCamUtils.h b/source/dvp/VisionCam/VisionCamUtils.h new file mode 100644 index 0000000..bd4c58a --- /dev/null +++ b/source/dvp/VisionCam/VisionCamUtils.h @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _VISION_CAM_UTILS_H_ +#define _VISION_CAM_UTILS_H_ + +#ifdef DVP_USE_ION +# include +#endif // DVP_USE_ION + +#include +#include + +#define FREE_IF_PRESENT(data) { if(data) free(data); data = NULL; } + +#ifdef DVP_USE_ION +# define ALLOCATOR_HANDLES_NUM (4) +# define ALLOCATOR_DIMENSIONS (1) +#endif // DVP_USE_ION + +#ifndef here +#define here {printf("=======> VCam Utils - %d <=======\n", __LINE__);fflush(stdout);} +#endif // here + +/** @fn void flushList(list_t *list) + * Flushes a list data. +*/ +void flushList(list_t *list); + +class DataBuffer_t +{ +public: + /** @fn DataBuffer_t::DataBuffer_t(size_t allocSize ) + * Constructor. + * Allocates a data buffers with a given size. + * @param size_t allocSize - the size of the buffer to be allocated. + */ + DataBuffer_t(size_t allocSize ); + ~DataBuffer_t(); + + void *getData(); + + size_t getSize(); + + status_e push(void* data, size_t size); + +private: + /** Locks read-write operations. + */ + mutex_t mBuffLock; + +#ifdef DVP_USE_ION + /** System Shared Mem allocator + */ + allocator_t *pAllocator; + _allocator_dimensions_t dims[ALLOCATOR_DIMENSIONS]; + allocator_dimensions_t strides; + value_t handles[ALLOCATOR_HANDLES_NUM];// = { 0, 0, 0, 0 }; +#endif // DVP_USE_ION + + /** Size of pDate buffer. */ + size_t nBuffSize; + + /** Used for memcpy monitoring */ + size_t bytesWritten; + + /** The buffer for 3A parameters in hardware acceptable format. */ + void *pData; + +private: /// Private Methods + /** @fn DataBuffer_t::DataBuffer_t(){} + * Hide default constructor. + * We want DataBuffer_t variables to be instantiated only with a valid data inside. + */ + DataBuffer_t(){} + + /** Forbid operator=() . outside this class. */ + DataBuffer_t &operator=(DataBuffer_t &sBuff __attribute__ ((unused)) ){return *this;} + DataBuffer_t &operator=(const DataBuffer_t &sBuff __attribute__ ((unused)) ){return *this;} +}; + +/** @class VisionCamExecutionService + * This class provide the ability to register a member function and parameter size against an ID. + * The registered function must be a class member function, and must accept a void* parameter with known size. + * Please take care to avoid collisinos in ID values. +*/ +template class VisionCamExecutionService { +public: + + /** @typedef execFuncPrt_t + * defines a type pointer to a 'Set_3A_*' member to function of 'CookieType' class. + */ + typedef status_e (CookieType::*execFuncPrt_t)(void*); + + /** @struct execListNode_t + * Defines a structure that holds an ID against each Set_3A_* method in this class. + */ + typedef struct _exec_list_node_t_ { + int32_t optIndex; + execFuncPrt_t exec; + size_t dataSize; + void *data; + }execListNode_t; + + /** @fn VisionCamExecutionService(void *cook) + * VisionCamExecutionService constructor. + * + * @param cook the caller class name. + */ + VisionCamExecutionService(void *cook) { + mExecutionDataList = list_create(); + cookie = (CookieType*)cook; + } + + /** @fn ~VisionCamExecutionService() + * VisionCamExecutionService class destructor. + */ + ~VisionCamExecutionService() { + + node_t *node = mExecutionDataList->head; + while( node ) + { + if( ((execListNode_t*)(node->data))->data ) + { + free( ((execListNode_t*)(node->data))->data ); + ((execListNode_t*)(node->data))->data = NULL; + } + node = node->next; + } + + flushList( mExecutionDataList ); + list_destroy(mExecutionDataList); + mExecutionDataList = NULL; + } + + /** @fn bool_e Register(int32_t index, execFuncPrt_t execFunc, size_t dataSize ) + * Registers a class member function against an ID and parameter size. + * + * @param index - integer value used as a key in function pointer list. + * @param execFunc - pointer to a function, with return type status_e and a sigle vaoid* parameter. + * @param dataSize - size of the parameter that this function (pointed by execFunc) accepts. + * @return true_e on success and false_e on failure. + */ + bool_e Register(int32_t index, execFuncPrt_t execFunc, size_t dataSize, void *data = NULL ) + { + bool_e ret = false_e; + node_t *node = (node_t*)calloc(1, sizeof(node_t)); + if( node ) + { + node->data = (value_t)calloc(1, sizeof(execListNode_t)); + if( node->data ) + { + ((execListNode_t*)(node->data))->optIndex = index; + ((execListNode_t*)(node->data))->exec = execFunc; + ((execListNode_t*)(node->data))->dataSize = dataSize; + + if( data && dataSize) + { + ((execListNode_t*)(node->data))->data = calloc(1, dataSize); + memcpy( ((execListNode_t*)(node->data))->data, data, dataSize); + } + + list_push(mExecutionDataList, node); + ret = true_e; + } + } + + return ret; + } + + /** @fn execFuncPrt_t getFunc( int32_t index ) + * retunrs a pointer to a member function that is registered against given ID. + * + * @param index - the ID with which the function is registered. + * @return pointer to a function of type execFuncPrt_t. + */ + execFuncPrt_t getFunc( int32_t index ) + { + execListNode_t *n = getExecNode(index); + if ( n ) return n->exec; + return NULL; + } + + /** @fn execFuncPrt_t getData( int32_t index ) + * retunrs a pointer to a member function that is registered against given ID. + * + * @param index - the ID with which the function is registered. + * @return pointer to a data that must be passed. + */ + void *getData( int32_t index ) + { + execListNode_t *n = getExecNode(index); + if( n ) return n->data; + return NULL; + } + + /** @fn size_t getDataSize( int32_t index ) + * Returns the size of the data that must be passed to a function registered against an ID. + * @param index - the ID with which the function is registered. + * @return the size of the parameter. + */ + size_t getDataSize( int32_t index ) + { + execListNode_t *n = getExecNode(index); + if( n ) return n->dataSize; + return 0; + } + +private: + /** Instance to the caller class. + */ + CookieType *cookie; + + /** list_t *mExecutionDataList + */ + list_t *mExecutionDataList; + + static int nodeCompare(node_t *a, node_t *b) + { + int ret = -1; + if( a && b ) + { + execListNode_t *aa = (execListNode_t*)a->data; + execListNode_t *bb = (execListNode_t*)b->data; + + if( aa && bb ) + { + if( aa->optIndex == bb->optIndex ) ret = 0; + else if( aa->optIndex < bb->optIndex ) ret = -1; + else ret = 1; + } + } + return ret; + } + + /** @fn execListNode_t *getExecNode(int32_t index) + * @return the data structure in which given execution function, stays beside the "index" value. + */ + execListNode_t *getExecNode(int32_t index) + { + execListNode_t execNode = { index, NULL, 0, NULL }; + node_t node = { NULL, NULL, (value_t)&execNode }; + node_t *found = list_search( mExecutionDataList, &node, reinterpret_cast(nodeCompare)); + + return ( found ? (execListNode_t*)(found->data) : NULL); + } +}; + +#endif // _VISION_CAM_UTILS_H_ diff --git a/source/dvp/VisionCam/concerto.mak b/source/dvp/VisionCam/concerto.mak new file mode 100644 index 0000000..027c5eb --- /dev/null +++ b/source/dvp/VisionCam/concerto.mak @@ -0,0 +1,63 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(PRELUDE) +TARGET=vcam +TARGETTYPE=library +CPPSOURCES=VisionCamFactory.cpp CameraEmulator.cpp FileVisionCam.cpp VisionCamFrame.cpp +ifdef UVC_INC + IDIRS+=$(UVC_INC) + CPPSOURCES+=UVCVisionCam.cpp + DEFS+=VCAM_USE_USB +endif +ifdef OMX_ROOT + IDIRS+=$(OMX_INCS) + SYS_SHARED_LIBS+=$(OMX_LIBS) + DEFS+=VCAM_USE_OMX + CPPSOURCES+=OMXVisionCam.cpp +endif +ifneq ($(TARGET_OS),SYSBIOS) + CPPSOURCES+=SocketVisionCam.cpp +endif +DEFS+=$(DVP_DEBUGGING) $(DVP_CPPFLAGS) +include $(FINALE) + +_MODULE=vcam_simple +include $(PRELUDE) +TARGET=vcam_simple +TARGETTYPE=exe +CPPSOURCES=VisionCamSimpleTest.cpp +STATIC_LIBS=vcam sosal cthreaded imgdbg +SHARED_LIBS=dvp +SYS_SHARED_LIBS += $(IPC_LIBS) $(MEM_LIBS) $(OMX_LIBS) $(PLATFORM_LIBS) +ifeq ($(TARGET_OS),LINUX) + STATIC_LIBS+=v4l2 +endif +include $(FINALE) + +ifneq ($(TARGET_OS),SYSBIOS) +_MODULE=vcam_server +include $(PRELUDE) +TARGET=vcam_server +TARGETTYPE=exe +CPPSOURCES=ServerVisionCam.cpp VisionCamServer.cpp +STATIC_LIBS=vcam sosal cthreaded imgdbg +SHARED_LIBS=dvp +SYS_SHARED_LIBS += $(IPC_LIBS) $(MEM_LIBS) $(OMX_LIBS) $(PLATFORM_LIBS) +ifeq ($(TARGET_OS),LINUX) + STATIC_LIBS+=v4l2 +endif +include $(FINALE) +endif + diff --git a/source/dvp/VisionEngine/Android.mk b/source/dvp/VisionEngine/Android.mk new file mode 100644 index 0000000..5ae6df8 --- /dev/null +++ b/source/dvp/VisionEngine/Android.mk @@ -0,0 +1,29 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CPPFLAGS := $(DVP_DEBUGGING) $(DVP_CPPFLAGS) $(DVP_FEATURES) +LOCAL_SRC_FILES := VisionEngine.cpp +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_WHOLE_STATIC_LIBRARIES := libvcam libsosal libimgdbg libcthreaded +ifeq ($(TARGET_ANDROID_VERSION),ICS) +LOCAL_WHOLE_STATIC_LIBRARIES += libanw +endif +LOCAL_MODULE := libVisionEngine +include $(BUILD_STATIC_LIBRARY) + diff --git a/source/dvp/VisionEngine/VisionEngine.cpp b/source/dvp/VisionEngine/VisionEngine.cpp new file mode 100644 index 0000000..4981e4f --- /dev/null +++ b/source/dvp/VisionEngine/VisionEngine.cpp @@ -0,0 +1,1040 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +static void DVP_SectionComplete(void * cookie, DVP_KernelGraph_t * graph, DVP_U32 sectionIndex, DVP_U32 numNodesExecuted) +{ + VisionEngine *pEngine = reinterpret_cast(cookie); + pEngine->GraphSectionComplete(graph, sectionIndex, numNodesExecuted); +} + +static void VisionCamCallback(VisionCamFrame *cameraFrame) +{ + VisionEngine *pEngine = reinterpret_cast(cameraFrame->mCookie); + DVP_PRINT(DVP_ZONE_ENGINE, "Received callback from Camera with frame %p (%p), port %d, width:%d,height:%d\n", cameraFrame, cameraFrame->mFrameBuff, cameraFrame->mFrameSource, cameraFrame->mWidth, cameraFrame->mHeight); + if (pEngine != NULL) { + pEngine->ReceiveImage(cameraFrame); + } else { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! NULL ENGINE!\n"); + } +} + +VisionEngine::VisionEngine() + : CThreaded() +{ + uint32_t width = 640; + uint32_t height = 480; + uint32_t fps = 30; + fourcc_t color = FOURCC_UYVY; + const char *name = "OMX"; + uint32_t numFrames = 0xFFFFFFFF; + m_numPorts = 1; + Constructor(width, height, fps, color, (char*)name, numFrames); +} + +VisionEngine::VisionEngine(uint32_t width, uint32_t height, uint32_t fps, fourcc_t color, char *camName, uint32_t numFrames) + : CThreaded() +{ + Constructor(width, height, fps, color, camName, numFrames); +} + +void VisionEngine::Constructor(uint32_t width, uint32_t height, uint32_t fps, fourcc_t color, char *camName, uint32_t numFrames) +{ + DVP_PRINT(DVP_ZONE_API, "+VisionEngine()\n"); + //m_framequeue = queue_create(4, sizeof(DVP_Image_t *)); + m_framequeue = queue_create(8, sizeof(VisionCamFrame *)); + m_active = false_e; + semaphore_create(&m_engineLock, 1, false_e); + m_camIdx = m_dispIdx = 0; + m_camMin = m_dispMin = 0; + m_camMax = m_dispMax = 1; + m_vidMin = m_vidMax = m_vidIdx = 0; + m_whitemode = VCAM_WHITE_BAL_CONTROL_AUTO; +#if DVP_FLICKER == 60 + m_flicker = FLICKER_60Hz; // AMERICAS, ASIA, and others. + DVP_PRINT(DVP_ZONE_ENGINE,"Antiflickering sets to 60 Hz\n"); +#elif DVP_FLICKER == 50 + m_flicker = FLICKER_50Hz; // EUROPE, Russia, Israel, and others. + DVP_PRINT(DVP_ZONE_ENGINE,"Antiflickering sets to 50 Hz\n"); +#else + m_flicker = FLICKER_AUTO; // AUTOMATIC + DVP_PRINT(DVP_ZONE_ENGINE,"Antiflickering sets to AUTO\n"); +#endif + m_focus = /*VCAM_FOCUS_CONTRO_AUTO_MACRO*/VCAM_FOCUS_CONTROL_AUTO; +#if defined(DUCATI_1_5) || defined(DUCATI_2_0) + m_capmode = VCAM_GESTURE_MODE; +#else +#if defined(__QNX__) + m_capmode = VCAM_VIEWFINDER_MODE; +#else + m_capmode = VCAM_VIDEO_NORMAL; +#endif +#endif +#if defined(SDP) || defined(PLAYBOOK) || defined(PANDA) + m_sensorIndex = VCAM_SENSOR_PRIMARY; +#else // all other platforms + m_sensorIndex = VCAM_SENSOR_SECONDARY; +#endif + m_focusDepth = -1; // this is in steps of milimeters from 0 to 150. + m_processing = false_e; + m_camcallback = VisionCamCallback; + m_capFrames = 0; + m_numFrames = numFrames; + m_pCam = NULL; + memset(&m_graphs, 0, sizeof(DVP_KernelGraph_t)); + m_droppedFrames = 0; + m_display_width = width; + m_display_height = height; + m_display_special = false_e; + m_width = width; + m_height = height; + m_fourcc = color; + m_fps = fps; + strncpy(m_path, "raw", MAX_PATH); // initial value. + strncpy(m_name, camName, MAX_PATH); + if (strncmp(m_name, "OMX", MAX_PATH) == 0) + m_camtype = VISIONCAM_OMX; + else if (strncmp(m_name, "USB", MAX_PATH) == 0) + m_camtype = VISIONCAM_USB; + else if (strncmp(m_name, "SOCKET", MAX_PATH) == 0) + m_camtype = VISIONCAM_SOCKET; + else + m_camtype = VISIONCAM_FILE; + DVP_PRINT(DVP_ZONE_ENGINE, "Using Camera type %d with name %s\n", m_camtype, m_name); + m_camera_rotation = 0; + m_display_rotation = 0; + m_display = NULL; + m_hDVP = 0; + m_pNodes = NULL; + m_numNodes = 0; + m_images = NULL; + m_numImages = 0; + m_imgdbg = NULL; + m_numImgDbg = 0; + m_buffers = NULL; + m_numBuffers = 0; + m_graphs = NULL; + m_numGraphs = 0; + m_display_enabled = false_e; + m_imgdbg_enabled = false_e; + m_face_detect = false_e; + m_face_detect_raw = false_e; + m_focus_delay = 0; + strcpy(m_imgdbg_path, "raw"PATH_DELIM); + DVP_Perf_Clear(&m_capPerf); + event_init(&m_wait, true_e); +#if defined(ANDROID) && (defined(ICS) || defined(JELLYBEAN)) + m_anw = NULL; + m_surface = NULL; + m_window = NULL; +#endif + m_stereo_info.layout = VCAM_STEREO_LAYOUT_TOPBOTTOM; + m_stereo_info.subsampling = 1; + DVP_PRINT(DVP_ZONE_API, "-VisionEngine()\n"); +} + +VisionEngine::~VisionEngine() +{ + StopThread(); + event_deinit(&m_wait); + queue_destroy(m_framequeue); + semaphore_delete(&m_engineLock); +} + +thread_ret_t VisionEngine::RunThread() +{ + thread_ret_t err = 0; + semaphore_wait(&m_engineLock); + m_active = true_e; + status_e status = Engine(); + m_active = false_e; + semaphore_post(&m_engineLock); + event_set(&m_wait); + assign_thread_ret(err, status, status_e); + thread_exit(err); +} + +bool VisionEngine::WaitForCompletion(uint32_t timeout) +{ + if (event_wait(&m_wait, timeout) == true_e) + return true; + else + return false; +} + +bool VisionEngine::Startup() +{ + m_framequeue = queue_reset(m_framequeue); + if (m_framequeue) + return StartThread(this); + else + return false; +} + +/** @note Do not call this directly, it is for the CThreaded class to use */ +void VisionEngine::Shutdown() +{ + m_running = false_e; + queue_pop(m_framequeue); +} + +void VisionEngine::SetCoreCapacity(DVP_Core_e core, DVP_U32 limit) +{ + if (m_hDVP) + { + DVP_SetCoreCapacity(m_hDVP, core, limit); + } +} + +DVP_U32 VisionEngine::GetCoreCapacity(DVP_Core_e core) +{ + if (m_hDVP) + { + return DVP_GetCoreCapacity(m_hDVP, core); + } + return 0; +} + +void VisionEngine::ReceiveImage(VisionCamFrame * cameraFrame) +{ + DVP_PRINT(DVP_ZONE_API, "+ReceiveImage()\n"); + DVP_PerformanceStop(&m_capPerf); + DVP_PRINT(DVP_ZONE_PERF, "Camera avg frame delay is "FMT_RTIMER_T" us ("FMT_RTIMER_T" fps)\n", + m_capPerf.avgTime, ((m_capPerf.avgTime != 0) ? (rtimer_freq()/m_capPerf.avgTime) : 0)); + + if (cameraFrame && m_running) + { + if (queue_write(m_framequeue, false_e, &cameraFrame) == true_e) + { + DVP_PRINT(DVP_ZONE_ENGINE, "ENGINE: Put VisionCamFrame %p into Frame Queue\n", cameraFrame); + } + else + { + DVP_PRINT(DVP_ZONE_WARNING, "WARNING! Dropped Frame from Camera in ReceiveImage!\n"); + Lock(); + if (m_pCam) + m_pCam->returnFrame(cameraFrame); + if (m_numFrames > 0) + { + m_numFrames--; + if (m_numFrames == 0) + { + // wake up listeners and quit the engine + Shutdown(); + } + } + Unlock(); + } + } + else + { + if (m_framequeue) + { + Shutdown(); + } + } + DVP_PerformanceStart(&m_capPerf); +} + +VisionCamFrame *VisionEngine::DequeueImage() +{ + VisionCamFrame *cameraFrame = NULL; + while (queue_length(m_framequeue) > 1) + { + bool_e ret = queue_read(m_framequeue, true_e, &cameraFrame); + DVP_Image_t *pPreviewImage = (DVP_Image_t *)cameraFrame->mFrameBuff; + if (ret == true_e && pPreviewImage) + { + DVP_PRINT(DVP_ZONE_WARNING, "Dropping VisionCamFrame %p Frame:%u\n", cameraFrame, m_droppedFrames); + m_droppedFrames++; + DisplayDrop(pPreviewImage); + if (m_pCam) + m_pCam->returnFrame(cameraFrame); + } + else + { + // We could be trying to pop the thread off the queue + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: Queue Read Failed!\n"); + m_running = false; + break; + } + } + if (m_running == false) + return NULL; + cameraFrame = NULL; + queue_read(m_framequeue, true_e, &cameraFrame); + return cameraFrame; +} + + +status_e VisionEngine::Engine() +{ + VisionCamFrame *cameraFrame = NULL; + status_e status = STATUS_SUCCESS; + DVP_PRINT(DVP_ZONE_API, "+Engine()\n"); + Lock(); + status = GraphSetup(); + Unlock(); + if (status == STATUS_SUCCESS) + { + DVP_PRINT(DVP_ZONE_ENGINE, "Entering Queue Read Loop, this thread will block until data is ready (%s)\n",(m_running?"true":"false")); + while (m_running && status == STATUS_SUCCESS) + { + DVP_PRINT(DVP_ZONE_ENGINE, "Engine Queue Read Loop is alive!\n"); + cameraFrame = DequeueImage(); + if (cameraFrame && cameraFrame->mLength) + { + DVP_PRINT(DVP_ZONE_ENGINE, "Read VisionCamFrame %p from Queue! (SRC:%d IMG:%p TIME:"FMT_INT64_T")\n", cameraFrame, cameraFrame->mFrameSource, cameraFrame->mFrameBuff, cameraFrame->mTimestamp); + + // only increment the frame count when the preview frame comes. + if (cameraFrame->mFrameSource == VCAM_PORT_PREVIEW) + m_capFrames++; + + m_processing = true_e; + status = ProcessImage(cameraFrame); + m_processing = false_e; + Lock(); + // only decrement the frame count when the preview frame comes. + if (cameraFrame->mFrameSource == VCAM_PORT_PREVIEW && m_numFrames > 0) + { + m_numFrames--; + if (m_numFrames == 0) + { + m_running = false_e; + } + DVP_PRINT(DVP_ZONE_ENGINE, "There are %u frames left.\n", m_numFrames); + } + Unlock(); + ReturnCameraFrame(cameraFrame); + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to read from Camera Queue!\n"); + m_running = false_e; + if ((m_camtype == VISIONCAM_FILE) && cameraFrame && (cameraFrame->mLength == 0)) + { + status = STATUS_END_OF_FILE; + } + else + { + status = STATUS_NO_RESOURCES; + } + break; + } + } + } + if (status != STATUS_SUCCESS) + { + DVP_PRINT(DVP_ZONE_ERROR, "Engine Thread quitting prematurely due to error %d\n", status); + } + DVP_PRINT(DVP_ZONE_ENGINE, "Engine Thread is shutting down!\n"); + GraphTeardown(); // locks are inside + DVP_PRINT(DVP_ZONE_API, "-Engine()\n"); + return status; +} + +status_e VisionEngine::CameraInit(void *cookie, fourcc_t color) +{ + VisionCamPortDesc_t single[] = { + {VCAM_PORT_PREVIEW, + m_width, + m_height, + color, + m_fps, + (VisionCamRotation_e)m_camera_rotation, + VCAM_MIRROR_NONE, + m_camMin, + m_camIdx, + m_camMax, + 0, + 0}, + }; + return CameraInit(cookie, single, dimof(single)); +} + +status_e VisionEngine::CameraInit(void *cookie, VisionCamPortDesc_t *desc, uint32_t numDesc, bool_e sendBuffers, bool_e startCam) +{ + status_e status = STATUS_SUCCESS; + uint32_t d = 0; + + while (m_pCam == NULL) + { + DVP_PRINT(DVP_ZONE_ENGINE, "CameraInit: Camera Type %d", m_camtype); + + m_pCam = VisionCamFactory(m_camtype); + if (m_pCam == NULL) { + break; + } + + VCAM_BREAK_IF_FAILED(status, m_pCam->init(cookie)); + VCAM_BREAK_IF_FAILED(status, m_pCam->enablePreviewCbk(m_camcallback)); + for (d = 0; d < numDesc; d++) + { + VCAM_BREAK_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_WIDTH, &desc[d].width, sizeof(uint32_t), desc[d].port)); + VCAM_BREAK_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_HEIGHT, &desc[d].height, sizeof(uint32_t), desc[d].port)); + VCAM_BREAK_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_COLOR_SPACE_FOURCC, &desc[d].color, sizeof(fourcc_t), desc[d].port)); + // Can't set ROTATION here, see below + VCAM_BREAK_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_FPS_FIXED, &desc[d].fps, sizeof(uint32_t), desc[d].port)); + } + if (m_camtype == VISIONCAM_FILE) + { + VCAM_BREAK_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_NAME, m_name, (int32_t)strlen(m_name))); + VCAM_BREAK_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_PATH, m_path, (int32_t)strlen(m_path))); + } + + VCAM_BREAK_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_SENSOR_SELECT, &m_sensorIndex, sizeof(m_sensorIndex))); + VCAM_BREAK_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_CAP_MODE, &m_capmode, sizeof(m_capmode))); + if (m_sensorIndex == VCAM_SENSOR_STEREO) { + for (d = 0; d < numDesc; d++) + { + VCAM_BREAK_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_STEREO_INFO, &m_stereo_info, sizeof(m_stereo_info), desc[d].port)); + } + } + VCAM_BREAK_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_FLICKER,&m_flicker,sizeof(m_flicker))); + + if (m_camtype == VISIONCAM_OMX) + { + for (d = 0; d < numDesc; d++) + { + VisionCamResType res; + VCAM_BREAK_IF_FAILED(status, m_pCam->getParameter(VCAM_PARAM_2DBUFFER_DIM, &res, sizeof(res), desc[d].port)); + desc[d].req_width = res.mWidth; + desc[d].req_height = res.mHeight; + if (sendBuffers && (res.mWidth != desc[d].width || res.mHeight != desc[d].height)) { + DVP_PRINT(DVP_ZONE_ERROR, "VisionCam expects w:%d and h:%d for port:%d!\n", res.mWidth, res.mHeight, desc[d].port); + status = STATUS_FAILURE; + break; + } + } + } + + if (status == STATUS_SUCCESS && sendBuffers) { + status = SendCameraBuffers(desc, numDesc); + if (status == STATUS_SUCCESS && startCam) { + status = StartCamera(); + } + } + } + + if (status != STATUS_SUCCESS) { + DVP_PRINT(DVP_ZONE_ERROR, "VisionCam returned %d over all startup functions!\n", status); + } + + return status; +} + +status_e VisionEngine::SendCameraBuffers(VisionCamPortDesc_t *desc, uint32_t numDesc) +{ + status_e status = STATUS_SUCCESS; + uint32_t d = 0; + int ancillary=VCAM_ANCILLARY_DATA; + int whiteBalanceAuto=VCAM_WHITE_BALANCE; +#if !defined(__QNX__) + int whiteBalanceManual=VCAM_MANUAL_WHITE_BALANCE; +#endif + + VCAM_RETURN_IF_FAILED(status, (m_pCam == NULL) ? STATUS_INVALID_PARAMETER : STATUS_SUCCESS); + for (d = 0; d < numDesc; d++) + { + VCAM_RETURN_IF_FAILED(status, m_pCam->useBuffers(&m_images[desc[d].minIdx], desc[d].maxIdx - desc[d].minIdx, desc[d].port)); + } + // @TODO BUG: Must set rotation after useBuffers + for (d = 0; d < numDesc; d++) + { + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_ROTATION, &desc[d].rotate, sizeof(desc[d].rotate), desc[d].port)); + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_MIRROR, &desc[d].mirror, sizeof(desc[d].mirror), desc[d].port)); + } + if (m_face_detect == true_e) + { + int FaceEnable = 1; + VCAM_RETURN_IF_FAILED(status, m_pCam->sendCommand(VCAM_CMD_FACE_DETECTION, &FaceEnable, sizeof(int))); + } + if (m_face_detect_raw == true_e) + { + int FaceEnable = 1; + VCAM_RETURN_IF_FAILED(status, m_pCam->sendCommand(VCAM_CMD_FACE_DETECTION_RAW, &FaceEnable, sizeof(int))); + } + + DVP_PerformanceStart(&m_capPerf); // we'll time the camera init to first capture + + if (m_imgdbg_enabled) + { + VCAM_RETURN_IF_FAILED(status, m_pCam->sendCommand(VCAM_EXTRA_DATA_START, &ancillary, sizeof(int))); + VCAM_RETURN_IF_FAILED(status, m_pCam->sendCommand(VCAM_EXTRA_DATA_START, &whiteBalanceAuto, sizeof(int))); +#if !defined(__QNX__) + VCAM_RETURN_IF_FAILED(status, m_pCam->sendCommand(VCAM_EXTRA_DATA_START, &whiteBalanceManual, sizeof(int))); +#endif + } + + return status; +} + +status_e VisionEngine::StartCamera() +{ + status_e status = STATUS_SUCCESS; + VCAM_RETURN_IF_FAILED(status, (m_pCam == NULL) ? STATUS_INVALID_PARAMETER : STATUS_SUCCESS); + + // turn on all the ports! + VCAM_RETURN_IF_FAILED(status, m_pCam->sendCommand(VCAM_CMD_PREVIEW_START, NULL, 0, VCAM_PORT_ALL)); + + // CAMERA is now in execute state! + if (m_focus_delay == 0) + { + if (m_focusDepth != -1) { + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_DO_MANUALFOCUS, &m_focusDepth, sizeof(m_focusDepth))); + } else { + //VisionCamFocusMode focus = VCAM_FOCUS_CONTROL_AUTO; + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_DO_AUTOFOCUS, &m_focus, sizeof(m_focus))); + } + } + return status; +} + +status_e VisionEngine::CameraDeinit() +{ + status_e status = STATUS_SUCCESS; + if (m_pCam) + { + // let any camera callbacks finish + DVP_PRINT(DVP_ZONE_ENGINE, "Stopping Camera\n"); + VCAM_COMPLAIN_IF_FAILED(status,m_pCam->sendCommand(VCAM_CMD_PREVIEW_STOP)); + DVP_PRINT(DVP_ZONE_ENGINE, "Destroying Camera\n"); + VCAM_COMPLAIN_IF_FAILED(status,m_pCam->disablePreviewCbk(m_camcallback)); + VCAM_COMPLAIN_IF_FAILED(status,m_pCam->releaseBuffers()); + VCAM_COMPLAIN_IF_FAILED(status,m_pCam->deinit()); + delete m_pCam; + m_pCam = NULL; + DVP_PRINT(DVP_ZONE_ENGINE, "Camera Destroyed\n"); + } + return status; +} + +DVP_U32 VisionEngine::GraphExecute(DVP_KernelGraph_t *graph) +{ + DVP_PRINT(DVP_ZONE_ENGINE, "Executing Kernel Graph %p\n", graph); +#if (DVP_DEBUG == 1) + fflush(stdout); +#endif + return DVP_KernelGraph_Process(m_hDVP, graph, this, DVP_SectionComplete); +} + +status_e VisionEngine::DelayedCameraFocusSetting() +{ + status_e status = STATUS_SUCCESS; + // default to preview port for Focus Controls + if (m_focusDepth == -1) { + //VisionCamFocusMode focus = VCAM_FOCUS_CONTROL_AUTO; + m_pCam->setParameter(VCAM_PARAM_DO_AUTOFOCUS, &m_focus, sizeof(m_focus)); + } else { + m_pCam->setParameter(VCAM_PARAM_DO_MANUALFOCUS, &m_focusDepth, sizeof(m_focusDepth)); + } + return status; +} + +status_e VisionEngine::ProcessImage(VisionCamFrame * cameraFrame) +{ + status_e status = STATUS_INVALID_STATE; + DVP_U32 g, numSections = 0; + + if (m_running == false) + return status; + + status = GraphUpdate(cameraFrame); + if (status == STATUS_SUCCESS) + { + for (g = 0; g < m_numGraphs; g++) + { + if (m_correlation[g].portIdx == VCAM_PORT_ALL || + m_correlation[g].portIdx == cameraFrame->mFrameSource) + { + numSections += GraphExecute(&m_graphs[g]); + } + } + if (m_imgdbg_enabled) + ImageDebug_Write(m_imgdbg, m_numImgDbg); + } + + status = PostProcessImage(cameraFrame, numSections); + + if (status == STATUS_SUCCESS && m_pCam && m_capFrames == m_focus_delay) + { + status = DelayedCameraFocusSetting(); + } + + status = RenderImage(cameraFrame); + + return status; +} + +status_e VisionEngine::PostProcessImage(VisionCamFrame *cameraFrame, uint32_t numSections) +{ + cameraFrame = cameraFrame; // warnings + numSections = numSections; // warnings + DVP_PRINT(DVP_ZONE_ENGINE, "Post Processsing VisionCamFrame %p: %u sections completed in kernel graph\n", cameraFrame, numSections); + return STATUS_SUCCESS; +} + +status_e VisionEngine::ReturnCameraFrame(VisionCamFrame *cameraFrame) +{ + if (m_pCam) + m_pCam->returnFrame(cameraFrame); + return STATUS_SUCCESS; +} + +status_e VisionEngine::RenderImage(VisionCamFrame *cameraFrame __attribute__((unused))) +{ + DisplayRender(&m_images[m_dispIdx]); // by definition, this is the display buffer + return STATUS_SUCCESS; +} + +status_e VisionEngine::GraphTeardown() +{ + uint32_t g = 0; + status_e status = STATUS_SUCCESS; + DVP_PRINT(DVP_ZONE_ENGINE, "DVP Graph Teardown\n"); + status = CameraDeinit(); + Lock(); + + if (m_imgdbg_enabled) + ImageDebug_Close(m_imgdbg, m_numImgDbg); + + for (g = 0; g < m_numGraphs; g++) { + DVP_PrintPerformanceGraph(m_hDVP, &m_graphs[g]); + FreeSections(&m_graphs[g]); + } + FreeGraphs(); + + DVP_PRINT(DVP_ZONE_ENGINE, "Unmapping and Freeing Memory\n"); + + FreeImageDebug(); + FreeNodes(); + FreeImageStructs(); // this will also free display buffers + FreeBufferStructs(); + DisplayDestroy(); + + DVP_PRINT(DVP_ZONE_ENGINE, "Deinitializing DVP\n"); + DVP_KernelGraph_Deinit(m_hDVP); + m_hDVP = 0; + + Unlock(); + return status; +} + +// SUPPORT APIs + +bool VisionEngine::AllocateNodes(uint32_t numNodes) +{ + m_numNodes = numNodes; + m_pNodes = DVP_KernelNode_Alloc(m_hDVP, numNodes); + if (m_pNodes) + { + DVP_PRINT(DVP_ZONE_MEM, "Allocated %u Kernel Node structures in array %p\n", numNodes,m_pNodes); + return true; + } + else + return false; +} + +void VisionEngine::FreeNodes() +{ + DVP_KernelNode_Free(m_hDVP, m_pNodes, m_numNodes); + m_pNodes = NULL; + m_numNodes = 0; +} + +bool VisionEngine::AllocateSections(DVP_KernelGraph_t *graph, uint32_t numSections) +{ + graph->numSections = numSections; + graph->sections = (DVP_KernelGraphSection_t *)calloc(numSections, sizeof(DVP_KernelGraphSection_t)); + graph->order = (DVP_U32 *)calloc(numSections, sizeof(DVP_U32)); + if (graph->sections && graph->order) + { + for (DVP_U32 s = 0; s < numSections; s++) + { + DVP_Perf_t p = DVP_PERF_INIT; + memcpy(&graph->sections[s].perf, &p, sizeof(p)); + } + return true; + } + else + return false; +} + +void VisionEngine::FreeSections(DVP_KernelGraph_t *graph) +{ + free(graph->sections); + free(graph->order); + memset(graph, 0, sizeof(DVP_KernelGraph_t)); +} + +bool VisionEngine::AllocateGraphs(uint32_t numGraphs) +{ + m_numGraphs = numGraphs; + m_graphs = (DVP_KernelGraph_t *)calloc(m_numGraphs, sizeof(DVP_KernelGraph_t)); + m_correlation = (KGraph_Image_Corr_t *)calloc(m_numGraphs, sizeof(KGraph_Image_Corr_t)); + if (m_graphs && m_correlation) + { + uint32_t g; + for (g = 0; g < m_numGraphs; g++) + { + // initialize the performance information + DVP_Perf_t p = DVP_PERF_INIT; + memcpy(&m_graphs[g].totalperf, &p, sizeof(DVP_Perf_t)); + + // initialize the correlation array + m_correlation[g].portIdx = VCAM_PORT_ALL; + } + return true; + } + else + return false; +} + +void VisionEngine::FreeGraphs() +{ + free(m_graphs); + m_graphs = NULL; + m_numGraphs = 0; +} + +bool VisionEngine::AllocateImageStructs(uint32_t numImages) +{ + m_numImages = numImages; + m_images = (DVP_Image_t *)calloc(m_numImages,sizeof(DVP_Image_t)); + if (m_images) + { + DVP_PRINT(DVP_ZONE_MEM, "Allocated %u image structures in array %p\n", numImages,m_images); + return true; + } + else + return false; +} + +void VisionEngine::FreeImageStructs() +{ + if (m_images) + { + for (DVP_U32 i = 0; i < m_numImages; i++) + { + if (m_dispMin <= i && i < m_dispMax && m_display_enabled) + DisplayFree(&m_images[i]); + else + DVP_Image_Free(m_hDVP, &m_images[i]); + DVP_Image_Deinit(&m_images[i]); + } + memset(m_images, 0xEF, m_numImages * sizeof(DVP_Image_t)); + free(m_images); + + m_images = NULL; + m_numImages = 0; + } +} + +bool VisionEngine::AllocateImageDebug(uint32_t numImgDbg) +{ + m_numImgDbg = numImgDbg; + m_imgdbg = (ImageDebug_t *)calloc(m_numImgDbg,sizeof(ImageDebug_t)); + if (m_imgdbg) + { + DVP_PRINT(DVP_ZONE_MEM, "Allocated %u image debugging structures in array %p\n", numImgDbg,m_imgdbg); + return true; + } + else + return false; +} + +void VisionEngine::FreeImageDebug() +{ + if (m_imgdbg && m_imgdbg_enabled) + { + memset(m_imgdbg, 0xEF, m_numImgDbg * sizeof(ImageDebug_t)); + free(m_imgdbg); + m_imgdbg = NULL; + m_numImgDbg = 0; + } +} + +bool VisionEngine::AllocateBufferStructs(uint32_t numBuffers) +{ + m_numBuffers = numBuffers; + m_buffers = (DVP_Buffer_t *)calloc(m_numBuffers,sizeof(DVP_Buffer_t)); + if (m_buffers) + { + DVP_PRINT(DVP_ZONE_MEM, "Allocated %u buffer structures in array %p\n", numBuffers,m_buffers); + return true; + } + else + return false; +} + +void VisionEngine::FreeBufferStructs() +{ + DVP_U32 i = 0; + if (m_buffers) + { + for (i = 0; i < m_numBuffers; i++) + { + DVP_Buffer_Free(m_hDVP, &m_buffers[i]); + DVP_Buffer_Deinit(&m_buffers[i]); + } + if(m_numBuffers) + { + memset(m_buffers, 0xEF, m_numBuffers * sizeof(DVP_Buffer_t)); + free(m_buffers); + } + m_buffers = NULL; + m_numBuffers = 0; + } +} + +bool VisionEngine::DisplayCreate(uint32_t image_width, uint32_t image_height, + uint32_t buffer_width, uint32_t buffer_height, + uint32_t scaled_width, uint32_t scaled_height, + uint32_t crop_top, uint32_t crop_left) +{ + DVP_PRINT(DVP_ZONE_VIDEO, "Creating Display Surfaces!\n"); + if (m_display_special == false_e) + { + m_display = DVP_Display_Create(image_width, image_height, + buffer_width, buffer_height, + m_display_width, m_display_height, + scaled_width, scaled_height, + crop_top, crop_left, + m_fourcc, m_display_rotation, m_dispMax-m_dispMin); + if (m_display) + return true; + else + return false; + } + else + { +#if defined(ANDROID) && (defined(ICS) || defined(JELLYBEAN)) + m_anw = anativewindow_create(m_window); + if (m_anw) + { + if (anativewindow_allocate(m_anw, + buffer_width, buffer_height, + m_dispMax-m_dispMin, + ANW_NV12_FORMAT, true) == false_e) + { + anativewindow_destroy(&m_anw); + } + else + { + anativewindow_set_crop(m_anw, crop_left, crop_top, image_width, image_height); + return true; + } + } + return false; +#endif + } + return false; +} + +bool VisionEngine::DisplayAllocate(DVP_Image_t *pImage) +{ + bool ret = false; + if (m_display_special == false_e) + { + if (DVP_Display_Alloc(m_display, pImage) == DVP_TRUE) + ret = true; + } + else + { +#if defined(ANDROID) && (defined(ICS) || defined(JELLYBEAN)) + uint8_t *ptrs[3] = {NULL, NULL, NULL}; + int32_t stride = 0; + if (anativewindow_acquire(m_anw, &pImage->reserved, ptrs, &stride) == true_e) + { + pImage->y_stride = stride; + pImage->memType = DVP_MTYPE_DISPLAY_2DTILED; +#if defined(GRALLOC_USE_MULTIPLE_POINTERS) + for (uint32_t p = 0; p < pImage->planes; p++) + { + pImage->pBuffer[p] = pImage->pData[p] = ptrs[p]; + } +#else + if (pImage->color == FOURCC_NV12) + { + pImage->pBuffer[0] = pImage->pData[0] = ptrs[0]; + pImage->pBuffer[1] = pImage->pData[1] = &ptrs[0][pImage->y_stride*pImage->bufHeight]; + } +#endif + ret = true; + } +#endif + } + DVP_PrintImage(DVP_ZONE_ENGINE, pImage); + return ret; +} + +/** The convienence call wraps the DVP Display "C" API or uses the ICS special mechanisms */ +void VisionEngine::DisplayFree(DVP_Image_t *pImage) +{ + if (m_display_special == false_e) + { + DVP_Display_Free(m_display, pImage); + } + else + { +#if defined(ANDROID) && (defined(ICS) || defined(JELLYBEAN)) + anativewindow_release(m_anw, pImage->reserved); +#endif + } +} + +/** The convienence call wraps the DVP Display "C" API or uses the ICS special mechanisms */ +void VisionEngine::DisplayDestroy() +{ + if (m_display_enabled) + { + DVP_PRINT(DVP_ZONE_VIDEO, "Deinitializing DVP Display!\n"); + if (m_images) + { + for (m_dispIdx = m_dispMin; m_dispIdx < m_dispMax; m_dispIdx++) + DisplayFree(&m_images[m_dispIdx]); + m_dispMin = 0; + m_dispMax = 0; + } + if (m_display_special == false_e) + { + DVP_Display_Destroy(&m_display); + m_display = NULL; + } + else + { +#if defined(ANDROID) && (defined(ICS) || defined(JELLYBEAN)) + anativewindow_free(m_anw); + anativewindow_destroy(&m_anw); +#endif + } + } +} + +void VisionEngine::DisplayDrop(DVP_Image_t *pImage) +{ + if (pImage && m_display_enabled && m_display_special) + { +#if defined(ANDROID) && (defined(ICS) || defined(JELLYBEAN)) + anativewindow_drop(m_anw, pImage->reserved); + anativewindow_dequeue(m_anw, NULL); +#endif + } +} + +void VisionEngine::DisplayRender(DVP_Image_t *pImage) +{ + static DVP_Image_t *pLast = NULL; + + if (m_display_enabled == true_e) + { + if (pLast != pImage) + { + DVP_PRINT(DVP_ZONE_VIDEO, "Display Rendering Image %p\n", pImage); + if (m_display_special == false_e) + { + DVP_Display_Render(m_display, pImage); + } + else + { +#if defined(ANDROID) && (defined(ICS) || defined(JELLYBEAN)) + anativewindow_enqueue(m_anw, pImage->reserved); + anativewindow_dequeue(m_anw, NULL); +#endif + } + pLast = pImage; + } + else + { + DVP_PRINT(DVP_ZONE_WARNING, "Attempted to redisplay last image %p!\n", pLast); + } + } +} + +#if defined(ANDROID) && (defined(ICS) || defined(JELLYBEAN)) +void VisionEngine::DisplayOnWindow(const sp& binder, const sp& window) +{ + int ret = 0; + Lock(); + // we already have this surface + if (binder == m_surface) { + DVP_PRINT(DVP_ZONE_WARNING, "Setting same window back on VisionEngine!\n"); + goto end; + } + + // the previous run has to stop and a new run has to start if it's currently running now. + ret = semaphore_trywait(&m_engineLock); + if (ret == 0) // engine is active and locked. + { + DVP_PRINT(DVP_ZONE_WARNING, "*******************************\n"); + DVP_PRINT(DVP_ZONE_WARNING, "Restarting VisionEngine Thread!\n"); + DVP_PRINT(DVP_ZONE_WARNING, "*******************************\n"); + Unlock(); + if (StopThread() == false) { + DVP_PRINT(DVP_ZONE_ERROR, "Thread died incorrectly!\n"); + } + m_display_special = true_e; + m_surface = NULL; + m_window = NULL; + queue_unpop(m_framequeue); + DVP_PRINT(DVP_ZONE_ENGINE, "Using new ANativeWindow interface %p!\n", window.get()); + m_surface = binder; + m_window = window; + Startup(); + Lock(); + DVP_PRINT(DVP_ZONE_WARNING, "******************************\n"); + DVP_PRINT(DVP_ZONE_WARNING, "VisionEngine thread restarted!\n"); + DVP_PRINT(DVP_ZONE_WARNING, "******************************\n"); + } + else if (ret == 1) + { + m_display_special = true_e; + DVP_PRINT(DVP_ZONE_ENGINE, "Using new ANativeWindow interface %p!\n", window.get()); + m_surface = binder; + m_window = window; + semaphore_post(&m_engineLock); + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to grab engine lock semaphore!\n"); + } +end: + Unlock(); +} + +void VisionEngine::DisplayOnSurface(const sp& surface) +{ + if (surface != 0) { + DVP_PRINT(DVP_ZONE_ENGINE, "Using Surface\n"); + sp binder(surface->asBinder()); + sp window(surface); + return DisplayOnWindow(binder, window); + } +} + +void VisionEngine::DisplayOnTexture(const sp& texture) +{ + if (texture != 0) { + DVP_PRINT(DVP_ZONE_ENGINE, "Using SurfaceTextureClient\n"); + sp binder(texture->asBinder()); + sp window = new SurfaceTextureClient(texture); + return DisplayOnWindow(binder, window); + } +} +#endif + + diff --git a/source/dvp/VisionEngine/concerto.mak b/source/dvp/VisionEngine/concerto.mak new file mode 100644 index 0000000..4ecc522 --- /dev/null +++ b/source/dvp/VisionEngine/concerto.mak @@ -0,0 +1,22 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(PRELUDE) +TARGET=VisionEngine +TARGETTYPE=library +DEFS+=$(DVP_FEATURES) +IDIRS+=$(DVP_INC) +CPPSOURCES=VisionEngine.cpp +include $(FINALE) + diff --git a/source/dvp/dvp_demo/Android.mk b/source/dvp/dvp_demo/Android.mk new file mode 100644 index 0000000..4714e28 --- /dev/null +++ b/source/dvp/dvp_demo/Android.mk @@ -0,0 +1,28 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH:=$(call my-dir) +# A Simple Demo of DVP with VCam as an Image Source and V4L2 output +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CPPFLAGS := $(DVP_DEBUGGING) $(DVP_CPPFLAGS) $(DVP_FEATURES) +LOCAL_SRC_FILES := dvp_demo.cpp +LOCAL_C_INCLUDES := $(DVP_INCLUDES) +LOCAL_SHARED_LIBRARIES:= libdl $(DVP_SYSLIBS) libOMX_Core libcutils libutils libdvp +LOCAL_STATIC_LIBRARIES := libvcam libsosal libcthreaded +LOCAL_MODULE := dvp_demo +include $(BUILD_EXECUTABLE) + diff --git a/source/dvp/dvp_demo/concerto.mak b/source/dvp/dvp_demo/concerto.mak new file mode 100644 index 0000000..27a264e --- /dev/null +++ b/source/dvp/dvp_demo/concerto.mak @@ -0,0 +1,28 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(PRELUDE) +TARGET=dvp_demo +TARGETTYPE=exe +DEFS+=$(DVP_FEATURES) +IDIRS+=$(DVP_INC) +CPPSOURCES=dvp_demo.cpp +STATIC_LIBS+=sosal imgdbg vcam cthreaded +SHARED_LIBS+=dvp +SYS_SHARED_LIBS += $(IPC_LIBS) $(MEM_LIBS) $(OMX_LIBS) $(PLATFORM_LIBS) +ifeq ($(TARGET_OS),LINUX) + STATIC_LIBS+=v4l2 +endif +include $(FINALE) + diff --git a/source/dvp/dvp_demo/dvp_demo.cpp b/source/dvp/dvp_demo/dvp_demo.cpp new file mode 100644 index 0000000..4de0d77 --- /dev/null +++ b/source/dvp/dvp_demo/dvp_demo.cpp @@ -0,0 +1,653 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief This is a complex example of how to use DVP to do vision processing + * into a series of display buffers previewed on the dvp_display subsystem. + * \author Erik Rainey + */ + +#if defined(DVP_USE_IMGLIB) +#include +#endif +#if defined(DVP_USE_VLIB) +#include +#endif +#include +#include + +#if defined(PC) +#define DVP_DEMO_MAX_TIMEOUTS (10000) +#else +#define DVP_DEMO_MAX_TIMEOUTS (10) +#endif + +typedef struct _dvp_demo_t { +#ifdef VCAM_AS_SHARED + module_t mod; +#endif + uint32_t numDisplayImages; + VisionCamFactory_f factory; + VisionCam *pCam; + queue_t *frameq; + dvp_display_t *dvpd; + DVP_Image_t *displays; /**< Buffers from the DVP Display */ + DVP_Image_t *subImages; /**< Subsections of the Display Image */ + DVP_Image_t *camImages; /**< GCam Images */ + DVP_Image_t *images; /**< DVP Graph Images */ + DVP_Handle dvp; + DVP_KernelNode_t *nodes; /**< The Kernel Graph Nodes */ + DVP_KernelGraph_t *graph; + uint32_t numNodes; +} DVP_Demo_t; + +void DVPCallback(void *cookie, DVP_KernelGraph_t *graph, DVP_U32 sectionIndex, DVP_U32 numNodesExecuted) +{ + cookie = cookie; // warnings + graph = graph; // warnings + sectionIndex = sectionIndex; // warnings + numNodesExecuted = numNodesExecuted; // warnings + DVP_PRINT(DVP_ZONE_ALWAYS, "Cookie %p Graph %p Graph Section %u Completed %u nodes\n", cookie, graph, sectionIndex, numNodesExecuted); +} + +void VisionCamCallback(VisionCamFrame * cameraFrame) +{ + DVP_Image_t *pImage = (DVP_Image_t *)cameraFrame->mFrameBuff; + queue_t *frameq = (queue_t *)cameraFrame->mCookie; + + DVP_PRINT(DVP_ZONE_CAM, "Writing Frame %p into Queue %p\n", cameraFrame, frameq); + DVP_PrintImage(DVP_ZONE_CAM, pImage); + if (queue_write(frameq, true_e, &cameraFrame) == false_e) + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to write frame to queue\n"); + } +} + +bool_e VisionCamInit(DVP_Demo_t *demo, VisionCam_e camType, uint32_t width, uint32_t height, uint32_t fps, uint32_t rotation, uint32_t color) +{ + int32_t ret = 0; +#ifdef VCAM_AS_SHARED + demo->mod = module_load(CAMERA_NAME); + if (demo->mod) + { + demo->factory = (VisionCamFactory_f)module_symbol(demo->mod, "VisionCamFactory"); + if (demo->factory) + { + demo->pCam = demo->factory(VISIONCAM_OMX); + if (demo->pCam) + { +#else + demo->pCam = VisionCamFactory(camType); + if (demo->pCam) + { +#endif + VisionCamSensorSelection sensorIndex = VCAM_SENSOR_SECONDARY; +#if defined(DUCATI_1_5) || defined(DUCATI_2_0) + VisionCamCaptureMode capmode = VCAM_GESTURE_MODE; +#else + VisionCamCaptureMode capmode = VCAM_VIDEO_NORMAL; +#endif + VisionCamFlickerType flicker = FLICKER_60Hz; + VisionCamFocusMode focus = VCAM_FOCUS_CONTROL_AUTO; + VisionCamWhiteBalType white = VCAM_WHITE_BAL_CONTROL_AUTO; + int32_t brightness = 50; + + // initialize the VisionCam + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->init(demo->frameq)); + + // configure the parameters + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->setParameter(VCAM_PARAM_WIDTH, &width, sizeof(width))); + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->setParameter(VCAM_PARAM_HEIGHT, &height, sizeof(height))); + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->setParameter(VCAM_PARAM_COLOR_SPACE_FOURCC, &color, sizeof(color))); + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->setParameter(VCAM_PARAM_CAP_MODE, &capmode, sizeof(capmode))); + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->setParameter(VCAM_PARAM_SENSOR_SELECT, &sensorIndex, sizeof(sensorIndex))); + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->setParameter(VCAM_PARAM_FPS_FIXED, &fps, sizeof(fps))); + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->setParameter(VCAM_PARAM_FLICKER, &flicker, sizeof(flicker))); + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->setParameter(VCAM_PARAM_BRIGHTNESS, &brightness, sizeof(brightness))); + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->setParameter(VCAM_PARAM_AWB_MODE, &white, sizeof(white))); + + // configure the buffers (the first X images are for the camera) + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->useBuffers(demo->camImages, demo->numDisplayImages)); + + // @todo BUG: Can't set rotation until after useBuffers + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->setParameter(VCAM_PARAM_ROTATION, &rotation, sizeof(rotation))); + + // register the callback + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->enablePreviewCbk(VisionCamCallback)); + + // start the preview + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->sendCommand(VCAM_CMD_PREVIEW_START)); + + // do the autofocus + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->setParameter(VCAM_PARAM_DO_AUTOFOCUS, &focus, sizeof(focus))); + + return true_e; + } + +#ifdef VCAM_AS_SHARED + } + } + } +#endif + return false_e; +} + +bool_e VisionCamDeinit(DVP_Demo_t *demo) +{ + int32_t ret = 0; + if (demo->pCam) + { + // destroy the camera + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->sendCommand(VCAM_CMD_PREVIEW_STOP)); + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->disablePreviewCbk(VisionCamCallback)); + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->releaseBuffers()); + VCAM_COMPLAIN_IF_FAILED(ret, demo->pCam->deinit()); + delete demo->pCam; + demo->pCam = NULL; + } +#ifdef VCAM_AS_SHARED + module_unload(demo->mod); +#endif + if (ret != 0) + return false_e; + else + return true_e; +} + +bool_e SubsectionImage(DVP_Image_t *dispFrame, DVP_Image_t *image, uint32_t index) +{ + if (dispFrame->planes == image->planes && + dispFrame->color == image->color) + { + uint32_t limit_i = dispFrame->width / image->width; + uint32_t limit_j = dispFrame->height / image->height; + uint32_t i = index % limit_i; + uint32_t j = index / limit_i; + + DVP_PRINT(DVP_ZONE_ALWAYS, "Requested Index %u in Image of {%u,%u} (%ux%u => %ux%u)\n",index, i,j, dispFrame->width, dispFrame->height, image->width, image->height); + DVP_PrintImage(DVP_ZONE_ALWAYS, dispFrame); + if (j > limit_j) + return false_e; + else + { + uint32_t p = 0; + + // make sure th strides are transfered. + image->y_stride = dispFrame->y_stride; + + // create each subimage plane from the display frame. + for (p = 0; p < dispFrame->planes; p++) + { + uint32_t k = (j * (image->height * dispFrame->y_stride)) + + (i * (image->width * dispFrame->x_stride)); + image->pData[p] = &dispFrame->pData[p][k]; + image->pBuffer[p] = &dispFrame->pData[p][k]; + DVP_PrintImage(DVP_ZONE_ALWAYS, image); + } + return true_e; + } + } + else + return false_e; +} + +int main(int argc, char *argv[]) +{ + int ret = 0; +#if (defined(DVP_USE_VLIB) || defined(DVP_USE_YUV)) && defined(DVP_USE_IMGLIB) + DVP_Demo_t *demo = (DVP_Demo_t *)calloc(1, sizeof(DVP_Demo_t)); + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + +#if defined(DVP_RUNTIME_DEBUG) + debug_get_zone_mask("DVP_ZONE_MASK", &dvp_zone_mask); +#endif + + if (demo && argc >= 1) + { + uint32_t i,j,k,n; + uint32_t display_width = (argc > 1?atoi(argv[1]):640); + uint32_t display_height = (argc > 2?atoi(argv[2]):480); + uint32_t width = (argc > 3?atoi(argv[3]):160); + uint32_t height = (argc > 4?atoi(argv[4]):120); + uint32_t fps = 30; + uint32_t numFrames = (argc > 5?atoi(argv[5]):100); // how many frames to display before quitting + uint32_t numSubImages = (display_width/width) * (display_height/height); + uint32_t numGraphImages = 20; /// @note make sure this matches the numbers used below + int32_t focusDepth = 10; + int32_t frameLock = 100; + demo->numDisplayImages = DVP_DISPLAY_NUM_BUFFERS - 1; + uint32_t numImages = numSubImages * demo->numDisplayImages; + VisionCam_e camType = VISIONCAM_OMX; + +#if defined(PC) + camType = VISIONCAM_USB; +#endif + + demo->frameq = queue_create(demo->numDisplayImages * VCAM_PORT_MAX, sizeof(VisionCamFrame *)); + demo->dvpd = DVP_Display_Create(display_width, display_height, display_width, display_height, DVP_DISPLAY_WIDTH, DVP_DISPLAY_HEIGHT, display_width, display_height, 0, 0, FOURCC_UYVY, 0, DVP_DISPLAY_NUM_BUFFERS); + demo->subImages = (DVP_Image_t *)calloc(numImages, sizeof(DVP_Image_t)); + demo->displays = (DVP_Image_t *)calloc(demo->numDisplayImages, sizeof(DVP_Image_t)); + demo->camImages = (DVP_Image_t *)calloc(demo->numDisplayImages, sizeof(DVP_Image_t)); + demo->images = (DVP_Image_t *)calloc(numGraphImages, sizeof(DVP_Image_t)); + demo->dvp = DVP_KernelGraph_Init(); + if (demo->frameq && demo->dvpd && demo->subImages && demo->displays && demo->camImages && demo->dvp && demo->images) + { + // initialize the display buffers + for (n = 0; n < demo->numDisplayImages; n++) + { + DVP_Image_Init(&demo->displays[n], display_width, display_height, FOURCC_UYVY); + DVP_Display_Alloc(demo->dvpd, &demo->displays[n]); + DVP_Image_Alloc(demo->dvp, &demo->displays[n], (DVP_MemType_e)demo->displays[n].memType); + DVP_Image_Init(&demo->camImages[n], width, height, FOURCC_UYVY); + // Blank the Images + for (i = 0; i < demo->displays[n].planes; i++) + for (j = 0; j < demo->displays[n].height; j++) + memset(&demo->displays[n].pData[i][j*demo->displays[n].y_stride],0x80,demo->displays[n].x_stride*demo->displays[n].width); + // initialize images which are the subsections of the display buffers + for (i = 0; i < numSubImages; i++) + { + uint32_t k = (n * numSubImages) + i; + DVP_Image_Init(&demo->subImages[k], width, height, FOURCC_UYVY); + SubsectionImage(&demo->displays[n], &demo->subImages[k], i); + if (i == 0) + { + // if this is the first index of the subsections, + // use this as the camera buffer + memcpy(&demo->camImages[n], &demo->subImages[k],sizeof(DVP_Image_t)); + } + } + } + + // initialize the DVP Nodes and Graphs + i = 0; + uint32_t idx_a9, len_a9; + uint32_t idx_dsp, len_dsp; + uint32_t idx_m3, len_m3; + uint32_t idx_conv, len_conv; + uint32_t idx_mask_x, idx_scratch, idx_mask_y, idx_scratch2; + + // A9 + idx_a9 = i; + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); // LUMA + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); // EDGE SOBEL + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); // EDGE PREWITT + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); // EDGE SCHARR + len_a9 = i - idx_a9; + for (j = 0; j < len_a9; j++) { + if (DVP_Image_Alloc(demo->dvp, &demo->images[idx_a9+j], DVP_MTYPE_MPUCACHED_VIRTUAL) == DVP_FALSE) { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: Failed to allocate A9 image\n"); + } + } + + // DSP + idx_dsp = i; + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); // LUMA + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); // CONV 3x3 Gx + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); // CONV 3x3 Gy + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); // DILATE + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); // IIR H + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); // IIR V + len_dsp = i - idx_dsp; + for (j = 0; j < len_dsp; j++) { +#if defined(DVP_USE_TILER) + if (DVP_Image_Alloc(demo->dvp, &demo->images[idx_dsp+j], DVP_MTYPE_MPUCACHED_1DTILED) == DVP_FALSE) { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: Failed to allocate DSP image\n"); + } +#else + if (DVP_Image_Alloc(demo->dvp, &demo->images[idx_dsp+j], DVP_MTYPE_DEFAULT) == DVP_FALSE) { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: Failed to allocate DSP image\n"); + } +#endif + } + + // SIMCOP + idx_m3 = i; + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); // LUMA + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); // SOBEL Gx + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); // SOBEL Gy + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); // IIR H + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); // IIR V + len_m3 = i - idx_m3; + for (j = 0; j < len_m3; j++) { +#if defined(DVP_USE_TILER) + if (DVP_Image_Alloc(demo->dvp, &demo->images[idx_m3+j], DVP_MTYPE_MPUNONCACHED_2DTILED) == DVP_FALSE) { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: Failed to allocate M3 image\n"); + } +#else + if (DVP_Image_Alloc(demo->dvp, &demo->images[idx_m3+j], DVP_MTYPE_DEFAULT) == DVP_FALSE) { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: Failed to allocate M3 image\n"); + } +#endif + } + + idx_conv = i; // the display conversion images start here + len_conv = i; // we want to convert all these images; + + // Mask & Scratch + idx_mask_x = i; + DVP_Image_Init(&demo->images[i++], 3, 3, FOURCC_Y800); + DVP_Image_Alloc(demo->dvp, &demo->images[idx_mask_x], DVP_MTYPE_MPUCACHED_VIRTUAL); + idx_mask_y = i; + DVP_Image_Init(&demo->images[i++], 3, 3, FOURCC_Y800); + DVP_Image_Alloc(demo->dvp, &demo->images[idx_mask_y], DVP_MTYPE_MPUCACHED_VIRTUAL); + idx_scratch = i; + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); + DVP_Image_Alloc(demo->dvp, &demo->images[idx_scratch], DVP_MTYPE_MPUCACHED_VIRTUAL); + idx_scratch2 = i; + DVP_Image_Init(&demo->images[i++], width, height, FOURCC_Y800); + DVP_Image_Alloc(demo->dvp, &demo->images[idx_scratch2], DVP_MTYPE_MPUCACHED_VIRTUAL); + + // fill in the mask with the SOBEL X Gradient edge filter + demo->images[idx_mask_x].pData[0][0] = (uint8_t)-1; + demo->images[idx_mask_x].pData[0][1] = (uint8_t) 0; + demo->images[idx_mask_x].pData[0][2] = (uint8_t) 1; + demo->images[idx_mask_x].pData[0][3] = (uint8_t)-2; + demo->images[idx_mask_x].pData[0][4] = (uint8_t) 0; + demo->images[idx_mask_x].pData[0][5] = (uint8_t) 2; + demo->images[idx_mask_x].pData[0][6] = (uint8_t)-1; + demo->images[idx_mask_x].pData[0][7] = (uint8_t) 0; + demo->images[idx_mask_x].pData[0][8] = (uint8_t) 1; + + // fill in the mask with the SOBEL Y Gradient edge filter + demo->images[idx_mask_y].pData[0][0] = (uint8_t)-1; + demo->images[idx_mask_y].pData[0][1] = (uint8_t)-2; + demo->images[idx_mask_y].pData[0][2] = (uint8_t)-1; + demo->images[idx_mask_y].pData[0][3] = (uint8_t) 0; + demo->images[idx_mask_y].pData[0][4] = (uint8_t) 0; + demo->images[idx_mask_y].pData[0][5] = (uint8_t) 0; + demo->images[idx_mask_y].pData[0][6] = (uint8_t) 1; + demo->images[idx_mask_y].pData[0][7] = (uint8_t) 2; + demo->images[idx_mask_y].pData[0][8] = (uint8_t) 1; + + demo->numNodes = len_a9 + len_dsp + len_m3 + len_conv; + + DVP_PRINT(DVP_ZONE_ALWAYS, "Allocating %u %ux%u images\n", demo->numNodes, width, height); + + // Allocate the Nodes + demo->nodes = DVP_KernelNode_Alloc(demo->dvp, demo->numNodes); + if (demo->nodes == NULL) + return STATUS_NOT_ENOUGH_MEMORY; + + DVP_KernelGraphSection_t sections[] = { + {&demo->nodes[idx_a9], len_a9, DVP_PERF_INIT, DVP_CORE_LOAD_INIT, DVP_FALSE}, + {&demo->nodes[idx_dsp], len_dsp, DVP_PERF_INIT, DVP_CORE_LOAD_INIT, DVP_FALSE}, + {&demo->nodes[idx_m3], len_m3, DVP_PERF_INIT, DVP_CORE_LOAD_INIT, DVP_FALSE}, + {&demo->nodes[idx_conv], len_conv, DVP_PERF_INIT, DVP_CORE_LOAD_INIT, DVP_FALSE}, + }; + DVP_U32 order[] = {0,0,0,1}; // 3 parallel then 1 series + DVP_KernelGraph_t graph = { + sections, + dimof(sections), + order, + DVP_PERF_INIT + }; + DVP_Transform_t *io = NULL; + DVP_Morphology_t *morph = NULL; + DVP_ImageConvolution_t *img = NULL; + DVP_IIR_t *iir = NULL; + demo->graph = &graph; + + i = 0; + // Now initialize the node structures for exactly what we want + + // A9 Section + demo->nodes[i].header.kernel = DVP_KN_XYXY_TO_Y800; + demo->nodes[i].header.affinity = DVP_CORE_CPU; + io = dvp_knode_to(&demo->nodes[i], DVP_Transform_t); + io->input = demo->camImages[0]; + io->output = demo->images[idx_a9]; + i++; + + demo->nodes[i].header.kernel = DVP_KN_SOBEL_8; + demo->nodes[i].header.affinity = DVP_CORE_CPU; + io = dvp_knode_to(&demo->nodes[i], DVP_Transform_t); + io->input = demo->images[idx_a9]; + io->output = demo->images[idx_a9+1]; + i++; + + demo->nodes[i].header.kernel = DVP_KN_PREWITT_8; + demo->nodes[i].header.affinity = DVP_CORE_CPU; + io = dvp_knode_to(&demo->nodes[i], DVP_Transform_t); + io->input = demo->images[idx_a9]; + io->output = demo->images[idx_a9+2]; + i++; + + demo->nodes[i].header.kernel = DVP_KN_SCHARR_8; + demo->nodes[i].header.affinity = DVP_CORE_CPU; + io = dvp_knode_to(&demo->nodes[i], DVP_Transform_t); + io->input = demo->images[idx_a9]; + io->output = demo->images[idx_a9+3]; + i++; + + // DSP Section + demo->nodes[i].header.kernel = DVP_KN_XYXY_TO_Y800; + demo->nodes[i].header.affinity = DVP_CORE_DSP; + io = dvp_knode_to(&demo->nodes[i], DVP_Transform_t); + io->input = demo->camImages[0]; + io->output = demo->images[idx_dsp]; + i++; + + demo->nodes[i].header.kernel = DVP_KN_IMG_CONV_3x3; + demo->nodes[i].header.affinity = DVP_CORE_DSP; + img = dvp_knode_to(&demo->nodes[i], DVP_ImageConvolution_t); + img->input = demo->images[idx_dsp]; + img->output = demo->images[idx_dsp+1]; + img->mask = demo->images[idx_mask_x]; + i++; + + demo->nodes[i].header.kernel = DVP_KN_IMG_CONV_3x3; + demo->nodes[i].header.affinity = DVP_CORE_DSP; + img = dvp_knode_to(&demo->nodes[i], DVP_ImageConvolution_t); + img->input = demo->images[idx_dsp+1]; + img->output = demo->images[idx_dsp+2]; + img->mask = demo->images[idx_mask_y]; + i++; + + demo->nodes[i].header.kernel = DVP_KN_DILATE_CROSS; + demo->nodes[i].header.affinity = DVP_CORE_DSP; + morph = dvp_knode_to(&demo->nodes[i], DVP_Morphology_t); + morph->input = demo->images[idx_dsp+2]; + morph->output = demo->images[idx_dsp+3]; + i++; + + demo->nodes[i].header.kernel = DVP_KN_IIR_HORZ; + demo->nodes[i].header.affinity = DVP_CORE_DSP; + iir = dvp_knode_to(&demo->nodes[i], DVP_IIR_t); + iir->input = demo->images[idx_dsp]; + iir->output = demo->images[idx_dsp+4]; + iir->scratch = demo->images[idx_scratch]; + iir->weight = 2000; + i++; + + demo->nodes[i].header.kernel = DVP_KN_IIR_VERT; + demo->nodes[i].header.affinity = DVP_CORE_DSP; + iir = dvp_knode_to(&demo->nodes[i], DVP_IIR_t); + iir->input = demo->images[idx_dsp]; + iir->output = demo->images[idx_dsp+5]; + iir->scratch = demo->images[idx_scratch]; + iir->weight = 2000; + i++; + + // SIMCOP Section + demo->nodes[i].header.kernel = DVP_KN_XYXY_TO_Y800; + demo->nodes[i].header.affinity = DVP_CORE_SIMCOP; + io = dvp_knode_to(&demo->nodes[i], DVP_Transform_t); + io->input = demo->camImages[0]; + io->output = demo->images[idx_m3]; + i++; + + demo->nodes[i].header.kernel = DVP_KN_IMG_CONV_3x3; + demo->nodes[i].header.affinity = DVP_CORE_SIMCOP; + img = dvp_knode_to(&demo->nodes[i], DVP_ImageConvolution_t); + img->input = demo->images[idx_m3]; + img->output = demo->images[idx_m3+1]; + img->mask = demo->images[idx_mask_x]; + i++; + + demo->nodes[i].header.kernel = DVP_KN_IMG_CONV_3x3; + demo->nodes[i].header.affinity = DVP_CORE_SIMCOP; + img = dvp_knode_to(&demo->nodes[i], DVP_ImageConvolution_t); + img->input = demo->images[idx_m3+1]; + img->output = demo->images[idx_m3+2]; + img->mask = demo->images[idx_mask_x]; + i++; + + demo->nodes[i].header.kernel = DVP_KN_IIR_HORZ; + demo->nodes[i].header.affinity = DVP_CORE_SIMCOP; + iir = dvp_knode_to(&demo->nodes[i], DVP_IIR_t); + iir->input = demo->images[idx_m3]; + iir->output = demo->images[idx_m3+3]; + iir->scratch = demo->images[idx_scratch2]; + iir->weight = 2000; + i++; + + demo->nodes[i].header.kernel = DVP_KN_IIR_VERT; + demo->nodes[i].header.affinity = DVP_CORE_SIMCOP; + iir = dvp_knode_to(&demo->nodes[i], DVP_IIR_t); + iir->input = demo->images[idx_m3]; + iir->output = demo->images[idx_m3+4]; + iir->scratch = demo->images[idx_scratch2]; + iir->weight = 2000; + i++; + + // CONVERSION for Display Graph + for (j = i, k = 0; j < demo->numNodes; j++, k++) { + demo->nodes[j].header.kernel = DVP_KN_Y800_TO_XYXY; + demo->nodes[j].header.affinity = DVP_CORE_CPU; + io = dvp_knode_to(&demo->nodes[i], DVP_Transform_t); + io->input = demo->images[k]; + //io->output = demo->subImages[k]; // this will get replaced as soon as a buffer is returned + } + + // initialize the camera + if (VisionCamInit(demo, camType, width, height, fps, 0, FOURCC_UYVY)) + { + VisionCamFrame *cameraFrame = NULL; + DVP_Image_t *pImage = NULL; + uint32_t recvFrames = 0; + uint32_t timeouts = 0; + + thread_msleep(1000/fps); // wait 1 frame period. + + DVP_PRINT(DVP_ZONE_ALWAYS, "VisionCam is initialized, entering queue read loop!\n"); + // read from the queue and display the images + do { + bool_e ret = queue_read(demo->frameq, false_e, &cameraFrame); + if (ret == true_e && cameraFrame != NULL) + { + uint32_t idx_disp = 0; + + pImage = (DVP_Image_t *)cameraFrame->mFrameBuff; + + timeouts = 0; + + DVP_PRINT(DVP_ZONE_ALWAYS, "Received Frame %p (%p) from camera\n", pImage, pImage->pData[0]); + + // match the pImage with a displays + for (idx_disp = 0; idx_disp < demo->numDisplayImages; idx_disp++) + if (pImage->pData[0] == demo->camImages[idx_disp].pData[0]) + break; + + DVP_PRINT(DVP_ZONE_ALWAYS, "Image Correlates to Display Buffer %u (%p->%p)\n", idx_disp, &demo->displays[idx_disp], demo->displays[idx_disp].pData[0]); + + // update the DVP Graphs with the new camera image + dvp_knode_to(&demo->nodes[idx_a9], DVP_Transform_t)->input = *pImage; + dvp_knode_to(&demo->nodes[idx_dsp], DVP_Transform_t)->input = *pImage; + dvp_knode_to(&demo->nodes[idx_m3], DVP_Transform_t)->input = *pImage; + + // update the conversion array + for (i = 0; i < len_conv; i++) { + // add one to the subImages index to skip the camera preview in that + // frame. + dvp_knode_to(&demo->nodes[idx_conv+i], DVP_Transform_t)->output = demo->subImages[(idx_disp * numSubImages) + i + 1]; + } + + // run the DVP Kernel Graph + DVP_KernelGraph_Process(demo->dvp, demo->graph, demo, DVPCallback); + + // update the display + DVP_Display_Render(demo->dvpd, &demo->displays[idx_disp]); + + demo->pCam->returnFrame(cameraFrame); + + recvFrames++; + if (recvFrames > numFrames) + break; + if (focusDepth >= 0) { + if (recvFrames == fps) { // after 1 second + demo->pCam->setParameter(VCAM_PARAM_DO_MANUALFOCUS, &focusDepth, sizeof(focusDepth)); + } + } + if (frameLock > 0) { + if (recvFrames == (uint32_t)frameLock) { + bool_e lock = true_e; + demo->pCam->sendCommand(VCAM_CMD_LOCK_AE, &lock, sizeof(lock)); + demo->pCam->sendCommand(VCAM_CMD_LOCK_AWB, &lock, sizeof(lock)); + } + } + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Timedout waiting for buffer from Camera!\n"); + timeouts++; + thread_msleep(1000/fps); + } + } while (timeouts < DVP_DEMO_MAX_TIMEOUTS); + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "DVP_DEMO Failed during camera initialization\n"); + ret = STATUS_NO_RESOURCES; + } + DVP_PrintPerformanceGraph(demo->dvp, demo->graph); + DVP_KernelNode_Free(demo->dvp, demo->nodes, demo->numNodes); + VisionCamDeinit(demo); + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "DVP_DEMO Failed during data structure initialization\n"); + } + if (demo->dvp) { + DVP_KernelGraph_Deinit(demo->dvp); + } + if (demo->camImages) + free(demo->camImages); + if (demo->displays) { + for (n = 0; n < demo->numDisplayImages; n++) { + DVP_Display_Free(demo->dvpd, &demo->displays[n]); + } + free(demo->displays); + } + if (demo->subImages) + free(demo->subImages); + if (demo->images) + free(demo->images); + if (demo->dvpd) + DVP_Display_Destroy(&demo->dvpd); + if (demo->frameq) + queue_destroy(demo->frameq); + } +#else + DVP_PRINT(DVP_ZONE_ERROR, "Required libraries are not present!\n"); + argc |= 1; + argv[0] = argv[0]; + ret = -1; +#endif + return ret; +} diff --git a/source/dvp/dvp_display/Android.mk b/source/dvp/dvp_display/Android.mk new file mode 100644 index 0000000..b529487 --- /dev/null +++ b/source/dvp/dvp_display/Android.mk @@ -0,0 +1,15 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(call all-subdir-makefiles) diff --git a/source/dvp/dvp_display/gfx/Android.mk b/source/dvp/dvp_display/gfx/Android.mk new file mode 100644 index 0000000..0e4163c --- /dev/null +++ b/source/dvp/dvp_display/gfx/Android.mk @@ -0,0 +1,46 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_ANDROID_VERSION),ICS) +BUILD_GFX:=1 +else ifeq ($(TARGET_ANDROID_VERSION),JELLYBEAN) +BUILD_GFX:=1 +endif + +ifeq ($(BUILD_GFX),1) + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(DVP_DEBUGGING) $(DVP_CFLAGS) +LOCAL_SRC_FILES := gfx_display.c +LOCAL_C_INCLUDES := $(DVP_INCLUDES) +LOCAL_MODULE := libgfxdisp +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(DVP_DEBUGGING) $(DVP_CFLAGS) -DTEST +LOCAL_SRC_FILES := gfx_display.c +LOCAL_C_INCLUDES +=$(DVP_INCLUDES) +LOCAL_MODULE := gfxd_test +LOCAL_STATIC_LIBRARIES := libsosal +LOCAL_SHARED_LIBRARIES := libutils libhardware +LOCAL_LDLIBS += -lhwcomposer.omap4.so +include $(BUILD_EXECUTABLE) +endif diff --git a/source/dvp/dvp_display/gfx/gfx_display.c b/source/dvp/dvp_display/gfx/gfx_display.c new file mode 100644 index 0000000..aeae744 --- /dev/null +++ b/source/dvp/dvp_display/gfx/gfx_display.c @@ -0,0 +1,401 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#undef GFX_DISPLAY_WRITE_TO_FILE + +typedef struct _gfx_display_t { +#ifdef GFX_DISPLAY_WRITE_TO_FILE + FILE *fp; + char filename[MAX_PATH]; +#endif + bitfield_t used; + alloc_device_t *allocator; + IMG_gralloc_module_public_t *module; + uint32_t numBuffers; + IMG_native_handle_t **handles; /**< An array of image native handles */ + uint8_t **buffers; + image_t **images; + queue_t *returnq; + uint32_t width; + uint32_t height; + int32_t stride; + fourcc_t color; +} gfx_display_t; +#define _GFX_DISPLAY_T + +#include + +typedef struct _hal_to_fourcc_t { + int format; + fourcc_t color; +} HAL_to_FOURCC_t; + +static HAL_to_FOURCC_t colors[] = { + {HAL_PIXEL_FORMAT_RGB_565, FOURCC_RGB565}, + //{HAL_PIXEL_FORMAT_RGB_888, FOURCC_RGB}, + {HAL_PIXEL_FORMAT_RGBA_8888, FOURCC_RGBA}, + {HAL_PIXEL_FORMAT_BGRA_8888, FOURCC_BGRA}, + //{HAL_PIXEL_FORMAT_YCbCr_422_SP, FOURCC_NV16}, + {HAL_PIXEL_FORMAT_YCbCr_422_I, FOURCC_YUY2}, + //{HAL_PIXEL_FORMAT_YCrCb_420_SP, FOURCC_NV21}, + {HAL_PIXEL_FORMAT_YV12, FOURCC_YV12}, + {0x100, FOURCC_NV12}, +}; + +void gfx_display_destroy(gfx_display_t **pgfxd) +{ + if (pgfxd && *pgfxd) + { +#ifdef GFX_DISPLAY_WRITE_TO_FILE + fclose((*pgfxd)->fp); +#endif + free((*pgfxd)); + pgfxd = NULL; + } +} + +gfx_display_t *gfx_display_create(char *filename) +{ + gfx_display_t *gfxd = (gfx_display_t *)calloc(1, sizeof(gfx_display_t)); + if (gfxd) + { +#ifdef GFX_DISPLAY_WRITE_TO_FILE + strncpy(gfxd->filename, filename, MAX_PATH); + gfxd->fp = fopen(gfxd->filename, "w+"); + if (gfxd->fp) + { + DVP_PRINT(DVP_ZONE_VIDEO, "Create GFX Display on File %s\n", filename); + } +#else + filename = filename; +#endif + } + return gfxd; +} + +bool_e gfx_display_free(gfx_display_t *gfxd) +{ + bool_e freed = false_e; + if (gfxd) + { + uint32_t i = 0; + for (i = 0; i < gfxd->numBuffers; i++) + { + gfxd->allocator->free(gfxd->allocator, (buffer_handle_t)gfxd->handles[i]); + } + free(gfxd->handles); + gfxd->numBuffers = 0; + bitfield_deinit(&gfxd->used); + queue_destroy(gfxd->returnq); + gralloc_close(gfxd->allocator); + freed = true_e; + } + return freed; +} + +bool_e gfx_display_allocate(gfx_display_t *gfxd, uint32_t numBuf, uint32_t width, uint32_t height, fourcc_t color) +{ + bool_e allocated = false_e; + if (gfxd) + { + int ret = 0; + ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const struct hw_module_t **)&gfxd->module); + DVP_PRINT(DVP_ZONE_VIDEO, "hw_get_module(%s,...) returned %d\n", GRALLOC_HARDWARE_MODULE_ID, ret); + if (ret < 0) + { + DVP_PRINT(DVP_ZONE_VIDEO, "Failed to open Gralloc HW\n"); + return false_e; + } + DVP_PRINT(DVP_ZONE_VIDEO, "hw_module_t *%p by %s\n", gfxd->module, gfxd->module->base.common.author); + + ret = gralloc_open((const struct hw_module_t *)gfxd->module, &gfxd->allocator); + if (ret == 0) + { + DVP_PRINT(DVP_ZONE_VIDEO, "gralloc_open() passed!\n"); + gfxd->numBuffers = numBuf; + gfxd->handles = (IMG_native_handle_t **)calloc(numBuf, sizeof(IMG_native_handle_t *)); + gfxd->images = (image_t **)calloc(numBuf, sizeof(image_t*)); + if (gfxd->handles && gfxd->images) + { + uint32_t i = 0; + int format = 0; + for (i = 0; i < dimof(colors); i++) + { + if (color == colors[i].color) + format = colors[i].format; + } + if (format > 0) + { + DVP_PRINT(DVP_ZONE_VIDEO, "Using format %d (0x%x) which is FOURCC 0x%x\n", format, format, color); + gfxd->color = color; + gfxd->width = width; + gfxd->height = height; + for (i = 0; i < numBuf; i++) + { + int usage = GRALLOC_USAGE_HW_TEXTURE | + GRALLOC_USAGE_HW_RENDER | + GRALLOC_USAGE_SW_READ_RARELY | // Non-cached ? + GRALLOC_USAGE_SW_WRITE_NEVER; + const struct native_handle_t *handle = NULL; + DVP_PRINT(DVP_ZONE_VIDEO, "Asking for %ux%u fmt:%d usage:%d\n", width, height, format, usage); + ret = gfxd->allocator->alloc(gfxd->allocator, width, height, format, usage, (buffer_handle_t *)&handle, &gfxd->stride); + if (ret == 0) + { + gfxd->handles[i] = (IMG_native_handle_t *)handle; + DVP_PRINT(DVP_ZONE_VIDEO, + "Allocated GRALLOC buffer handle version:%d numFD=%d fd[0]=%d fd[1]=%d %ux%u fmt=%d bpp=%u stride=%d\n", + gfxd->handles[i]->base.version, + gfxd->handles[i]->base.numFds, + gfxd->handles[i]->fd[0], + gfxd->handles[i]->fd[1], + gfxd->handles[i]->iWidth, + gfxd->handles[i]->iHeight, + gfxd->handles[i]->iFormat, + gfxd->handles[i]->uiBpp, + gfxd->stride); + allocated = true_e; + } + else + allocated = false_e; + } + } + else + { + DVP_PRINT(DVP_ZONE_VIDEO, "No compatible format found!\n"); + } + + if (allocated) + { + bitfield_init(&gfxd->used, numBuf); + gfxd->returnq = queue_create(numBuf, sizeof(void *)); + } + } + } + else + { + DVP_PRINT(DVP_ZONE_VIDEO, "Failed to open Gralloc device!\n"); + } + } + return allocated; +} + +void gfx_display_release(gfx_display_t *gfxd, image_t **pptr, void *handle) +{ + if (gfxd) + { + int ret = 0; + uint32_t idx = 0; + for (idx = 0; idx < gfxd->numBuffers; idx++) + { + if (gfxd->handles[idx] == handle) { + bitfield_rls(&gfxd->used, idx); + ret = gfxd->module->base.unlock((const struct gralloc_module_t *)gfxd->module, (buffer_handle_t)gfxd->handles[idx]); + if (pptr) { + *pptr = NULL; + } + image_free(&gfxd->images[idx]); + break; + } + } + } +} + +image_t *gfx_display_acquire(gfx_display_t *gfxd, void **pHandle) +{ + if (gfxd) + { + uint32_t idx = 0; + if (bitfield_get(&gfxd->used, &idx)) + { + uint8_t *bufs[4] = {0,0,0,0}; + int ret = 0; + int usage = GRALLOC_USAGE_HW_TEXTURE | + GRALLOC_USAGE_HW_RENDER | + GRALLOC_USAGE_SW_READ_RARELY | + GRALLOC_USAGE_SW_WRITE_NEVER; + + // save the handle with the client + *pHandle = (void *)gfxd->handles[idx]; + + // allocate an image structure, + gfxd->images[idx] = image_allocate(gfxd->width, gfxd->height, gfxd->color); + + // by locking the memory we are mapping it to our UVA + ret = gfxd->module->base.lock((const struct gralloc_module_t *)gfxd->module, (buffer_handle_t)gfxd->handles[idx], usage, 0, 0, gfxd->width, gfxd->height, (void **)bufs); + + DVP_PRINT(DVP_ZONE_VIDEO, "Locking %p to {%p, %p, %p, %p} (ret=%d)\n", gfxd->handles[idx], bufs[0], bufs[1], bufs[2], bufs[3], ret); + + // fill in the details in the image_t structure... + if (gfxd->color == FOURCC_NV12) { + gfxd->images[idx]->plane[0].ptr = bufs[0]; + gfxd->images[idx]->plane[1].ptr = bufs[1]; + gfxd->images[idx]->plane[0].ystride = gfxd->stride; + gfxd->images[idx]->plane[1].ystride = gfxd->stride; + } else { + gfxd->images[idx]->plane[0].ptr = bufs[0]; + gfxd->images[idx]->plane[0].ystride = gfxd->stride; + } + return gfxd->images[idx]; + } + } + return NULL; +} + +bool_e gfx_display_queue(gfx_display_t *gfxd, void *handle) +{ +#ifdef GFX_DISPLAY_WRITE_TO_FILE + if (gfxd) + { + size_t bytes = 0; + uint32_t i = 0; + // match the handle to the actually mapped pointer. + for (i = 0; i < gfxd->numBuffers; i++) + { + if (handle == gfxd->handles[i]) + { + uint32_t p,l,y = 0; + image_t *img = gfxd->images[i]; + for (p = 0; p < img->numPlanes; p++) + { + for (y = 0; y < img->plane[p].ydim/img->plane[p].yscale; y++) + { + i = (y * img->plane[p].ystride); + l = (img->plane[p].xdim / img->plane[p].xscale) * img->plane[p].xstride; + bytes += fwrite(&img->plane[p].ptr[i], 1, l, gfxd->fp); + } + } + DVP_PRINT(DVP_ZONE_VIDEO, "Wrote %zu bytes to file!\n", bytes); + + // write the pointer into the queue + return queue_write(gfxd->returnq, true_e, &handle); + } + } + } + return false_e; +#else + if (gfxd && handle) + { + // write the pointer into the queue + return queue_write(gfxd->returnq, true_e, &handle); + } + else + return false_e; +#endif +} + +bool_e gfx_display_dequeue(gfx_display_t *gfxd, void **phandle) +{ + if (gfxd) + { + // wait for buffer from queue + return queue_read(gfxd->returnq, true_e, phandle); + } + return false_e; +} + +uint32_t gfx_display_length(gfx_display_t *gfxd) +{ + switch (gfxd->color) + { + case FOURCC_NV12: + case FOURCC_YV12: + return gfxd->stride * ((gfxd->height * 3) / 2); + default: + return gfxd->width*gfxd->height; + } +} + +#ifdef TEST + +uint32_t dvp_zone_mask = 0xFFFF; // declare a local version for testing... + +int main(int argc, char *argv[]) +{ + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + +#if defined(DVP_RUNTIME_DEBUG) + debug_get_zone_mask("DVP_ZONE_MASK", &dvp_zone_mask); +#endif + + if (argc > 2) + { + const uint32_t numBuf = 4; + uint32_t count = atoi(argv[1]); + char filename[MAX_PATH]; + gfx_display_t *gfxd = NULL; + image_t *ptrs[numBuf]; + void *hdls[numBuf]; + + strncpy(filename, argv[2], MAX_PATH); + gfxd = gfx_display_create(filename); + if (gfxd) + { + printf("Opened GFX Display!\n"); + if (gfx_display_allocate(gfxd, numBuf, 320, 240, FOURCC_NV12)) + { + uint32_t i,j; + printf("Allocated buffers!\n"); + for (i = 0; i < numBuf; i++) + { + ptrs[i] = gfx_display_acquire(gfxd, &hdls[i]); + if (ptrs[i]) + { + printf("Acquired Buffer %p hdl %p\n", ptrs[i], hdls[i]); + } + else + { + printf("Failed to acquire buffer %u!\n",i); + } + } + + for (j = 0; j < count; j++) + { + for (i = 0; i < numBuf; i++) + { + // Queue to Display + gfx_display_queue(gfxd, hdls[i]); + + // Remove from Display + gfx_display_dequeue(gfxd, &hdls[i]); + } + } + + for (i = 0; i < numBuf; i++) + { + printf("Release Buffer %p\n", ptrs[i]); + gfx_display_release(gfxd, NULL, hdls[i]); + } + + gfx_display_free(gfxd); + } + else + { + printf("Failed to allocate!\n"); + } + gfx_display_destroy(&gfxd); + } + } + return 0; +} + +#endif diff --git a/source/dvp/dvp_display/gtk/concerto.mak b/source/dvp/dvp_display/gtk/concerto.mak new file mode 100644 index 0000000..e2007c8 --- /dev/null +++ b/source/dvp/dvp_display/gtk/concerto.mak @@ -0,0 +1,39 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_OS),LINUX) +ifneq ($(GTK_PATH),) + +include $(PRELUDE) +TARGET=gtkwindow +TARGETTYPE=library +CSOURCES=gtkwindow.c +IDIRS+=$(GTK_INC) +include $(FINALE) + +# Set the module manually so that we can have 2 builds in one makefile. +_MODULE=gtk_test +include $(PRELUDE) +TARGET=gtk_test +TARGETTYPE=exe +CSOURCES=gtk_test.c +IDIRS+=$(GTK_INC) +LDIRS+=$(GTK_LDIRS) +STATIC_LIBS=gtkwindow sosal +SYS_SHARED_LIBS+=$(GTK_LIBS) +include $(FINALE) + +endif +endif + diff --git a/source/dvp/dvp_display/gtk/gtk_test.c b/source/dvp/dvp_display/gtk/gtk_test.c new file mode 100644 index 0000000..31ff028 --- /dev/null +++ b/source/dvp/dvp_display/gtk/gtk_test.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +long flen(FILE *f) +{ + long new_, old = ftell(f); + fseek(f, 0, SEEK_END); + new_ = ftell(f); + fseek(f, old, SEEK_SET); + return new_; +} + +uint32_t dvp_zone_mask = 0xFFFF; // declare a local version for testing + +int main(int argc, char *argv[]) +{ + uint32_t count = 4; + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + +#if defined(DVP_RUNTIME_DEBUG) + debug_get_zone_mask("DVP_ZONE_MASK", &dvp_zone_mask); +#endif + + if (argc == 1) + { + GtkWindow_t *w = gtkwindow_open("GTK Test"); + gtkwindow_allocate(w, 640, 480, count, FOURCC_RGB); + thread_msleep(5000); + gtkwindow_free(w); + gtkwindow_close(w); + } + else if (argc == 5) + { + char filename[MAX_PATH]; + char *name = argv[1]; + uint32_t width = atoi(argv[2]); + uint32_t height = atoi(argv[3]); + fourcc_t color = *(fourcc_t *)argv[4]; + PYUV_GetFilename(filename, "", name, width, height, 30, color); + printf("Opening %s\n", filename); + FILE *fp = fopen(filename, "rb"); + if (fp) + { + uint32_t numFrames, frameSize, f, i = 0; + GtkWindow_t *w = gtkwindow_open("GTK Renderer"); + gtkwindow_allocate(w, width, height, count, color); + frameSize = gtkwindow_length(w, 0); + numFrames = flen(fp)/frameSize; + DVP_PRINT(DVP_ZONE_ALWAYS, "There are %u frames in the file!\n", numFrames); + for (f = 0; f < numFrames; f++) + { + uint32_t index; + void *ptr = gtkwindow_acquire(w, &index); + size_t b = fread(ptr, 1, frameSize, fp); + DVP_PRINT(DVP_ZONE_ALWAYS, "Read "FMT_SIZE_T" bytes from file!\n", b); + if (gtkwindow_queue(w, index)) { + gtkwindow_dequeue(w, &index); // blocking call + DVP_PRINT(DVP_ZONE_ALWAYS, "Dequeued index %u, had ptr %p\n", index, ptr); + gtkwindow_release(w, ptr, index); + } + thread_msleep(33); + } + gtkwindow_free(w); + gtkwindow_close(w); + fclose(fp); + } + } + return 0; +} diff --git a/source/dvp/dvp_display/gtk/gtkwindow.c b/source/dvp/dvp_display/gtk/gtkwindow.c new file mode 100644 index 0000000..5ef1ea2 --- /dev/null +++ b/source/dvp/dvp_display/gtk/gtkwindow.c @@ -0,0 +1,343 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + + +//****************************************************************************** +// INTERNAL FUNCTIONS +//****************************************************************************** + +static gboolean on_draw_expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) +{ + GtkWindow_t *w = (GtkWindow_t *)user_data; + DVP_PRINT(DVP_ZONE_VIDEO, "**** RENDERING!!! fb[%u] *****\n", w->fi); + gdk_draw_rgb_image(widget->window, + widget->style->fg_gc[GTK_STATE_NORMAL], + 0, 0, + w->fb[w->fi]->plane[0].xdim, + w->fb[w->fi]->plane[0].ydim, + GDK_RGB_DITHER_MAX, + w->fb[w->fi]->plane[0].ptr, + w->fb[w->fi]->plane[0].ystride); + return TRUE; +} + +static thread_ret_t threadGtkRenderer(void *arg) +{ + GtkWindow_t *w = (GtkWindow_t *)arg; + DVP_PRINT(DVP_ZONE_VIDEO, "GTK: Render Loop Running!\n"); + while (w->bRendering) + { + image_t *img = NULL; + if (queue_read(w->queue, true_e, &img) == true_e) + { + if (img != NULL) + { + //GdkRectangle rect = {0,0,w->width, w->height}; + //GdkWindow *window = gtk_widget_get_root_window(w->window); + DVP_PRINT(DVP_ZONE_VIDEO, "GTK: Render Loop Received image_t %p of format 0x%08x!\n", img, img->color); + //gdk_window_freeze_updates(window); + w->fi = (w->fi + 1) % dimof(w->fb); + image_convert(w->fb[w->fi], img); + //gdk_window_thaw_updates(window); + //gdk_window_invalidate_rect(window, &rect, TRUE); + gtk_widget_queue_draw_area(w->draw_area, 0, 0, w->width, w->height); + queue_write(w->dequeue, false_e, &img); + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "GTK: Render loop dequeued a NULL image!\n"); + } + } + else if (w->bRendering == false_e) + break; + } + thread_exit(0); +} + +static thread_ret_t threadGtkMain(void *arg) +{ + GtkWindow_t *w = (GtkWindow_t *)arg; + while (w->bRunning) + { + DVP_PRINT(DVP_ZONE_VIDEO, "+gtk_main()\n"); + event_set(&w->wait); + gtk_main(); + DVP_PRINT(DVP_ZONE_VIDEO, "-gtk_main()\n"); + } + thread_exit(0); +} + +//****************************************************************************** +// EXTERNAL API +//****************************************************************************** + +void gtkwindow_close(GtkWindow_t *w) +{ + if (w) + { + memset(w, 0, sizeof(GtkWindow_t)); + free(w); + } +} + +GtkWindow_t *gtkwindow_open(const char *title) +{ + GtkWindow_t *w = (GtkWindow_t *)calloc(1, sizeof(GtkWindow_t)); + if (w) + { + char *args[] = { + "--gtk-module", + "--gtk-debug", + "--display", + "--name", + "--class", + "--sync" + }; + char **argv = args; + int argc = dimof(argv); + gtk_init(&argc, &argv); + gdk_rgb_init(); + gdk_rgb_set_verbose(TRUE); + w->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + DVP_PRINT(DVP_ZONE_VIDEO, "Creating Window %s\n", title); + gtk_window_set_title(GTK_WINDOW(w->window), (const gchar *)title); + } + return w; +} + +bool_e gtkwindow_release(GtkWindow_t *w, void *ptr, uint32_t index) +{ + if (w) + { + bool_e ret = false_e; + mutex_lock(&w->lock); + if (index < w->numImg) + { + ret = bitfield_rls(&w->active, index); + } + else if (index == 0xFFFFFFFF) + { + uint32_t i = 0; + for (i = 0; i < w->numImg; i++) + { + if (w->images[i]->plane[0].ptr == ptr) + { + ret = bitfield_rls(&w->active, i); + } + } + } + mutex_unlock(&w->lock); + return ret; + } + return false_e; +} + +void *gtkwindow_acquire(GtkWindow_t *w, uint32_t *index) +{ + if (w) + { + void *ptr = NULL; + mutex_lock(&w->lock); + if (bitfield_get(&w->active, index) == false_e) + { + DVP_PRINT(DVP_ZONE_VIDEO, "Failed to acquire an image!\n"); + } + else + { + ptr = w->images[*index]->plane[0].ptr; + } + mutex_unlock(&w->lock); + return ptr; + } + else + return NULL; +} + +bool_e gtkwindow_free(GtkWindow_t *w) +{ + if (w) + { + uint32_t i; + w->bRendering = false_e; + queue_pop(w->dequeue); + queue_pop(w->queue); + thread_join(w->hRender); + queue_destroy(w->queue); + queue_destroy(w->dequeue); + + w->bRunning = false_e; + gtk_main_quit(); + gtk_widget_destroy(w->window); + thread_join(w->hMain); + + for (i = 0; i < dimof(w->fb); i++) { + image_unback(w->fb[i]); + image_free(&w->fb[i]); + } + for (i = 0; i < w->numImg; i++) { + image_unback(w->images[i]); + image_free(&w->images[i]); + } + free(w->images); + bitfield_deinit(&w->active); + event_deinit(&w->wait); + mutex_deinit(&w->lock); + return true_e; + } + else + return false_e; +} + +bool_e gtkwindow_allocate(GtkWindow_t *w, uint32_t width, uint32_t height, uint32_t count, fourcc_t color) +{ + if (w) + { + uint32_t i; + if (image_query_format(color) == false_e) + { + DVP_PRINT(DVP_ZONE_ERROR, "Invalid color space 0x%08x\n", color); + return false_e; + } + + mutex_init(&w->lock); + event_init(&w->wait, true_e); + + // remember values + w->width = width; + w->height = height; + + DVP_PRINT(DVP_ZONE_VIDEO, "Allocating %lu Frame Buffer Images\n", dimof(w->fb)); + w->fi = 0; + for (i = 0; i < dimof(w->fb); i++) + { + w->fb[i] = image_allocate(width, height, FOURCC_BGR); + image_back(w->fb[i]); + image_fill(w->fb[i], 0xFF, 0x00, 0x00); // RED + } + DVP_PRINT(DVP_ZONE_VIDEO, "Allocating %u User Images\n", count); + w->numImg = count; + w->images = (image_t **)calloc(count, sizeof(image_t *)); + for (i = 0 ; i < count; i++) { + w->images[i] = image_allocate(width, height, color); + image_back(w->images[i]); + image_print(w->images[i]); + } + bitfield_init(&w->active, count); + w->queue = queue_create(count, sizeof(image_t *)); + w->dequeue = queue_create(count, sizeof(image_t *)); + + DVP_PRINT(DVP_ZONE_VIDEO, "Creating GdkDrawingArea (Count=%u)\n", count); + w->draw_area = gtk_drawing_area_new(); + gtk_widget_set_size_request(w->draw_area, width, height); + gtk_container_add(GTK_CONTAINER(w->window), w->draw_area); + gtk_widget_set_app_paintable(w->draw_area, TRUE); + gtk_signal_connect(GTK_OBJECT(w->draw_area), "expose-event", GTK_SIGNAL_FUNC(on_draw_expose), w); + gtk_widget_set_events(w->draw_area, GDK_EXPOSURE_MASK); + gtk_widget_show_all(w->window); + + // Start GTK Main + w->bRunning = true_e; + w->hMain = thread_create(threadGtkMain, w); + + event_wait(&w->wait, EVENT_FOREVER); + + // Start GTK Renderer + w->bRendering = true_e; + w->hRender = thread_create(threadGtkRenderer, w); + + return true_e; + } + else + return false_e; +} + +uint32_t gtkwindow_search_index(GtkWindow_t *w, void *ptr) +{ + if (w) + { + uint32_t i; + for (i = 0; i < w->numImg; i++) + { + if (w->images[i]->plane[0].ptr == ptr) + break; + } + if (i == w->numImg) + return 0xFFFFFFFF; + return i; + } + else + return 0xFFFFFFFF; +} + +void *gtkwindow_search_buffer(GtkWindow_t *w, uint32_t index) +{ + if (w && index < w->numImg) + return w->images[index]->plane[0].ptr; + else + return NULL; +} + +bool_e gtkwindow_queue(GtkWindow_t *w, uint32_t index) +{ + if (w && index < w->numImg) + { + DVP_PRINT(DVP_ZONE_VIDEO, "Queueing %u %p\n", index, w->images[index]); + return queue_write(w->queue, false_e, &w->images[index]); + } + else + return false_e; +} + +bool_e gtkwindow_dequeue(GtkWindow_t *w, uint32_t *index) +{ + if (w) + { + image_t *img; + bool_e ret = false_e; + //DVP_PRINT(DVP_ZONE_VIDEO, "Attempting to dequeue from GTK\n"); + ret = queue_read(w->dequeue, true_e, &img); + if (ret) + { + DVP_PRINT(DVP_ZONE_VIDEO, "Dequeued %p\n", img); + *index = gtkwindow_search_index(w, img->plane[0].ptr); + DVP_PRINT(DVP_ZONE_VIDEO, "Dequeueing %u\n", *index); + } + return ret; + } + else + return false_e; +} + +uint32_t gtkwindow_length(GtkWindow_t *w, uint32_t index) +{ + if (w) + { + uint32_t len=0, p = 0; + for (p = 0; p < w->images[index]->numPlanes; p++) + { + len += w->images[index]->plane[p].numBytes; + } + return len; + } + else + return 0; +} + + + diff --git a/source/dvp/dvp_display/include/gfx_display.h b/source/dvp/dvp_display/include/gfx_display.h new file mode 100644 index 0000000..e111f8b --- /dev/null +++ b/source/dvp/dvp_display/include/gfx_display.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _GFX_FILE_H_ +#define _GFX_FILE_H_ + +#include + +#ifndef _GFX_DISPLAY_T +#define _GFX_DISPLAY_T +typedef void * gfx_display_t; +#endif + +void gfx_display_destroy(gfx_display_t **pgfxd); + +gfx_display_t *gfx_display_create(char *filename); + +bool_e gfx_display_allocate(gfx_display_t *gfxd, uint32_t numBuf, uint32_t width, uint32_t height, fourcc_t color); + +bool_e gfx_display_free(gfx_display_t *gfxd); + +image_t *gfx_display_acquire(gfx_display_t *gfxd, void **pHandle); + +void gfx_display_release(gfx_display_t *gfxd, image_t **pimg, void *handle); + +bool_e gfx_display_queue(gfx_display_t *gfxd, void *ptr); + +bool_e gfx_display_dequeue(gfx_display_t *gfxd, void **pptr); + +uint32_t gfx_display_length(gfx_display_t *gfxd); + +#endif + + diff --git a/source/dvp/dvp_display/include/gtkwindow.h b/source/dvp/dvp_display/include/gtkwindow.h new file mode 100644 index 0000000..7112f36 --- /dev/null +++ b/source/dvp/dvp_display/include/gtkwindow.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _GTK_WINDOW_H_ +#define _GTK_WINDOW_H_ + +#include +#include + +#define GTK_MAX_IMAGES (10) + +typedef struct _gtk_window_t { + GtkWidget *window; + GtkWidget *draw_area; + uint32_t width; + uint32_t height; + image_t *fb[2]; /**< Internal framebuffers */ + uint32_t fi; /**< active frame buffer index */ + image_t **images; + bitfield_t active; + queue_t *queue; + queue_t *dequeue; + uint32_t curImg; + uint32_t numImg; + mutex_t lock; + bool_e bRunning; + thread_t hMain; + bool_e bRendering; + thread_t hRender; + event_t wait; +} GtkWindow_t; + +#ifdef __cplusplus +extern "C" { +#endif + +void gtkwindow_close(GtkWindow_t *w); +GtkWindow_t *gtkwindow_open(const char *title); + +bool_e gtkwindow_free(GtkWindow_t *w); +bool_e gtkwindow_allocate(GtkWindow_t *w, uint32_t width, uint32_t height, fourcc_t color, uint32_t numImages); + +void * gtkwindow_acquire(GtkWindow_t *w, uint32_t *index); +bool_e gtkwindow_release(GtkWindow_t *w, void *ptr, uint32_t index); + +bool_e gtkwindow_queue(GtkWindow_t *w, uint32_t index); +bool_e gtkwindow_dequeue(GtkWindow_t *w, uint32_t *index); + +uint32_t gtkwindow_length(GtkWindow_t *w, uint32_t index); +void *gtkwindow_search_buffer(GtkWindow_t *w, uint32_t index); +uint32_t gtkwindow_search_index(GtkWindow_t * w, void * ptr); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/source/dvp/dvp_display/include/qnxscreen_api.h b/source/dvp/dvp_display/include/qnxscreen_api.h new file mode 100644 index 0000000..ce2cbbf --- /dev/null +++ b/source/dvp/dvp_display/include/qnxscreen_api.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _QNXSCREEN_API_H_ +#define _QNXSCREEN_API_H_ + +#include + +#if defined(__QNX__) +#include +#include + +#define QNXSCREEN_INVALID_INDEX (0xFFFFFFFF) +#define QNXSCREEN_MAX_INDEX 32 + +struct qnxscreen_img_metrics { + int left; + int top; + int width; + int height; +}; + +struct qnxscreen_api { + screen_window_t win; + screen_context_t ctx; + screen_buffer_t buf[QNXSCREEN_MAX_INDEX]; + struct qnxscreen_img_metrics metrics; + int pfmt; + uint32_t count; + bitfield_t used; + mutex_t m_lock; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +struct qnxscreen_api *qnxscreen_open(void); +void qnxscreen_close(struct qnxscreen_api **q); +bool_e qnxscreen_post(struct qnxscreen_api *q, uint32_t index); +bool_e qnxscreen_free(struct qnxscreen_api *q); +bool_e qnxscreen_allocate(struct qnxscreen_api *q, + uint32_t width, uint32_t height, + uint32_t count, fourcc_t color); +void *qnxscreen_acquire(struct qnxscreen_api *q, uint32_t *index); +bool_e qnxscreen_release(struct qnxscreen_api *q, void *buffer, uint32_t index); +uint32_t qnxscreen_length(struct qnxscreen_api *q, uint32_t index); +uint32_t qnxscreen_search_buffer(struct qnxscreen_api *q, void *buffer); +void *qnxscreen_search_index(struct qnxscreen_api *q, uint32_t index); +bool_e qnxscreen_rotate(struct qnxscreen_api *q, int32_t angle); +bool_e qnxscreen_mirror(struct qnxscreen_api *q, bool_e mirror); +bool_e qnxscreen_position(struct qnxscreen_api *q, + uint32_t x, uint32_t y, uint32_t w, uint32_t h); +bool_e qnxscreen_transparency(struct qnxscreen_api *q, uint32_t alpha); +bool_e qnxscreen_metrics(struct qnxscreen_api *q, + uint32_t *width, uint32_t *height); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + diff --git a/source/dvp/dvp_display/include/surfaceflinger.h b/source/dvp/dvp_display/include/surfaceflinger.h new file mode 100644 index 0000000..c742fa2 --- /dev/null +++ b/source/dvp/dvp_display/include/surfaceflinger.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SURFACEFLINGER_H_ +#define _SURFACEFLINGER_H_ + +#if defined(ANDROID) && (defined(ICS) || defined(JELLYBEAN)) + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _SURFACEFLINGER_T_ +#define _SURFACEFLINGER_T_ +typedef void * surfaceflinger_t; +#endif + +void surfaceflinger_destroy(surfaceflinger_t **psf); + +surfaceflinger_t *surfaceflinger_create(uint32_t width, + uint32_t height); + +void surfaceflinger_free(surfaceflinger_t *sf); + +bool_e surfaceflinger_allocate(surfaceflinger_t *sf, + uint32_t buffer_width, + uint32_t buffer_height, + int32_t numBuffers, + int32_t format); + +bool_e surfaceflinger_acquire(surfaceflinger_t *sf, void **pHandle, uint8_t **ptrs, int32_t *stride); + +bool_e surfaceflinger_release(surfaceflinger_t *sf, void *handle); + +bool_e surfaceflinger_enqueue(surfaceflinger_t *sf, void *handle); + +bool_e surfaceflinger_dequeue(surfaceflinger_t *sf, void **pHandle); + +bool_e surfaceflinger_drop(surfaceflinger_t *sf, void *handle); + +bool_e surfaceflinger_set_crop(surfaceflinger_t *sf, + uint32_t crop_left, + uint32_t crop_top, + uint32_t crop_width, + uint32_t crop_height); + +bool_e surfaceflinger_set_position(surfaceflinger_t *sf, + uint32_t left, + uint32_t top); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif // _SURFACEFLINGER_H_ + diff --git a/source/dvp/dvp_display/include/v4l2_api.h b/source/dvp/dvp_display/include/v4l2_api.h new file mode 100644 index 0000000..bf7c178 --- /dev/null +++ b/source/dvp/dvp_display/include/v4l2_api.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _V4L2_API_H_ +#define _V4L2_API_H_ + +#include + +#if defined(ANDROID) || defined(LINUX) +#include +#include +#include +#include +#include + +// must also set: +// $ echo "2lcd" > /sys/devices/platform/omapdss/overlay2/manager +// $ echo "3" > /sys/devices/platform/omapdss/overlay2/zorder +// $ echo "2" > /sys/devices/platform/omapdss/overlay1/zorder +// $ echo "1" > /sys/devices/platform/omapdss/overlay0/zorder +#if defined(ANDROID) && (defined(BLAZE) || defined(SDP)) +#define V4L2_DISPLAY_DEVICE 1 // /dev/video1 == vid2 == overlay2 (bug in 2.6.32/35?) +#define V4L2_DISPLAY_COLOR FOURCC_UYVY +#elif defined(LINUX) && (defined(BLAZE) || defined(SDP)) +#define V4L2_DISPLAY_DEVICE 2 // /dev/video2 == overlay2 +#define V4L2_DISPLAY_COLOR FOURCC_UYVY +#else +#define V4L2_DISPLAY_DEVICE 1 // /dev/video1 == vid2 == overlay2 +#define V4L2_DISPLAY_COLOR FOURCC_UYVY +#endif +#define V4L2_INVALID_INDEX (0xFFFFFFFF) + +typedef struct _v4l2_api_t +{ + int device; + bool_e nonblocking; + struct v4l2_format format; + struct v4l2_requestbuffers reqbuf; + struct v4l2_capability capability; + struct v4l2_buffer *bufDesc; + void **buffers; + uint32_t count; + bool_e streaming;/**< Indicates if streaming is on currently */ + bitfield_t used; + uint32_t active; /**< Number of Active Buffers */ + mutex_t m_lock; +} v4l2_api_t; + +#ifdef __cplusplus +extern "C" { +#endif + +v4l2_api_t *v4l2_open(int deviceNum, int flags, bool_e nonblocking); +void v4l2_close(v4l2_api_t **v); +int v4l2_wait(v4l2_api_t *v); +bool_e v4l2_queue(v4l2_api_t *v, uint32_t index, uint32_t type); +bool_e v4l2_dequeue(v4l2_api_t *v, uint32_t *index, uint32_t type); +bool_e v4l2_start(v4l2_api_t *v, uint32_t type); +bool_e v4l2_stop(v4l2_api_t *v, uint32_t type); +bool_e v4l2_control_get(v4l2_api_t *v, int control, int *value); +bool_e v4l2_control_set(v4l2_api_t *v, int control, int value); +bool_e v4l2_crop(v4l2_api_t *v, uint32_t left, uint32_t top, uint32_t width, uint32_t height); +bool_e v4l2_free(v4l2_api_t *v); +bool_e v4l2_allocate(v4l2_api_t *v, uint32_t width, uint32_t height, uint32_t count, fourcc_t color, int fmtType); +void *v4l2_acquire(v4l2_api_t *v, uint32_t *index); +bool_e v4l2_release(v4l2_api_t *v, void *buffer, uint32_t index); +void v4l2_query_print(v4l2_api_t *v); +uint32_t v4l2_length(v4l2_api_t *v, uint32_t index); +uint32_t v4l2_search_buffer(v4l2_api_t *v, void *buffer); +void *v4l2_search_index(v4l2_api_t *v, uint32_t index); +bool_e v4l2_rotate(v4l2_api_t *v, int32_t angle); +bool_e v4l2_mirror(v4l2_api_t *v, bool_e mirror); +bool_e v4l2_position(v4l2_api_t *v, uint32_t x, uint32_t y, uint32_t w, uint32_t h); +bool_e v4l2_transparency(v4l2_api_t *v, uint32_t flags, uint32_t colorkey); +bool_e v4l2_metrics(v4l2_api_t *v, uint32_t *width, uint32_t *height); +void v4l2_query_formats(v4l2_api_t *v, uint32_t type); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + diff --git a/source/dvp/dvp_display/include/w32window.h b/source/dvp/dvp_display/include/w32window.h new file mode 100644 index 0000000..7d488fb --- /dev/null +++ b/source/dvp/dvp_display/include/w32window.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _W32_WINDOW_H_ +#define _W32_WINDOW_H_ + +#include + +#define W32_MAX_IMAGES (10) + +typedef struct _w32_window_t { + WNDCLASS class; + HWND window; + ATOM atom; + TCHAR className[MAX_PATH]; + TCHAR windowName[MAX_PATH]; + uint32_t width; + uint32_t height; + image_t *fb[2]; /**< Internal framebuffers */ + uint32_t fi; /**< active frame buffer index */ + image_t **images; + bitfield_t active; + queue_t *queue; + queue_t *dequeue; + uint32_t curImg; + uint32_t numImg; + mutex_t lock; + bool_e bRunning; + thread_t hMain; + bool_e bRendering; + thread_t hRender; + event_t wait; +} W32Window_t; + +#ifdef __cplusplus +extern "C" { +#endif + +void w32window_close(W32Window_t *w); +W32Window_t *w32window_open(const char *title); + +bool_e w32window_free(W32Window_t *w); +bool_e w32window_allocate(W32Window_t *w, uint32_t width, uint32_t height, fourcc_t color, uint32_t numImages); + +void * w32window_acquire(W32Window_t *w, uint32_t *index); +bool_e w32window_release(W32Window_t *w, void *ptr, uint32_t index); + +bool_e w32window_queue(W32Window_t *w, uint32_t index); +bool_e w32window_dequeue(W32Window_t *w, uint32_t *index); + +uint32_t w32window_length(W32Window_t *w, uint32_t index); +void *w32window_search_buffer(W32Window_t *w, uint32_t index); +uint32_t w32window_search_index(W32Window_t * w, void * ptr); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/source/dvp/dvp_display/nativewindow/Android.mk b/source/dvp/dvp_display/nativewindow/Android.mk new file mode 100644 index 0000000..7dd9a8e --- /dev/null +++ b/source/dvp/dvp_display/nativewindow/Android.mk @@ -0,0 +1,35 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_ANDROID_VERSION),ICS) +BUILD_ANW:=1 +else ifeq ($(TARGET_ANDROID_VERSION), JELLYBEAN) +BUILD_ANW:=1 +endif + +ifeq ($(BUILD_ANW),1) + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CPPFLAGS := $(DVP_DEBUGGING) $(DVP_CPPFLAGS) +LOCAL_SRC_FILES := anativewindow.cpp +LOCAL_C_INCLUDES := $(DVP_INCLUDES) +LOCAL_MODULE := libanw +include $(BUILD_STATIC_LIBRARY) + +endif + diff --git a/source/dvp/dvp_display/nativewindow/anativewindow.cpp b/source/dvp/dvp_display/nativewindow/anativewindow.cpp new file mode 100644 index 0000000..70acef8 --- /dev/null +++ b/source/dvp/dvp_display/nativewindow/anativewindow.cpp @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(ANDROID) && (defined(ICS) || defined(JELLYBEAN)) + +#include +#include +#include + +#define ANW_ERROR(status, string) { \ + if (status < 0) { \ + DVP_PRINT(DVP_ZONE_ERROR, "%s[%u] %s status = %d\n", __FUNCTION__, __LINE__, string, status); \ + }\ +} + +void anativewindow_destroy(anativewindow_t **panw) +{ + if (panw && *panw) + { + anativewindow_t *anw = *panw; + free(anw); + *panw = NULL; + } +} + +anativewindow_t *anativewindow_create(const sp &window) +{ + anativewindow_t *anw = (anativewindow_t *)calloc(1, sizeof(anativewindow_t)); + if (anw) + { + // clear the entire structure + memset(anw, 0, sizeof(anativewindow_t)); + anw->m_window = window; + } + return anw; +} + +void anativewindow_free(anativewindow_t *anw) +{ + status_t status; + + // disconnect from the native window + status = native_window_api_disconnect(anw->m_window.get(), NATIVE_WINDOW_API_CAMERA); + ANW_ERROR(status,"DISCONNECT"); + + anw->m_window.clear(); + free(anw->m_native_buffers); +} + +bool_e anativewindow_allocate(anativewindow_t *anw, + uint32_t buffer_width, + uint32_t buffer_height, + int32_t numBuffers, + int32_t format, + bool flipH) +{ + if (format != ANW_NV12_FORMAT) + return false_e; + + if (anw) + { + status_t status = 0; + + anw->m_format = format; + anw->m_usage = GRALLOC_USAGE_HW_TEXTURE | + GRALLOC_USAGE_HW_RENDER | + GRALLOC_USAGE_SW_READ_OFTEN | // Non-cached ? If you use RARELY it will complain + GRALLOC_USAGE_SW_WRITE_NEVER; // can't access from UVA + anw->m_numBuffers = numBuffers; + anw->m_width = buffer_width; + anw->m_height = buffer_height; + anw->m_native_buffers = (ANativeWindowBuffer **)calloc(numBuffers, sizeof(ANativeWindowBuffer *)); + DVP_PRINT(DVP_ZONE_VIDEO, "Created %u pointers in native array %p\n", numBuffers, anw->m_native_buffers); + if (anw->m_native_buffers == NULL) { + return false_e; + } + + // connect to the native window API + status = native_window_api_connect(anw->m_window.get(), NATIVE_WINDOW_API_CAMERA); + ANW_ERROR(status,"CONNECT"); + + // set the scaling mode of the windows + status = native_window_set_scaling_mode(anw->m_window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); + ANW_ERROR(status,"SCALING"); + +#if defined(BLAZE_TABLET) && defined(ICS) + // set the layout of the buffer + status = native_window_set_buffers_layout(anw->m_window.get(), NATIVE_WINDOW_BUFFERS_LAYOUT_PROGRESSIVE); // progressive + ANW_ERROR(status,"LAYOUT"); +#endif + + // set the format of the buffer + status = native_window_set_buffers_format(anw->m_window.get(), anw->m_format); + ANW_ERROR(status,"FORMAT"); + + // setup the dimensions + status = native_window_set_buffers_dimensions(anw->m_window.get(), anw->m_width, anw->m_height); + ANW_ERROR(status,"DIM"); + + if (flipH) { + // set the horizontal flip + status = native_window_set_buffers_transform(anw->m_window.get(), NATIVE_WINDOW_TRANSFORM_FLIP_H); + ANW_ERROR(status,"TRANSFORM FLIP HORIZONTAL"); + } + + // set the usage of the GRALLOC buffers + status = native_window_set_usage(anw->m_window.get(), anw->m_usage); + if (status < 0 ) { + DVP_PRINT(DVP_ZONE_ERROR, "%s[%u] USAGE status = %d (0x%08x)\n", __FUNCTION__, __LINE__, status, anw->m_usage); + } + + // set the number of buffers required. + status = native_window_set_buffer_count(anw->m_window.get(), anw->m_numBuffers); + ANW_ERROR(status,"COUNT"); + + // get the number of dequeueable buffers + status = anw->m_window->query(anw->m_window.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, (int*)&anw->m_nonqueue); + ANW_ERROR(status,"QUERY NONQUEUE"); + + for (uint32_t n = 0; n < anw->m_numBuffers; n++) + { + status = anw->m_window->dequeueBuffer(anw->m_window.get(), &anw->m_native_buffers[n]); + if (status != 0) { + DVP_PRINT(DVP_ZONE_ERROR, "%s[%u] %s status = %d\n", __FUNCTION__, __LINE__, "Failed window buffer dequeue!", status); \ + return false_e; + } + if (anw->m_native_buffers[n]) + { + native_handle_t *hdl = (native_handle_t *)anw->m_native_buffers[n]->handle; + hdl = hdl; // warnings + DVP_PRINT(DVP_ZONE_VIDEO, "ANativeBuffer %p => dim %dx%d stride %d usage %d format %d handle %p numFds=%u\n", + anw->m_native_buffers[n], + anw->m_native_buffers[n]->width, + anw->m_native_buffers[n]->height, + anw->m_native_buffers[n]->stride, + anw->m_native_buffers[n]->usage, + anw->m_native_buffers[n]->format, + anw->m_native_buffers[n]->handle, + hdl->numFds); + } + } + return true_e; + } + return false_e; +} + +bool_e anativewindow_acquire(anativewindow_t *anw, void **pHandle, uint8_t **ptrs, int32_t *stride) +{ + bool_e ret = false_e; + if (anw && anw->m_native_buffers && anw->m_curIdx < anw->m_numBuffers && anw->m_native_buffers[anw->m_curIdx]) + { + status_t status = 0; + GraphicBufferMapper &mapper = GraphicBufferMapper::get(); + Rect bounds; + + bounds.left = 0; + bounds.right = anw->m_width; + bounds.top = 0; + bounds.bottom = anw->m_height; + + status = anw->m_window->lockBuffer(anw->m_window.get(), anw->m_native_buffers[anw->m_curIdx]); + ANW_ERROR(status,"LOCK WINDOW"); + + status = mapper.lock((buffer_handle_t)anw->m_native_buffers[anw->m_curIdx]->handle, anw->m_usage, bounds, (void **)ptrs); + ANW_ERROR(status,"LOCK"); + if (status == NO_ERROR) + { + //DVP_PRINT(DVP_ZONE_VIDEO, "ptrs = {%p, %p, %p}\n", ptrs[0], ptrs[1], ptrs[2]); + *pHandle = (void *)anw->m_native_buffers[anw->m_curIdx]->handle; + *stride = anw->m_native_buffers[anw->m_curIdx]->stride; + ret = true_e; + } + + anw->m_curIdx++; + } + return ret; +} + +bool_e anativewindow_release(anativewindow_t *anw, void *handle) +{ + if (anw && handle) + { + GraphicBufferMapper &mapper = GraphicBufferMapper::get(); + status_t status = NO_ERROR; + + for (uint32_t i = 0; i < anw->m_numBuffers; i++) + { + if (anw->m_native_buffers[i] && handle == anw->m_native_buffers[i]->handle) + { + status = mapper.unlock((buffer_handle_t)anw->m_native_buffers[i]->handle); + ANW_ERROR(status,"UNLOCK"); + status = anw->m_window->cancelBuffer(anw->m_window.get(), anw->m_native_buffers[i]); + ANW_ERROR(status,"CANCEL"); + return true_e; + } + } + } + return false_e; +} + +bool_e anativewindow_enqueue(anativewindow_t *anw, void *handle) +{ + if (anw && handle) + { + GraphicBufferMapper &mapper = GraphicBufferMapper::get(); + for (uint32_t i = 0; i < anw->m_numBuffers; i++) { + if (handle == anw->m_native_buffers[i]->handle) { + status_t status; + + status = mapper.unlock((buffer_handle_t)anw->m_native_buffers[i]->handle); + if (status < 0 ) { + DVP_PRINT(DVP_ZONE_ERROR, "%s[%u] %p UNLOCK status = %d\n", __FUNCTION__, __LINE__, anw->m_native_buffers[i], status); + } + status = anw->m_window->queueBuffer(anw->m_window.get(), anw->m_native_buffers[i]); + if (status < 0 ) { + DVP_PRINT(DVP_ZONE_ERROR, "%s[%u] %p QUEUE status = %d\n", __FUNCTION__, __LINE__, anw->m_native_buffers[i], status); + } + return true_e; + } + } + } + return false_e; +} + +bool_e anativewindow_dequeue(anativewindow_t *anw, void **pHandle) +{ + if (anw) + { + GraphicBufferMapper &mapper = GraphicBufferMapper::get(); + status_t status; + uint8_t *ptrs[3] = {NULL, NULL, NULL}; + Rect bounds; + uint32_t lockRetries = 10; + ANativeWindowBuffer *nativeBuffer = NULL; + + bounds.left = 0; + bounds.right = anw->m_width; + bounds.top = 0; + bounds.bottom = anw->m_height; + + // Now we're dequeuing a different buffer from the window... + + status = anw->m_window->dequeueBuffer(anw->m_window.get(), &nativeBuffer); + if (status < 0 ) { + DVP_PRINT(DVP_ZONE_ERROR, "%s[%u] %p DEQUEUE status = %d\n", __FUNCTION__, __LINE__, nativeBuffer, status); + } + + // early exit + if (nativeBuffer == NULL) + return false_e; + + status = anw->m_window->lockBuffer(anw->m_window.get(), nativeBuffer); + if (status < 0 ) { + DVP_PRINT(DVP_ZONE_ERROR, "%s[%u] %p LOCKWINDOW status = %d\n", __FUNCTION__, __LINE__, nativeBuffer, status); + } + do { + status = mapper.lock(nativeBuffer->handle, anw->m_usage, bounds, (void **)ptrs); + if (status < 0 ) { + DVP_PRINT(DVP_ZONE_ERROR, "%s[%u] %p LOCK status = %d\n", __FUNCTION__, __LINE__, nativeBuffer, status); + } + } while (status != NO_ERROR && lockRetries--); + + if (pHandle) + *pHandle = (void *)nativeBuffer->handle; + + return true_e; + } + return false_e; +} + +bool_e anativewindow_drop(anativewindow_t *anw, void *handle) +{ + if (anw && handle) + { + GraphicBufferMapper &mapper = GraphicBufferMapper::get(); + for (uint32_t i = 0; i < anw->m_numBuffers; i++) { + if (handle == anw->m_native_buffers[i]->handle) { + status_t status; + + status = mapper.unlock((buffer_handle_t)anw->m_native_buffers[i]->handle); + if (status < 0 ) { + DVP_PRINT(DVP_ZONE_ERROR, "%s[%u] %p UNLOCK status = %d\n", __FUNCTION__, __LINE__, anw->m_native_buffers[i], status); + } + status = anw->m_window->cancelBuffer(anw->m_window.get(), anw->m_native_buffers[i]); + if (status < 0 ) { + DVP_PRINT(DVP_ZONE_ERROR, "%s[%u] %p CANCEL status = %d\n", __FUNCTION__, __LINE__, anw->m_native_buffers[i], status); + } + if (status >= 0) + return true_e; + } + } + } + return false_e; +} + +bool_e anativewindow_set_crop(anativewindow_t *anw, + uint32_t crop_left, + uint32_t crop_top, + uint32_t crop_width, + uint32_t crop_height) +{ + if (anw) + { + status_t status = 0; + android_native_rect_t crop = {crop_left, crop_top, crop_width, crop_height}; + + if (!crop_left && !crop_top && !crop_width && !crop_height) + status = native_window_set_crop(anw->m_window.get(), NULL); + else + status = native_window_set_crop(anw->m_window.get(), &crop); + + ANW_ERROR(status,"CROP"); + + return (status < 0 ? false_e : true_e); + } + return false_e; +} + +#endif + + diff --git a/source/dvp/dvp_display/qnxscreen/concerto.mak b/source/dvp/dvp_display/qnxscreen/concerto.mak new file mode 100644 index 0000000..4e2509a --- /dev/null +++ b/source/dvp/dvp_display/qnxscreen/concerto.mak @@ -0,0 +1,33 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_OS),__QNX__) + +include $(PRELUDE) +TARGET=qnxscreen +TARGETTYPE=library +CSOURCES=qnxscreen_api.c +include $(FINALE) + +# Set the module manually so that we can have 2 builds in one makefile. +_MODULE=qnxscreen_test +include $(PRELUDE) +TARGET=qnxscreen_test +TARGETTYPE=exe +CSOURCES=qnxscreen_test.c +STATIC_LIBS=qnxscreen sosal +SYS_SHARED_LIBS+=socket OMX_Core screen mmosal +include $(FINALE) + +endif diff --git a/source/dvp/dvp_display/qnxscreen/qnxscreen_api.c b/source/dvp/dvp_display/qnxscreen/qnxscreen_api.c new file mode 100644 index 0000000..a7ac3e1 --- /dev/null +++ b/source/dvp/dvp_display/qnxscreen/qnxscreen_api.c @@ -0,0 +1,524 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(__QNX__) + +#include +#include + +#define QNXSCREEN_EXTRA_DEBUG + +void qnxscreen_close(struct qnxscreen_api **q) +{ + if (!q || (*q)) + return; + + /* This should free all the associated context allocated resources */ + screen_destroy_context((*q)->ctx); + + free(*q); + *q = NULL; +} + +struct qnxscreen_api *qnxscreen_open(void) +{ + struct qnxscreen_api *q; + int ret; + + q = calloc(1, sizeof(struct qnxscreen_api)); + + if (!q) { + DVP_PRINT(DVP_ZONE_ERROR, + "(%s) Failure to allocate base struct\n", __func__); + return q; + } + + mutex_init(&q->m_lock); + + ret = screen_create_context(&q->ctx, SCREEN_APPLICATION_CONTEXT); + if (ret) { + DVP_PRINT(DVP_ZONE_ERROR, + "(%s) Failure on screen_create_context: (%d)\n", + __func__, errno); + goto fail; + } + + return q; + +fail: + free(q); + return NULL; +} + +uint32_t qnxscreen_search_buffer(struct qnxscreen_api *q, void *buffer) +{ + uint32_t index = QNXSCREEN_INVALID_INDEX; + + for (index = 0; index < q->count; index++) { + void *tmpbuf_dat; + int ret; + + ret = screen_get_buffer_property_pv(q->buf[index], + SCREEN_PROPERTY_POINTER, + (void **)&tmpbuf_dat); + if (ret) + return QNXSCREEN_INVALID_INDEX; + + if (tmpbuf_dat == buffer) + return index; + } + + if (index >= q->count) + index = QNXSCREEN_INVALID_INDEX; + + return index; +} + +void *qnxscreen_search_index(struct qnxscreen_api *q, uint32_t index) +{ + void *tmpbuf_dat; + int ret; + + if (index > q->count || index > QNXSCREEN_MAX_INDEX) + return NULL; + + ret = screen_get_buffer_property_pv(q->buf[index], SCREEN_PROPERTY_POINTER, + (void **)&tmpbuf_dat); + if (ret) + return NULL; + + return tmpbuf_dat; +} + +bool_e qnxscreen_post(struct qnxscreen_api *q, uint32_t index) +{ + int clipRect[4]; + + if (!q) { + DVP_PRINT(DVP_ZONE_ERROR, + "(%s) OOPS: Invalid struct qnxscreen_api pointer." + " Something is seriously wrong!\n", + __func__); + return false_e; + } + + if (index > q->count || index > QNXSCREEN_MAX_INDEX) { + DVP_PRINT(DVP_ZONE_ERROR, "Invalid index %d\n", index); + return false_e; + } + + clipRect[0] = q->metrics.left; + clipRect[1] = q->metrics.top; + clipRect[2] = q->metrics.left + q->metrics.width; + clipRect[3] = q->metrics.top + q->metrics.height; + + /* Just flush out the only buffer we have */ + if (screen_post_window(q->win, q->buf[index], 1, clipRect, 0)) { + DVP_PRINT(DVP_ZONE_ERROR, + "(%s): Failure on screen_post_window (%d)\n", + __func__, errno); + return false_e; + } + + return true_e; +} + +uint32_t qnxscreen_length(struct qnxscreen_api *q, uint32_t index) +{ + uint32_t len = 0; + int err; + int pformat = 0; + int stride = 0; + + err = screen_get_window_property_iv(q->win, SCREEN_PROPERTY_FORMAT, &pformat); + if (err) { + DVP_PRINT(DVP_ZONE_ERROR, "QNX Screen Length of Buffer is unknown\n"); + return 0; + } + + err = screen_get_buffer_property_iv(q->buf[index], + SCREEN_PROPERTY_STRIDE, &stride); + if (err) { + DVP_PRINT(DVP_ZONE_ERROR, "QNX Screen Stride of Buffer is unknown\n"); + return 0; + } else { + DVP_PRINT(DVP_ZONE_VIDEO, "QNX Screen Buffer Stride is %d bytes\n", stride); + } + + switch (pformat) { + case SCREEN_FORMAT_NV12: + len = stride * q->metrics.height; + len += len / 2; /// @note remember to reverse this outside the function. + break; + default: + len = stride * q->metrics.height; + break; + } + + DVP_PRINT(DVP_ZONE_VIDEO, "QNX Screen Length of Buffer is %u bytes\n", len); + return len; +} + +void *qnxscreen_acquire(struct qnxscreen_api *q, uint32_t *index) +{ + void *buf = NULL; + *index = QNXSCREEN_INVALID_INDEX; + + if (!q) + return NULL; + + mutex_lock(&q->m_lock); + if (bitfield_get(&q->used, index) == false_e) { + mutex_unlock(&q->m_lock); + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Failed to acquire QNX Screen Buffer!\n"); + return NULL; + } + + buf = qnxscreen_search_index(q, *index); +#ifdef QNXSCREEN_EXTRA_DEBUG + DVP_PRINT(DVP_ZONE_VIDEO, "QNX Screen Acquiring %p index %u\n", buf, *index); +#endif + mutex_unlock(&q->m_lock); + + return buf; +} + +bool_e qnxscreen_release(struct qnxscreen_api *q, void *buffer, uint32_t index) +{ + bool_e ret = false_e; + + if (!q) + return false_e; + + mutex_lock(&q->m_lock); + if (index < q->count) { +#ifdef QNXSCREEN_EXTRA_DEBUG + DVP_PRINT(DVP_ZONE_VIDEO, "QNX Screen Releasing %p index %u\n", buffer, index); +#endif + if (bitfield_rls(&q->used, index) == false_e) { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Failed to release QNX Screen Buffer!\n"); + ret = false_e; + } + } else if (index == QNXSCREEN_INVALID_INDEX) { + index = qnxscreen_search_buffer(q, buffer); + if (index != QNXSCREEN_INVALID_INDEX) { +#ifdef QNXSCREEN_EXTRA_DEBUG + DVP_PRINT(DVP_ZONE_VIDEO, "QNX Screen Releasing %p index %u\n", buffer, index); +#endif + if (bitfield_rls(&q->used, index) == false_e) { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Failed to release QNX Screen Buffer!\n"); + } else { + ret = true_e; + } + } else { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Buffer was not a QNX Screen Buffer!\n"); + } + } else { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Buffer was not a QNX Screen Buffer!\n"); + } + mutex_unlock(&q->m_lock); + return ret; +} + +bool_e qnxscreen_free(struct qnxscreen_api *q) +{ + uint32_t i; + + if (!q) + return false_e; + + mutex_lock(&q->m_lock); + screen_destroy_window(q->win); + q->count = 0; + bitfield_deinit(&q->used); + mutex_unlock(&q->m_lock); + return true_e; +} + +bool_e qnxscreen_metrics(struct qnxscreen_api *q, + uint32_t *width, uint32_t *height) +{ + int size[2] = {0}; + int ret; + + if (!q) + return false_e; + + ret = screen_get_window_property_iv(q->win, SCREEN_PROPERTY_SIZE, size); + if (ret) + return false_e; + + *width = size[0]; + *height = size[1]; + return true_e; +} + +bool_e qnxscreen_rotate(struct qnxscreen_api *q, int32_t angle) +{ + int ret; + + ret = screen_set_window_property_iv(q->win, SCREEN_PROPERTY_ROTATION, (int *)&angle); + if (ret) + return false_e; + + return true_e; +} + +bool_e qnxscreen_mirror(struct qnxscreen_api *q, bool_e mirror) +{ + int ret; + int val; + + if (mirror == true_e) + val = 1; + else + val = 0; + + ret = screen_set_window_property_iv(q->win, SCREEN_PROPERTY_MIRROR, &val); + if (ret) + return false_e; + + return true_e; +} + +bool_e qnxscreen_position(struct qnxscreen_api *q, + uint32_t x, uint32_t y, uint32_t w, uint32_t h) +{ + int size[2] = {(int)w, (int)h}; + int pos[2] = {(int)x, (int)y}; + int ret; + + ret = screen_set_window_property_iv(q->win, SCREEN_PROPERTY_POSITION, pos); + if (ret) + return false_e; + + ret = screen_set_window_property_iv(q->win, SCREEN_PROPERTY_SIZE, size); + if (ret) + return false_e; + + return true_e; +} + +bool_e qnxscreen_transparency(struct qnxscreen_api *q, uint32_t alpha) +{ + int ret; + + if (alpha > 255) + alpha = 255; + + ret = screen_set_window_property_iv(q->win, SCREEN_PROPERTY_GLOBAL_ALPHA, (int *)&alpha); + if (ret) + return false_e; + + return true_e; +} + +typedef struct _qnxscreen_pix_to_fourcc_lut_t { + int qnxscreen_fmt; + uint32_t fourcc; +} QNXSCR_to_FOURCC_t; + +QNXSCR_to_FOURCC_t codes[] = { + {SCREEN_FORMAT_UYVY, FOURCC_UYVY}, + {SCREEN_FORMAT_NV12, FOURCC_NV12}, + {SCREEN_FORMAT_RGB888, FOURCC_BGR}, +}; +uint32_t numCodes = dimof(codes); + +/* NOTE: Shouldn't this be more flexible? */ +#define OMX_CAMERA_ALIGNMENT 128 + +bool_e qnxscreen_allocate(struct qnxscreen_api *q, + uint32_t width, uint32_t height, + uint32_t count, fourcc_t color) +{ + bool_e ret = false_e; + int size[2] = {(int)width, (int)height}; + int bsize[2] = {(int)width, (int)height}; + int i; + int pformat = 0; + int err; + int zOrder = 50; + int dispCount = 0; + int formatCount = 0; + int sensitivity = SCREEN_SENSITIVITY_NEVER; + int tranparency = SCREEN_TRANSPARENCY_NONE; + int idleMode = SCREEN_IDLE_MODE_KEEP_AWAKE; + screen_display_t *displays; + screen_display_t display; + int formats[SCREEN_FORMAT_NFORMATS]; + bool_e configured = false_e; + const int usage = SCREEN_USAGE_WRITE | SCREEN_USAGE_NATIVE | SCREEN_USAGE_CAPTURE; + + mutex_lock(&q->m_lock); + + err = screen_create_window_type(&q->win, q->ctx, SCREEN_APPLICATION_WINDOW); + if (err) { + DVP_PRINT(DVP_ZONE_ERROR, + "(%s) Failure on screen_create_window_type: (%d)\n", + __func__, errno); + goto leave; + } + + err = screen_get_context_property_iv(q->ctx, SCREEN_PROPERTY_DISPLAY_COUNT, (void *)&dispCount); + if (err) { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to query the number of displays! err=%d\n",err); + goto leave2; + } + DVP_PRINT(DVP_ZONE_VIDEO, "There are %u displays\n", dispCount); + + err = screen_set_window_property_iv(q->win, SCREEN_PROPERTY_ZORDER, &zOrder); + if (err) { + DVP_PRINT(DVP_ZONE_ERROR, + "(%s) Failure on screen_create_window_type: (%d)\n", + __func__, errno); + goto leave2; + } + + // this tells the window to not receive input events + err = screen_set_window_property_iv(q->win, SCREEN_PROPERTY_SENSITIVITY, &sensitivity); + if (err) { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to set window sensitivity to zero (%d)\n", err); + goto leave2; + } + + // this is not the same as global alpha. + err = screen_set_window_property_iv(q->win, SCREEN_PROPERTY_TRANSPARENCY, &tranparency); + if (err) { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to set window transparency to none (%d)\n", err); + goto leave2; + } + + err = screen_set_window_property_iv(q->win, SCREEN_PROPERTY_USAGE, &usage); + if (err) { + DVP_PRINT(DVP_ZONE_ERROR, + "(%s) Failure setting USAGE window property: (%d)\n", + __func__, errno); + goto leave2; + } + + err = screen_set_window_property_iv(q->win, SCREEN_PROPERTY_IDLE_MODE, &idleMode); + if (err) { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to set window idle mode to keep awake (%d)\n", err); + goto leave2; + } + + err = screen_set_window_property_iv(q->win, SCREEN_PROPERTY_SIZE, size); + if (err) + goto leave2; + + err = screen_set_window_property_iv(q->win, SCREEN_PROPERTY_SOURCE_SIZE, bsize); + if (err) { + DVP_PRINT(DVP_ZONE_ERROR, + "(%s) Failure setting SOURCE_SIZE window property: (%d)\n", + __func__, errno); + goto leave2; + } + + if (width % OMX_CAMERA_ALIGNMENT) + bsize[0] = ( (width / OMX_CAMERA_ALIGNMENT) + 1) * OMX_CAMERA_ALIGNMENT; + + err = screen_set_window_property_iv(q->win, SCREEN_PROPERTY_BUFFER_SIZE, bsize); + if (err) { + DVP_PRINT(DVP_ZONE_ERROR, + "(%s) Failure setting BUFFER_SIZE window property: (%d)\n", + __func__, errno); + goto leave2; + } + + for (i = 0; i < numCodes; i++) { + if (color == codes[i].fourcc) + pformat = codes[i].qnxscreen_fmt; + } + if (pformat == 0) + { + DVP_PRINT(DVP_ZONE_ERROR, "Unknown FOURCC 0x%x\n", color); + goto leave2; + } + else + { + DVP_PRINT(DVP_ZONE_VIDEO, "Configuring display for fmt:%d\n", pformat); + } + + screen_get_window_property_pv(q->win, SCREEN_PROPERTY_DISPLAY, (void *)&display); + screen_get_display_property_iv(display, SCREEN_PROPERTY_FORMAT_COUNT, (void *)&formatCount); + screen_get_display_property_iv(display, SCREEN_PROPERTY_FORMATS, (void *)formats); + for (i = 0; i < formatCount; i++) + { + DVP_PRINT(DVP_ZONE_VIDEO, "Display %p supports format %d\n", display, formats[i]); + } + configured = false_e; + for (i = 0; i < formatCount; i++) + { + if (formats[i] == pformat) + { + err = screen_set_window_property_iv(q->win, SCREEN_PROPERTY_FORMAT, &pformat); + if (err) + { + DVP_PRINT(DVP_ZONE_ERROR, "screen_set_window_property_iv() returned %d when setting format %d\n", err, pformat); + goto leave2; + } + else + configured = true_e; + } + } + if (configured == false_e) + { + DVP_PRINT(DVP_ZONE_ERROR, "Display %p does not support format %d\n", display, pformat); + goto leave2; + } + + err = screen_create_window_buffers(q->win, (int)count); + if (err) { + DVP_PRINT(DVP_ZONE_ERROR, "screen_create_window_buffers() returned %d when requesting %u buffers\n", err, count); + goto leave2; + } + + err = screen_get_window_property_pv(q->win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)q->buf); + if (err) { + perror("screen_get_window_property(SCREEN_PROPERTY_RENDER_BUFFERS)"); + goto leave2; + } + + q->count = count; + q->pfmt = pformat; + q->metrics.left = 0; + q->metrics.top = 0; + q->metrics.width = size[0]; + q->metrics.height = size[1]; + bitfield_init(&q->used, q->count); + + DVP_PRINT(DVP_ZONE_VIDEO, "QNX Screen Configuring %u images for %ux%u fmt:%d\n", + count, size[0], size[1], pformat); + for (i = 0; i < q->count; i++) + { + void *ptr = NULL; + screen_get_buffer_property_pv(q->buf[i], SCREEN_PROPERTY_POINTER, &ptr); + DVP_PRINT(DVP_ZONE_VIDEO, "\t[%u] ptr=%p\n", i, ptr); + } + ret = true_e; +leave: + mutex_unlock(&q->m_lock); + return ret; + +leave2: + screen_destroy_window(q->win); + mutex_unlock(&q->m_lock); + return ret; +} + +#endif + diff --git a/source/dvp/dvp_display/qnxscreen/qnxscreen_test.c b/source/dvp/dvp_display/qnxscreen/qnxscreen_test.c new file mode 100644 index 0000000..0ce603f --- /dev/null +++ b/source/dvp/dvp_display/qnxscreen/qnxscreen_test.c @@ -0,0 +1,249 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +uint32_t width; +uint32_t height; +uint32_t count; +uint32_t fourcc; +char fourcc_str[5]; +uint32_t iter; +uint32_t fps; +bool_e f_running = false_e; +char filename[255]; +uint32_t alpha; +option_t opts[] = { + {OPTION_TYPE_INT, &width, sizeof(width), "-w", "--width", "Width of buffer"}, + {OPTION_TYPE_INT, &height, sizeof(height), "-h", "--height", "Height of buffer"}, + {OPTION_TYPE_INT, &count, sizeof(count), "-#", "--count", "Number of buffers"}, + {OPTION_TYPE_INT, &fps, sizeof(fps), "-r", "--fps", "Frame rate"}, + {OPTION_TYPE_STRING, &fourcc_str, sizeof(fourcc_str), "-c", "--fourcc", "FOURCC Code as string (UYVY|NV12|BGR3) "}, + {OPTION_TYPE_INT, &iter, sizeof(iter), "-i", "--iterations", "Number of alloc/free cycles"}, + {OPTION_TYPE_STRING, filename, sizeof(filename), "-f", "--file", "Uses a file to render to the screen"}, + {OPTION_TYPE_INT, &alpha, sizeof(alpha), "-a", "--alpha", "Set the global alpha on the screen"}, +}; +size_t numOpts = dimof(opts); + +typedef struct _yuv_color_t { + uint32_t uyvy; + uint8_t y; + uint8_t cb; + uint8_t cr; +} yuv_color_t; + +#define SET_UYVY(y,cb,cr) ((y << 24)|(cr << 16)|(y << 8)|cb) + +yuv_color_t sdtv_colors[] = { + {SET_UYVY(180,128,128), 180, 128, 128}, // white + {SET_UYVY(162, 44,142), 162, 44, 142}, // Yellow + {SET_UYVY(131,156, 44), 131, 156, 44}, // Cyan + {SET_UYVY(112, 72, 58), 112, 72, 58}, // Green + {SET_UYVY( 84,184,198), 84, 184, 198}, // Magenta + {SET_UYVY( 65,100,212), 65, 100, 212}, // Red + {SET_UYVY( 35,212,114), 35, 212, 114}, // Blue + {SET_UYVY( 16,128,128), 16, 128, 128}, // Black +}; +uint32_t numSDTVColors = dimof(sdtv_colors); + +yuv_color_t hdtv_colors[] = { + {SET_UYVY(180,128,128), 180, 128, 128}, // White + {SET_UYVY(168, 44,136), 168, 44, 136}, // Yellow + {SET_UYVY(145,147, 44), 145, 147, 44}, // Cyan + {SET_UYVY(133, 63, 52), 133, 63, 52}, // Green + {SET_UYVY( 63,193,204), 64, 193, 204}, // Magenta + {SET_UYVY( 51,109,212), 51, 109, 212}, // Red + {SET_UYVY( 28,212,120), 28, 212, 120}, // Blue + {SET_UYVY( 16,128,128), 16, 128, 128}, // Black +}; +uint32_t numHDTVColors = dimof(hdtv_colors); + +void qnxscreen_test_file(uint8_t *buffer, uint32_t width, uint32_t height, uint32_t stride, FILE *f) +{ + uint32_t y, i, l; + + for (y = 0; y < height; y++) { + i = (y * stride); + l = width * sizeof(uint16_t); + if (fread(&buffer[i], 1, l, f) == 0) + printf("Can't read file\n"); + } +} + +void qnxscreen_test_fill(uint8_t *buffer, uint32_t width, uint32_t height, uint32_t stride, fourcc_t color) +{ + uint32_t bar_width = width / numSDTVColors; + uint32_t x, y, i; + //printf("bar_width = %u\n", bar_width); + if (color == FOURCC_NV12) { + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + i = (y * stride) + (x * sizeof(uint8_t)); + buffer[i] = sdtv_colors[x / bar_width].y; + } + } + for (y = 0; y < height/2; y++) { +#if 1 + for (x = 0; x < width/2; x++) { + i = (height * stride) + (y * stride) + (x * sizeof(uint16_t)); + buffer[i+0] = sdtv_colors[(x*2) / bar_width].cb; + buffer[i+1] = sdtv_colors[(x*2) / bar_width].cr; + } +#else + i = (height * stride) + (y * stride); + memset(&buffer[i], 128, width); +#endif + } + } else if (color == FOURCC_UYVY) { + for (y = 0; y < height; y++) { + for (x = 0; x < width; x += 2) { // increment over pixel pairs + uint32_t *p32 = NULL; + i = (y * stride) + (x * sizeof(uint16_t)); // account that each "pixel" is 2 bytes + p32 = (uint32_t *)&buffer[i]; + *p32 = sdtv_colors[x / bar_width].uyvy; + } + } + } +} + +int main(int argc, char *argv[]) +{ + int err = 0; + bool_e useFile = false_e; + FILE *f = NULL; + event_t timer; + struct qnxscreen_api *q; + uint32_t c, i = 0; + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + +#if defined(DVP_RUNTIME_DEBUG) + debug_get_zone_mask("DVP_ZONE_MASK", &dvp_zone_mask); +#endif + + width = 640; + height = 480; + count = 4; + iter = 1; + fps = 30; + alpha = 255; + strcpy(fourcc_str, "NV12"); + memset(filename, 0, sizeof(filename)); + event_init(&timer, true_e); + + option_process(argc, argv, opts, numOpts); + fourcc_str[4] = '\0'; + fourcc = FOURCC_STRING(fourcc_str); + + if (width > SCREEN_DIM_X) + width = SCREEN_DIM_X; + if (height > SCREEN_DIM_Y) + height = SCREEN_DIM_Y; + if (iter == 0) iter = 1; + + DVP_PRINT(DVP_ZONE_ALWAYS, "Rendering %u images %u times to display %ux%u @ %u fps in %s\n",count,iter,width,height,fps,fourcc_str); + + if (filename[0] != '\0') { + useFile = true_e; + DVP_PRINT(DVP_ZONE_ALWAYS, "Opening file %s\n", filename); + f = fopen(filename, "rb"); + if (f == NULL) + useFile = false_e; + } + + q = qnxscreen_open(); + if (!q) { + err++; + goto out; + } + + for (i = 0; i < iter; i++) { + + // allocate a bunch of memory + if (qnxscreen_allocate(q, width, height, count, fourcc) != true_e) { + DVP_PRINT(DVP_ZONE_ALWAYS, "Failed to allocate buffers!\n"); + err++; + continue; + } + + qnxscreen_transparency(q, alpha); + + /* Ensure we're starting the file read from the start */ + if (useFile) rewind(f); + + for (c = 0; c < count; c++) { + uint32_t index = c; + void *buffer = qnxscreen_acquire(q, &index); + uint32_t length; + uint32_t stride; + + if (!buffer) { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to Acquire QNX Screen Buffer!\n"); + continue; + } + + length = qnxscreen_length(q, index); + if (fourcc == FOURCC_UYVY || fourcc == FOURCC_BGR) + stride = length / height; + else if (fourcc == FOURCC_NV12) + stride = length / (height + height/2); + DVP_PRINT(DVP_ZONE_ALWAYS, "Stride of buffer is %u\n", stride); + if (useFile) { + // read from the file + qnxscreen_test_file(buffer, width, height, stride, f); + } else if (fourcc == FOURCC_UYVY || fourcc == FOURCC_NV12) { + // fill the buffer + DVP_PRINT(DVP_ZONE_ALWAYS, "Rendering Test Pattern into Buffer!\n"); + qnxscreen_test_fill(buffer, width, height, stride, fourcc); + } else if (fourcc == FOURCC_BGR) { + uint32_t x,y,i; + uint8_t *pixels = buffer; + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + i = (y * stride) + (x * 3); + pixels[i+0] = 0xFF; // B + pixels[i+1] = 0x00; // G + pixels[i+2] = 0x00; // R + } + } + } + + // post the buffer + qnxscreen_post(q, index); + + event_wait(&timer, 1000 / fps); + } + + // free that memory + if (qnxscreen_free(q) == false_e) { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to free buffers!\n"); + err++; + } + } + qnxscreen_close(&q); + +out: + event_deinit(&timer); + if (useFile) + fclose(f); + DVP_PRINT(DVP_ZONE_ALWAYS, "Number of errors = %u\n", err); + return err; +} diff --git a/source/dvp/dvp_display/surfaceflinger/Android.mk b/source/dvp/dvp_display/surfaceflinger/Android.mk new file mode 100644 index 0000000..3e31960 --- /dev/null +++ b/source/dvp/dvp_display/surfaceflinger/Android.mk @@ -0,0 +1,37 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_ANDROID_VERSION),ICS) +BUILD_SF:=1 +else ifeq ($(TARGET_ANDROID_VERSION),JELLYBEAN) +BUILD_SF:=1 +else +BUILD_SF:=0 +endif + +ifeq ($(BUILD_SF),1) +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CPPFLAGS := $(DVP_DEBUGGING) $(DVP_CPPFLAGS) +LOCAL_SRC_FILES := surfaceflinger.cpp +LOCAL_C_INCLUDES := $(DVP_INCLUDES) +LOCAL_WHOLE_STATIC_LIBRARIES += libanw +LOCAL_MODULE := libsf +include $(BUILD_STATIC_LIBRARY) + +endif + diff --git a/source/dvp/dvp_display/surfaceflinger/surfaceflinger.cpp b/source/dvp/dvp_display/surfaceflinger/surfaceflinger.cpp new file mode 100644 index 0000000..32c7437 --- /dev/null +++ b/source/dvp/dvp_display/surfaceflinger/surfaceflinger.cpp @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(ANDROID) && (defined(ICS) || defined(JELLYBEAN)) + +#include +#include +#include + +typedef struct _surfaceflinger_t { + anativewindow_t *anw; + sp mSurfaceControl; +} surfaceflinger_t; +#define _SURFACEFLINGER_T_ + +#include + +#if defined(ICS) +#include +#include +#include +#else +#include +#include +#include +#endif +#include +#include +#include +#include + +void surfaceflinger_destroy(surfaceflinger_t **psf) +{ + DVP_PRINT(DVP_ZONE_VIDEO, "surfaceflinger_destroy: ENTER psf = %p\n", psf); + + if (psf && *psf) + { + surfaceflinger_t *sf = *psf; + + if (sf->anw) + { + anativewindow_destroy(&(sf->anw)); + } + + // clear the entire structure + memset(sf, 0, sizeof(surfaceflinger_t)); + free(sf); + *psf = NULL; + } +} + +surfaceflinger_t *surfaceflinger_create(uint32_t width, uint32_t height) +{ + DVP_PRINT(DVP_ZONE_VIDEO, "surfaceflinger_create: ENTER width = %d, height = %d\n", + width, height); + + surfaceflinger_t *sf = (surfaceflinger_t *)calloc(1, sizeof(surfaceflinger_t)); + if (sf == NULL) + return NULL; + + sp client = new SurfaceComposerClient(); + sf->mSurfaceControl = client->createSurface(0, width, height, PIXEL_FORMAT_RGBX_8888); + + // This sets the z-order, choose a sufficiently big value so the + // surface is on top of everything else + SurfaceComposerClient::openGlobalTransaction(); + sf->mSurfaceControl->setLayer(100000); + SurfaceComposerClient::closeGlobalTransaction(); + + // Get the ANativeWindow + sp surface = sf->mSurfaceControl->getSurface(); + sp window = surface.get(); + + DVP_PRINT(DVP_ZONE_VIDEO, "surfaceflinger_create: window = %p\n", window.get()); + + sf->anw = anativewindow_create(window); + if (sf->anw == NULL) + { + free(sf); + return NULL; + } + + DVP_PRINT(DVP_ZONE_VIDEO, "surfaceflinger_create: SUCCESS sf = %p\n", sf); + + return sf; +} + +void surfaceflinger_free(surfaceflinger_t *sf) +{ + DVP_PRINT(DVP_ZONE_VIDEO, "surfaceflinger_free: ENTER sf = %p\n", sf); + + if (sf == NULL) + return; + + anativewindow_free(sf->anw); +} + +bool_e surfaceflinger_allocate(surfaceflinger_t *sf, + uint32_t buffer_width, + uint32_t buffer_height, + int32_t numBuffers, + int32_t format) +{ + format = format; // warnings + DVP_PRINT(DVP_ZONE_VIDEO, "surfaceflinger_allocate: ENTER sf = %p, width = %d, height = %d, num = %d, format = %d\n", + sf, buffer_width, buffer_height, numBuffers, format); + + if (sf == NULL) + return false_e; + + bool_e res = anativewindow_allocate(sf->anw, + buffer_width, + buffer_height, + numBuffers, + ANW_NV12_FORMAT, + false); + + DVP_PRINT(DVP_ZONE_VIDEO, "surfaceflinger_allocate: EXIT res = %d\n", res); + + return res; +} + +bool_e surfaceflinger_acquire(surfaceflinger_t *sf, void **pHandle, uint8_t **ptrs, int32_t *stride) +{ + DVP_PRINT(DVP_ZONE_VIDEO, "surfaceflinger_acquire: ENTER sf = %p\n", sf); + + if (sf == NULL) + return false_e; + + bool_e res = anativewindow_acquire(sf->anw, pHandle, ptrs, stride); + + DVP_PRINT(DVP_ZONE_VIDEO, "surfaceflinger_acquire: EXIT res = %d, Handle = %p, ptrs = %p, stride = %d\n", + res, *pHandle, *ptrs, *stride); + + return res; +} + +bool_e surfaceflinger_release(surfaceflinger_t *sf, void *handle) +{ + DVP_PRINT(DVP_ZONE_VIDEO, "surfaceflinger_release: ENTER sf = %p\n", sf); + + if (sf == NULL) + return false_e; + + return anativewindow_release(sf->anw, handle); +} + +bool_e surfaceflinger_enqueue(surfaceflinger_t *sf, void *handle) +{ +// DVP_PRINT(DVP_ZONE_VIDEO, "surfaceflinger_enqueue: ENTER sf = %p\n", sf); + + if (sf == NULL) + return false_e; + + return anativewindow_enqueue(sf->anw, handle); +} + +bool_e surfaceflinger_dequeue(surfaceflinger_t *sf, void **pHandle) +{ +// DVP_PRINT(DVP_ZONE_VIDEO, "surfaceflinger_dequeue: ENTER sf = %p\n", sf); + + if (sf == NULL) + return false_e; + + return anativewindow_dequeue(sf->anw, pHandle); +} + +bool_e surfaceflinger_drop(surfaceflinger_t *sf, void *handle) +{ + DVP_PRINT(DVP_ZONE_VIDEO, "surfaceflinger_drop: ENTER sf = %p\n", sf); + + if (sf == NULL) + return false_e; + + return anativewindow_drop(sf->anw, handle); +} + +bool_e surfaceflinger_set_crop(surfaceflinger_t *sf, + uint32_t crop_left, + uint32_t crop_top, + uint32_t crop_width, + uint32_t crop_height) +{ + DVP_PRINT(DVP_ZONE_VIDEO, "surfaceflinger_set_crop: ENTER sf = %p\n", sf); + + if (sf == NULL) + return false_e; + + return anativewindow_set_crop(sf->anw, crop_left, crop_top, crop_width, crop_height); +} + +bool_e surfaceflinger_set_position(surfaceflinger_t *sf, + uint32_t left, + uint32_t top) +{ + SurfaceComposerClient::openGlobalTransaction(); + sf->mSurfaceControl->setPosition(left, top); + SurfaceComposerClient::closeGlobalTransaction(); + + return true_e; +} + +#endif diff --git a/source/dvp/dvp_display/v4l2/Android.mk b/source/dvp/dvp_display/v4l2/Android.mk new file mode 100644 index 0000000..9de6032 --- /dev/null +++ b/source/dvp/dvp_display/v4l2/Android.mk @@ -0,0 +1,37 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(DVP_DEBUGGING) $(DVP_CFLAGS) +LOCAL_SRC_FILES := v4l2_api.c +LOCAL_C_INCLUDES := $(DVP_INCLUDES) +LOCAL_MODULE := libv4l2 +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(DVP_DEBUGGING) $(DVP_CFLAGS) +LOCAL_SRC_FILES := v4l2_api.c v4l2_test.c +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_MODULE := v4l2_test +LOCAL_STATIC_LIBRARIES := libv4l2 libsosal +LOCAL_SHARED_LIBRARIES := libutils +include $(BUILD_EXECUTABLE) + diff --git a/source/dvp/dvp_display/v4l2/concerto.mak b/source/dvp/dvp_display/v4l2/concerto.mak new file mode 100644 index 0000000..fcb1bee --- /dev/null +++ b/source/dvp/dvp_display/v4l2/concerto.mak @@ -0,0 +1,33 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_OS),LINUX) + +include $(PRELUDE) +TARGET=v4l2 +TARGETTYPE=library +CSOURCES=v4l2_api.c +include $(FINALE) + +# Set the module manually so that we can have 2 builds in one makefile. +_MODULE=v4l2_test +include $(PRELUDE) +TARGET=v4l2_test +TARGETTYPE=exe +CSOURCES=v4l2_test.c +STATIC_LIBS=v4l2 sosal +SYS_SHARED_LIBS=dl pthread +include $(FINALE) + +endif diff --git a/source/dvp/dvp_display/v4l2/v4l2_api.c b/source/dvp/dvp_display/v4l2/v4l2_api.c new file mode 100644 index 0000000..b31aba4 --- /dev/null +++ b/source/dvp/dvp_display/v4l2/v4l2_api.c @@ -0,0 +1,836 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(ANDROID) || defined(LINUX) + +#include +#include + +#define V4L2_NONBLOCKING +#define V4L2_POLLING +#if !(defined(BLAZE) || defined(SDP)) +#define V4L2_SUPPORT_HFLIP +#endif + +#ifdef V4L2_POLLING +#if defined(ANDROID) +#include +#elif defined(LINUX) +#include +#ifdef POLLIN +#define POLL_IN POLLIN +#endif +#ifdef POLLPRI +#define POLL_PRI POLLPRI +#endif +#endif +#endif + + +#define V4L2_IOCTL(dev, flag, arg) v4l2_ioctl(dev, flag, #flag, arg) + +static bool_e v4l2_ioctl(int dev, int flag, char *name, void *arg) +{ + int err = 0; + name = name; // warnings + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2 IOCTL %s arg: %p\n", name, arg); + do { + err = ioctl(dev, flag, arg); + if (err == 0) + return true_e; + else + { + if (errno != EINTR && errno != EAGAIN) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! V4L2 IOCTL %s arg %p returned %d (errno=%d)\n", name, arg, err, errno); +#if defined(V4L2_EXTRA_DEBUG) && (DVP_DEBUG == 1) + perror("V4L2 IOCTL"); +#endif + return false_e; + } + else if (errno == EINTR) + { + // try to call the ioctl again, we were interrupted. + DVP_PRINT(DVP_ZONE_WARNING, "V4L2 IOCTL %s arg %p Interrupted!\n", name, arg); + } + else if (errno == EAGAIN) + { + // nothing ready now, call again later + //DVP_PRINT(DVP_ZONE_WARNING, "V4L2 IOCTL %s arg %p Call Again Later!\n", name, arg); + return false_e; + } + } + } while (errno == EINTR); + return false_e; +} + +static void v4l2_print_fmt(struct v4l2_format *fmt) +{ + DVP_PRINT(DVP_ZONE_VIDEO, "struct v4l2_format type:%u ",fmt->type); + if (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT || + fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + { + DVP_PRINT(DVP_ZONE_VIDEO, "pix %ux%u fmt:0x%08x field:%u size:%u\n", + fmt->fmt.pix.width, + fmt->fmt.pix.height, + fmt->fmt.pix.pixelformat, + fmt->fmt.pix.field, + fmt->fmt.pix.sizeimage); + } + else + { + DVP_PRINT(DVP_ZONE_VIDEO, "\n"); + } +} + +static void v4l2_print_index(v4l2_api_t *v, uint32_t index) +{ + if (v && index < v->count) + { + struct v4l2_buffer *desc = &v->bufDesc[index]; + void *buf = v->buffers[index]; + buf = buf; // warnings + desc = desc; // warnings + DVP_PRINT(DVP_ZONE_VIDEO, "struct v4l2_buffer [%u] type:%u used:%u len:%u flags=0x%08x field:%u memory:%u offset:%u buf:%p\n", + desc->index, + desc->type, + desc->bytesused, + desc->length, + desc->flags, + desc->field, + desc->memory, + desc->m.offset, + buf); + } +} + +/* +static void v4l2_print_buffer(v4l2_api_t *v, uint32_t index) +{ + if (V4L2_IOCTL(v->device, VIDIOC_QUERYBUF, &v->bufDesc[index]) == true_e) + { + v4l2_print_index(v, index); + } +} + +static void v4l2_print_buffers(v4l2_api_t *v) +{ + uint32_t i; + for (i = 0; i < v->count; i++) + { + v4l2_print_buffer(v,i); + } +} +*/ + +static void v4l2_print_formats(v4l2_api_t *v, uint32_t type) +{ + uint32_t i = 0; + bool_e ret = false_e; + do { + struct v4l2_fmtdesc fmtdesc; + memset(&fmtdesc, 0, sizeof(fmtdesc)); + fmtdesc.type = type; + fmtdesc.index = i++; + ret = V4L2_IOCTL(v->device, VIDIOC_ENUM_FMT, &fmtdesc); + if (ret == true_e) + { + DVP_PRINT(DVP_ZONE_VIDEO, "[%u] Type: %u Flags: 0x%08x FMT: 0x%08x Desc: %s\n", fmtdesc.index, fmtdesc.type, fmtdesc.flags, fmtdesc.pixelformat, fmtdesc.description); + } + } while (ret == true_e); +} + +void v4l2_close(v4l2_api_t **v) +{ + if ((*v)->device > 0) + { + close((*v)->device); + (*v)->device = 0; + } + free((*v)); + *v = NULL; +} + +v4l2_api_t *v4l2_open(int deviceNum, int capFlags, bool_e nonblocking) +{ + bool_e unwind = false_e; + int devFlags = O_RDWR; + char dev_name[40]; + v4l2_api_t *v = (v4l2_api_t *)calloc(1,sizeof(v4l2_api_t)); + if (v) + { + if (nonblocking) + devFlags |= O_NONBLOCK; + v->nonblocking = nonblocking; + sprintf(dev_name, "/dev/video%d", deviceNum); + DVP_PRINT(DVP_ZONE_VIDEO, "OPEN %s\n", dev_name); + v->device = open(dev_name, devFlags); + if (v->device > 0) + { + if (V4L2_IOCTL(v->device, VIDIOC_QUERYCAP, &v->capability) == false_e) + unwind = true_e; + else + { + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2 Driver: %s\n", v->capability.driver); + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2 Card: %s\n", v->capability.card); + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2 Bus: %s\n", v->capability.bus_info); + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2 Caps: 0x%08x\n", v->capability.capabilities); + if ((v->capability.capabilities & (__u32)capFlags) != (__u32)capFlags) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: VIDIOC_QUERYCAP indicated that driver is not capable of required devFlags 0x%x\n", capFlags); + unwind = true_e; + } + } + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Failed to open %s\n", dev_name); + unwind = true_e; + } + } + if (unwind) + v4l2_close(&v); + return v; +} + +uint32_t v4l2_search_buffer(v4l2_api_t *v, void *buffer) +{ + uint32_t index = 0; + for (index = 0; index < v->count; index++) + { + if (v->buffers[index] == buffer) + return index; + } + return V4L2_INVALID_INDEX; +} + +void *v4l2_search_index(v4l2_api_t *v, uint32_t index) +{ + if (index < v->count) + return v->buffers[index]; + else + return NULL; +} + +int v4l2_wait(v4l2_api_t *v) +{ + if (v) + { + if (v->nonblocking) + { + int ret = 0; +#ifdef V4L2_POLLING + struct pollfd pds; + + pds.fd = v->device; + pds.events = POLL_IN|POLL_PRI; + ret = poll(&pds, 1, 1000); // 1 sec + if (ret == 0) + { + DVP_PRINT(DVP_ZONE_WARNING, "V4L2 Wait Timeout\n"); + return 0; + } + else if (ret > 0) + { + if (pds.revents & (POLL_IN|POLL_PRI)) + return 1; + else + return -1; + } +#else + fd_set fds; + struct timeval timer; + + FD_ZERO(&fds); + FD_SET(v->device, &fds); + timer.tv_sec = 2; // 2 seconds + timer.tv_usec = 0; + + // "Highest watched file descriptor + 1" + ret = select(v->device+1, &fds, NULL, NULL, &timer); + if (ret == 0) // zero descriptors set + { + DVP_PRINT(DVP_ZONE_WARNING, "V4L2 Wait Timeout!\n"); + return 0; // TIMEOUT + } + else if (ret > 0) // some descriptors set! + { + if (FD_ISSET(v->device, &fds)) + return 1; + else + return -1; + } +#endif + } + else + return 1; // in the blocking mode, just return 1 + } + else + return -1; // if v == NULL, return error + return 1; +} + +bool_e v4l2_control_get(v4l2_api_t *v, int control, int *value) +{ + struct v4l2_control ctrl; + struct v4l2_queryctrl qctrl; + memset(&qctrl, 0, sizeof(qctrl)); + qctrl.id = control; + if (V4L2_IOCTL(v->device, VIDIOC_QUERYCTRL, &qctrl)) + { + if (qctrl.flags & V4L2_CTRL_TYPE_BOOLEAN || + qctrl.type & V4L2_CTRL_TYPE_INTEGER) + { +#if defined(DVP_DEBUG) + int min = qctrl.minimum; + int max = qctrl.maximum; + int step = qctrl.step; + DVP_PRINT(DVP_ZONE_VIDEO, "Ctrl: %d Min:%d Max:%d Step:%d\n",control,min,max,step); +#endif + ctrl.id = control; + if (V4L2_IOCTL(v->device, VIDIOC_G_CTRL, &ctrl)) + { + *value = ctrl.value; + return true_e; + } + else + return false_e; + } + else + return false_e; + } + else + return false_e; +} + +bool_e v4l2_control_set(v4l2_api_t *v, int control, int value) +{ + struct v4l2_control ctrl; + struct v4l2_queryctrl qctrl; + memset(&qctrl, 0, sizeof(qctrl)); + qctrl.id = control; + if (V4L2_IOCTL(v->device, VIDIOC_QUERYCTRL, &qctrl)) + { + if (qctrl.flags & V4L2_CTRL_TYPE_BOOLEAN || + qctrl.type & V4L2_CTRL_TYPE_INTEGER) + { + int min = qctrl.minimum; + int max = qctrl.maximum; + int step = qctrl.step; + DVP_PRINT(DVP_ZONE_VIDEO, "Ctrl: %d Min:%d Max:%d Step:%d\n",control,min,max,step); + if ((min <= value) && (value <= max)) + { + if (step > 1) + value = value - (value % step); + } + else + value = qctrl.default_value; + ctrl.id = control; + ctrl.value = value; + if (V4L2_IOCTL(v->device, VIDIOC_S_CTRL, &ctrl)) + return true_e; + else + return false_e; + } + else + return false_e; + } + else + return false_e; +} + +bool_e v4l2_queue(v4l2_api_t *v, uint32_t index, uint32_t type) +{ + if (v && index < v->count) + { + struct v4l2_buffer *buffer = &v->bufDesc[index]; + buffer->index = index; + buffer->timestamp.tv_sec = 0; + buffer->timestamp.tv_usec = 0; // render ASAP + if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT) + { + buffer->bytesused = buffer->length; + buffer->field = V4L2_FIELD_NONE; + } + else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + { + buffer->bytesused = 0; + buffer->field = V4L2_FIELD_ANY; + } + v4l2_print_index(v, index); + if (V4L2_IOCTL(v->device, VIDIOC_QBUF, buffer) == false_e) + return false_e; + else + { + mutex_lock(&v->m_lock); + v->active++; + v4l2_print_index(v, index); + mutex_unlock(&v->m_lock); + return true_e; + } + } + return false_e; +} + +bool_e v4l2_dequeue(v4l2_api_t *v, uint32_t *index, uint32_t type) +{ + if (v && index) + { + struct v4l2_buffer buffer; + memset(&buffer, 0, sizeof(buffer)); + buffer.type = type; + buffer.memory = V4L2_MEMORY_MMAP; + if (V4L2_IOCTL(v->device, VIDIOC_DQBUF, &buffer) == false_e) + return false_e; + *index = buffer.index; + mutex_lock(&v->m_lock); + v->active--; + v4l2_print_index(v, buffer.index); + mutex_unlock(&v->m_lock); + return true_e; + } + return false_e; +} + +bool_e v4l2_start(v4l2_api_t *v, uint32_t type) +{ + bool_e ret = true_e; + + if (v == NULL) + return false_e; + + mutex_lock(&v->m_lock); + if (v->active >= 1 && v->streaming == false_e) + { + if (V4L2_IOCTL(v->device, VIDIOC_STREAMON, &type) == false_e) + ret = false_e; + else + v->streaming = true_e; + } + mutex_unlock(&v->m_lock); + return ret; +} + +bool_e v4l2_stop(v4l2_api_t *v, uint32_t type) +{ + int ret = true_e; + + if (v == NULL) + return false_e; + + mutex_lock(&v->m_lock); + if (v->streaming == true_e) + { + if (V4L2_IOCTL(v->device, VIDIOC_STREAMOFF, &type) == false_e) + ret = false_e; + else + v->streaming = false_e; + } + mutex_unlock(&v->m_lock); + return ret; +} + +uint32_t v4l2_length(v4l2_api_t *v, uint32_t index) +{ + uint32_t len = 0; + if (v && index < v->count) + { + len = v->bufDesc[index].length; + } + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2 Length of Buffer is %u bytes\n", len); + return len; +} + +void *v4l2_acquire(v4l2_api_t *v, uint32_t *index) +{ + void *buf = NULL; + *index = V4L2_INVALID_INDEX; + + if (v) + { + mutex_lock(&v->m_lock); + if (bitfield_get(&v->used, index) == false_e) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Failed to acquire V4L2 Buffer!\n"); + } + else + { + buf = v->buffers[*index]; + } + mutex_unlock(&v->m_lock); + } + return buf; +} + +bool_e v4l2_release(v4l2_api_t *v, void *buffer, uint32_t index) +{ + int ret = true_e; + if (v && index < v->count) + { + mutex_lock(&v->m_lock); + if (index < v->count) + { + if (bitfield_rls(&v->used, index) == false_e) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Failed to release V4L2 Buffer!\n"); + ret = false_e; + } + } + else if (index == V4L2_INVALID_INDEX) + { + // search for index of buffer + for (index = 0; index < v->count; index++) + { + if (buffer == v->buffers[index]) + { + if (bitfield_rls(&v->used, index) == false_e) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Failed to release V4L2 Buffer!\n"); + ret = false_e; + } + break; + } + } + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Buffer was not a V4L2 Buffer!\n"); + ret = false_e; + } + mutex_unlock(&v->m_lock); + } + return ret; +} + +bool_e v4l2_free(v4l2_api_t *v) +{ + if (v) + { + uint32_t i; + mutex_lock(&v->m_lock); + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2: Freeing display memory! %u buffers, (%u active)\n", v->count, v->active); + if (v->active) { + DVP_PRINT(DVP_ZONE_WARNING, "V4L2: WARNING! There are still %u buffers active\n", v->active); + } + for (i = 0; i < v->count; i++) + { + if (munmap(v->buffers[i], v->bufDesc[i].length)) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Failed to unmap display buffer!\n"); + } + else + { + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2 Unmapped buffer %p for %u bytes (errno=%d)\n", v->buffers[i], v->bufDesc[i].length, errno); + } + } + if (v->buffers) + { + free(v->buffers); + v->buffers = NULL; + } + if (v->bufDesc) + { + free(v->bufDesc); + v->bufDesc = NULL; + } + v->count = 0; + v->active = 0; + bitfield_deinit(&v->used); + mutex_unlock(&v->m_lock); + return true_e; + } + else + return false_e; +} + +bool_e v4l2_metrics(v4l2_api_t *v, uint32_t *width, uint32_t *height) +{ + if (v) + { + struct v4l2_format format; + + // get the current position of the overlay + format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + if (V4L2_IOCTL(v->device, VIDIOC_G_FMT, &format) == true_e) + { + *width = format.fmt.pix.width; + *height = format.fmt.pix.height; + return true_e; + } + } + return false_e; +} + +bool_e v4l2_rotate(v4l2_api_t *v, int32_t angle) +{ + struct v4l2_control ctrl; + +#ifdef V4L2_CID_ROTATE + ctrl.id = V4L2_CID_ROTATE; +#endif +#ifndef V4L2_SUPPORT_HFLIP + V4L2_IOCTL(v->device, VIDIOC_G_CTRL, &ctrl); + if (ctrl.value == 180) + { + // "fake" HFLIP is on since the kernel doesn't support it. + if (angle == 0) + return true_e; + else if (angle == 90) + ctrl.value = 270; + else if (angle == 270) + ctrl.value = 90; + else if (angle == 180) + ctrl.value = 0; + else + return false_e; + } +#else + if (angle == 0 || angle == 90 || angle == 180 || angle == 270) + ctrl.value = angle; + else + ctrl.value = 0; +#endif + return V4L2_IOCTL(v->device, VIDIOC_S_CTRL, &ctrl); +} + +bool_e v4l2_mirror(v4l2_api_t *v, bool_e mirror) +{ + struct v4l2_control ctrl; + +#ifdef V4L2_SUPPORT_HFLIP + + ctrl.id = V4L2_CID_HFLIP; + ctrl.value = (mirror == true_e ? 1 : 0); + return V4L2_IOCTL(v->device, VIDIOC_S_CTRL, &ctrl); + +#else + __u32 vflip, rotate; + + vflip = V4L2_CID_VFLIP; + rotate = V4L2_CID_ROTATE; + + ctrl.id = vflip; + if (mirror) + ctrl.value = 1; + else + ctrl.value = 0; + + if (V4L2_IOCTL(v->device, VIDIOC_S_CTRL, &ctrl) == true_e) + { + ctrl.id = rotate; + ctrl.value = 180; + return V4L2_IOCTL(v->device, VIDIOC_S_CTRL, &ctrl); + } + else + return false_e; +#endif +} + +bool_e v4l2_position(v4l2_api_t *v, uint32_t x, uint32_t y, uint32_t w, uint32_t h) +{ + struct v4l2_format format; + + // get the current position of the overlay + format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + if (V4L2_IOCTL(v->device, VIDIOC_G_FMT, &format) == true_e) + { + // configure the position of the overlay + format.fmt.win.w.left = x; + format.fmt.win.w.top = y; + format.fmt.win.w.width = w; + format.fmt.win.w.height = h; + return V4L2_IOCTL(v->device, VIDIOC_S_FMT, &format); + } + return false_e; +} + +bool_e v4l2_crop(v4l2_api_t *v, uint32_t left, uint32_t top, uint32_t width, uint32_t height) +{ + struct v4l2_crop crop; + + crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + crop.c.left = left; + crop.c.top = top; + crop.c.width = width; + crop.c.height = height; + DVP_PRINT(DVP_ZONE_VIDEO, "Setting Crop Rect to {%d,%d for %d,%d}\n", + crop.c.left, + crop.c.top, + crop.c.width, + crop.c.height); + return V4L2_IOCTL(v->device, VIDIOC_S_CROP, &crop); +} + +bool_e v4l2_transparency(v4l2_api_t *v, uint32_t flags, uint32_t colorkey) +{ + struct v4l2_framebuffer fbuf; + memset(&fbuf, 0, sizeof(fbuf)); + if (V4L2_IOCTL(v->device, VIDIOC_G_FBUF, &fbuf) == true_e) + { +#ifdef V4L2_FBUF_FLAG_SRC_CHROMAKEY + if (flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) + fbuf.flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY; + else + fbuf.flags &= ~V4L2_FBUF_FLAG_SRC_CHROMAKEY; +#endif + if (flags & V4L2_FBUF_FLAG_CHROMAKEY) + fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY; + else + fbuf.flags &= ~V4L2_FBUF_FLAG_CHROMAKEY; + + // now set the format information. + if (V4L2_IOCTL(v->device, VIDIOC_S_FBUF, &fbuf) == true_e) + { + // get the format info and set the color key color + struct v4l2_format fmt; + memset(&fmt, 0, sizeof(fmt)); + fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; + if (V4L2_IOCTL(v->device, VIDIOC_G_FMT, &fmt) == true_e) + { + fmt.fmt.win.chromakey = colorkey & 0xFFFFFF; // 24 bit mask (for RGB 24 plane) + return V4L2_IOCTL(v->device, VIDIOC_S_FMT, &fmt); + } + } + } + // catch all return + return false_e; +} + +typedef struct _v4l2_pix_to_fourcc_lut_t { + uint32_t v4l2; + uint32_t fourcc; +} V4L2_to_FOURCC_t; + +V4L2_to_FOURCC_t codes[] = { + {V4L2_PIX_FMT_UYVY, FOURCC_UYVY}, + {V4L2_PIX_FMT_YUYV, FOURCC_YUY2}, // capture + {V4L2_PIX_FMT_NV12, FOURCC_NV12}, + //{V4L2_PIX_FMT_BGR24, FOURCC_BGR}, // I don't think this is supported by capture or displays we use + {V4L2_PIX_FMT_RGB24, FOURCC_RGB}, + {V4L2_PIX_FMT_RGB32, FOURCC_RGBA}, // we'll use a global alpha +}; +uint32_t numCodes = dimof(codes); + +bool_e v4l2_allocate(v4l2_api_t *v, uint32_t width, uint32_t height, uint32_t count, fourcc_t color, int fmtType) +{ + bool_e unwind = false_e; + bool_e ret = false_e; + uint32_t i; + + mutex_lock(&v->m_lock); + + v4l2_print_formats(v, fmtType); + + v->format.type = fmtType; + // Get the current format... + if (V4L2_IOCTL(v->device, VIDIOC_G_FMT, &v->format)) + { + v4l2_print_fmt(&v->format); + } + v->format.fmt.pix.width = width; + v->format.fmt.pix.height = height; + v->format.fmt.pix.pixelformat = 0; + v->format.fmt.pix.field = V4L2_FIELD_ANY; + for (i = 0; i < numCodes; i++) + { + if (color == codes[i].fourcc) + v->format.fmt.pix.pixelformat = codes[i].v4l2; + } + if (v->format.fmt.pix.pixelformat == 0) + goto leave; + + v4l2_print_fmt(&v->format); + if (V4L2_IOCTL(v->device, VIDIOC_S_FMT, &v->format) == false_e) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: Failed to negotiate the format of the display!\n"); + goto leave; + } + + v->reqbuf.type = fmtType; + v->reqbuf.memory = V4L2_MEMORY_MMAP; + v->reqbuf.count = count; + if (V4L2_IOCTL(v->device, VIDIOC_REQBUFS, &v->reqbuf) == false_e) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: Failed to negotiate the number of buffers for the display\n"); + goto leave; + } + if (v->reqbuf.count != count) + { + DVP_PRINT(DVP_ZONE_WARNING, "ERROR: Driver only allocated %d buffers, we wanted %d instead\n", v->reqbuf.count, count); + } + v->count = v->reqbuf.count; + + bitfield_init(&v->used, v->count); + + v->bufDesc = (struct v4l2_buffer *)calloc(1, sizeof(struct v4l2_buffer) * v->count); + if (v->bufDesc) + { + v->buffers = calloc(1, sizeof(void *) * v->count); + if (v->buffers) + { + for (i = 0; i < v->count; i++) + { + v->bufDesc[i].type = v->reqbuf.type; + v->bufDesc[i].memory = v->reqbuf.memory; + v->bufDesc[i].index = i; + + if (V4L2_IOCTL(v->device, VIDIOC_QUERYBUF, &v->bufDesc[i]) == false_e) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: Failed to get the address of buffer %u!\n",i); + unwind = true_e; + break; + } + + if (v->bufDesc[i].flags != V4L2_BUF_FLAG_MAPPED) + { + v->buffers[i] = mmap(NULL, v->bufDesc[i].length, + PROT_READ | PROT_WRITE, + MAP_SHARED, + v->device, + v->bufDesc[i].m.offset); + if (v->buffers[i] == MAP_FAILED) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: mmap failed\n"); + unwind = true_e; + break; + } + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Buffer already mmaped!\n"); + } + v4l2_print_index(v,i); + } + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2: %u buffers allocated and mapped\n", v->count); + ret = true_e; + } + else + unwind = true_e; + } + else + unwind = true_e; +leave: + mutex_unlock(&v->m_lock); + if (unwind) { + v4l2_free(v); + ret = false_e; // make sure we're clear that we failed. + } + return ret; + +} + +#endif + diff --git a/source/dvp/dvp_display/v4l2/v4l2_test.c b/source/dvp/dvp_display/v4l2/v4l2_test.c new file mode 100644 index 0000000..fe2d8cb --- /dev/null +++ b/source/dvp/dvp_display/v4l2/v4l2_test.c @@ -0,0 +1,215 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +uint32_t dvp_zone_mask; // declare a local version for testing. + +uint32_t width; +uint32_t height; +uint32_t count; +uint32_t fourcc; +uint32_t iter; +uint32_t fps; +bool_e f_running = false_e; +char filename[255]; +option_t opts[] = { + {OPTION_TYPE_INT, &width, sizeof(width), "-w", "--width", "Width of buffer"}, + {OPTION_TYPE_INT, &height, sizeof(height), "-h", "--height", "Height of buffer"}, + {OPTION_TYPE_INT, &count, sizeof(count), "-#", "--count", "Number of buffers"}, + {OPTION_TYPE_INT, &fps, sizeof(fps), "-f", "--fps", "Frame rate"}, + {OPTION_TYPE_HEX, &fourcc, sizeof(fourcc), "-c", "--color", "Color Space of Buffer"}, + {OPTION_TYPE_INT, &iter, sizeof(iter), "-i", "--iterations", "Number of alloc/free cycles"}, + {OPTION_TYPE_STRING, filename, sizeof(filename), "-f", "--file", "Uses a file to render to the screen"}, +}; +size_t numOpts = dimof(opts); + +#define SET_UYVY(y,cb,cr) ((y << 24)|(cr << 16)|(y << 8)|cb) + +uint32_t sdtv_colors[] = { + SET_UYVY(180,128,128), + SET_UYVY(162, 44,142), + SET_UYVY(131,156, 44), + SET_UYVY(112, 72, 58), + SET_UYVY( 84,184,198), + SET_UYVY( 65,100,212), + SET_UYVY( 35,212,114), + SET_UYVY( 16,128,128), +}; +uint32_t numSDTVColors = dimof(sdtv_colors); + +void v4l2_test_file(uint8_t *buffer, uint32_t width, uint32_t height, uint32_t stride, FILE *f) +{ + uint32_t y,i,l; + for (y = 0; y < height; y++) + { + i = (y * stride); + l = width * sizeof(uint16_t); + if (fread(&buffer[i], 1, l, f) == 0) + printf("Can't read file\n"); + } +} + +void v4l2_test_fill(uint8_t *buffer, uint32_t width, uint32_t height, uint32_t stride) +{ + uint32_t bar_width = width / numSDTVColors; + uint32_t x,y,i; + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x+=2) + { + uint32_t *p32 = NULL; + i = (y * stride) + (x * sizeof(uint16_t)); + p32 = (uint32_t *)&buffer[i]; + *p32 = sdtv_colors[width/bar_width]; + } + } +} + +bool_e running; +event_t wait_for_frame; + +thread_ret_t dequeuer(void *arg) +{ + v4l2_api_t *v = (v4l2_api_t *)arg; + uint32_t index = 0; + void *buffer = NULL; + + while (running) + { + event_wait(&wait_for_frame, 100); + if (v4l2_wait(v)) + { + // dequeue the buffer + if (v4l2_dequeue(v, &index, V4L2_BUF_TYPE_VIDEO_OUTPUT) == true_e) + { + // set the buffer pointer (though not strictly necessary) + buffer = v->buffers[index]; + + // release the buffer + v4l2_release(v, buffer, index); + } + } + } + return 0; +} + +int main(int argc, char *argv[]) +{ + int err = 0; + bool_e useFile = false_e; + FILE *f = NULL; + event_t timer; + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + +#if defined(DVP_RUNTIME_DEBUG) + debug_get_zone_mask("DVP_ZONE_MASK", &dvp_zone_mask); +#endif + + width = 640; + height = 480; + count = 4; + fourcc = FOURCC_UYVY; + iter = 1; + fps = 30; + + event_init(&timer, true_e); + + option_process(argc, argv, opts, numOpts); + + if (filename[0] != '\0') + { + useFile = true_e; + f = fopen(filename, "rb"); + if (f == NULL) + useFile = false_e; + } + event_init(&wait_for_frame, true_e); + v4l2_api_t *v = v4l2_open(V4L2_DISPLAY_DEVICE, V4L2_CAP_STREAMING, true_e); + if (v) + { + uint32_t c,i = 0; + for (i = 0; i < iter; i++) + { + // allocate a bunch of memory + if (v4l2_allocate(v, width, height, count, fourcc, V4L2_BUF_TYPE_VIDEO_OUTPUT) == true_e) + { + thread_t t; + + running = true_e; + t = thread_create(dequeuer, v); + + for (c = 0; c < count; c++) + { + uint32_t index = 0; + void *buffer = v4l2_acquire(v, &index); + if (buffer != NULL) + { + uint32_t stride = v4l2_length(v, index) / height; + + if (useFile) + { + // read from the file + v4l2_test_file(buffer, width, height, stride, f); + } + else + { + // fill the buffer + v4l2_test_fill(buffer, width, height, stride); + } + + // queue the buffer + v4l2_queue(v, index, V4L2_BUF_TYPE_VIDEO_OUTPUT); + v4l2_start(v, V4L2_BUF_TYPE_VIDEO_OUTPUT); + event_set(&wait_for_frame); + } + else + { + DVP_PRINT(DVP_ZONE_ALWAYS, "Failed to Acquire V4L2 Buffer!\n"); + } + + event_wait(&timer, 1000/fps); + } + + running = false_e; + v4l2_stop(v, V4L2_BUF_TYPE_VIDEO_OUTPUT); + thread_join(t); + + // free that memory + if (v4l2_free(v) == false_e) { + DVP_PRINT(DVP_ZONE_ALWAYS, "Failed to free buffers!\n"); + err++; + } + } + else + { + DVP_PRINT(DVP_ZONE_ALWAYS, "Failed to allocate buffers!\n"); + err++; + } + } + v4l2_close(&v); + } + event_deinit(&wait_for_frame); + event_deinit(&timer); + if (useFile) + fclose(f); + DVP_PRINT(DVP_ZONE_ALWAYS, "Number of errors = %u\n", err); + return err; +} diff --git a/source/dvp/dvp_display/win32/concerto.mak b/source/dvp/dvp_display/win32/concerto.mak new file mode 100644 index 0000000..dd5fd62 --- /dev/null +++ b/source/dvp/dvp_display/win32/concerto.mak @@ -0,0 +1,36 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_OS),Windows_NT) + +include $(PRELUDE) +TARGET=w32window +TARGETTYPE=library +CSOURCES=w32window.c +IDIRS+=$(SOSAL_INC) +include $(FINALE) + +# Set the module manually so that we can have 2 builds in one makefile. +_MODULE=w32_test +include $(PRELUDE) +TARGET=w32_test +TARGETTYPE=exe +CSOURCES=w32_test.c +STATIC_LIBS=w32window sosal +SYS_SHARED_LIBS+=Gdi32 Kernel32 $(PLATFORM_LIBS) +ENTRY=WinMainCRTStartup +include $(FINALE) + +endif + diff --git a/source/dvp/dvp_display/win32/w32_test.c b/source/dvp/dvp_display/win32/w32_test.c new file mode 100644 index 0000000..123ade4 --- /dev/null +++ b/source/dvp/dvp_display/win32/w32_test.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +HINSTANCE g_hInstance; + +#define DVP_CONSOLE +#include + +thread_ret_t threadMessages(void *arg) +{ + MSG Msg; + DVP_PRINT(DVP_ZONE_VIDEO, "Windows Messaging Thread Started!\n"); + while(GetMessage(&Msg, NULL, 0, 0)) + { + DVP_PRINT(DVP_ZONE_VIDEO, "MSG THREAD: HWND:%p msg:%u\n", Msg.hwnd, Msg.message); + TranslateMessage(&Msg); + DispatchMessage( &Msg); + } + DVP_PRINT(DVP_ZONE_VIDEO, "Windows Messaging Thread Stopping!\n"); + thread_exit((int)(Msg.wParam)); +} + +int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow) +{ + uint32_t i,count = 4,iter = 1000; + uint32_t width = 640; + uint32_t height = 480; + uint8_t *ptr = NULL; + W32Window_t *w = NULL; + image_t *rgb = NULL; + thread_t msgs = NULL; + char c; + + AllocConsole(); + + DVP_PRINT(DVP_ZONE_ALWAYS, "Starting in WinMain(0x%08x)\n", hInstance); + + rgb = image_allocate(width, height, FOURCC_RGB); + image_back(rgb); + ptr = rgb->plane[0].ptr; // save it + g_hInstance = hInstance; + w = w32window_open("W32Test"); + if (w32window_allocate(w, width, height, count, FOURCC_RGB)) + { + msgs = thread_create(threadMessages, NULL); + + for (i = 0; i < iter; i++) + { + uint32_t index; + void *buffer = w32window_acquire(w, &index); + if (buffer != NULL) + { + rgb->plane[0].ptr = (uint8_t *)buffer; + image_fill(rgb, 0x34, 0x00, 0xD0); + if (w32window_queue(w, index)) + { + thread_msleep(33); + + DVP_PRINT(DVP_ZONE_ALWAYS, "Press a button to quit\n"); + ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE), &c, 1, NULL, NULL); + + if (w32window_dequeue(w, &index)) + { + w32window_release(w, buffer, index); + } + } + } + } + rgb->plane[0].ptr = ptr; + image_unback(rgb); + image_free(&rgb); + w32window_free(w); + } + w32window_close(w); + + DVP_PRINT(DVP_ZONE_ALWAYS, "Press a button to quit\n"); + ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE), &c, 1, NULL, NULL); + + FreeConsole(); + + return 9; +} + diff --git a/source/dvp/dvp_display/win32/w32window.c b/source/dvp/dvp_display/win32/w32window.c new file mode 100644 index 0000000..982330f --- /dev/null +++ b/source/dvp/dvp_display/win32/w32window.c @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#define DVP_CONSOLE +#include + +extern HINSTANCE g_hInstance; + +//****************************************************************************** +// INTERNAL FUNCTIONS +//****************************************************************************** + +static thread_ret_t threadw32Renderer(void *arg) +{ + W32Window_t *w = (W32Window_t *)arg; + DVP_PRINT(DVP_ZONE_VIDEO, "w32: Render Loop Running!\n"); + while (w->bRendering) + { + image_t *img = NULL; + if (queue_read(w->queue, true_e, &img) == true_e) + { + if (img != NULL) + { + RECT rect = {0, 0, w->width, w->height}; + DVP_PRINT(DVP_ZONE_VIDEO, "w32: Render Loop Received image_t %p of format 0x%08x!\n", img, img->color); + w->fi = (w->fi + 1) % dimof(w->fb); + image_convert(w->fb[w->fi], img); + //InvalidateRect(w->window, NULL, TRUE); + //if (UpdateWindow(w->window) == TRUE) + if (RedrawWindow(w->window, &rect, NULL, RDW_INTERNALPAINT|RDW_INVALIDATE) == FALSE) + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to redraw (error=%d)\n", GetLastError()); + } + else + { + DVP_PRINT(DVP_ZONE_VIDEO, "Redraw returned success!\n"); + } + queue_write(w->dequeue, false_e, &img); + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "w32: Render loop dequeued a NULL image!\n"); + } + } + else if (w->bRendering == false_e) + break; + } + thread_exit(0); +} + +// of type WNDPROC +static LRESULT w32window_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + LRESULT lr = 0; + HDC hDC = 0; + static W32Window_t *w = NULL; + DVP_PRINT(DVP_ZONE_VIDEO, "HWND %p msg:%u wParam:%p lParam:%p\n", hwnd, uMsg, wParam, lParam); + switch (uMsg) + { + case WM_DESTROY: + PostQuitMessage(WM_QUIT); + break; + case WM_CREATE: + { + CREATESTRUCT *cs = (CREATESTRUCT *)lParam; + w = cs->lpCreateParams; + DVP_PRINT(DVP_ZONE_VIDEO, "Saved W32Window_t *%p\n", w); + break; + } + case WM_PAINT: + { + PAINTSTRUCT ps; + uint32_t x,y; + image_t *img = w->fb[w->fi]; + hDC = BeginPaint(hwnd, &ps); + for (y = 0; y < img->plane[0].ydim; y++) + { + for (x = 0; x < img->plane[0].xdim; x+=img->plane[0].xstep) + { + uint8_t *rgb = image_pixel(img, 0, x, y); + COLORREF pixel = RGB(rgb[0],rgb[1],rgb[2]); + SetPixel(hDC, x, y, pixel); + } + } + EndPaint(hwnd, &ps); + break; + } + default: + return DefWindowProc(hwnd, uMsg, wParam, lParam); + } + return lr; +} + +//****************************************************************************** +// EXTERNAL API +//****************************************************************************** + +void w32window_close(W32Window_t *w) +{ + if (w) + { + UnregisterClass(w->className, w->class.hInstance); + memset(w, 0, sizeof(W32Window_t)); + free(w); + } +} + +W32Window_t *w32window_open(const char *title) +{ + W32Window_t *w = (W32Window_t *)calloc(1, sizeof(W32Window_t)); + //DVP_PRINT(DVP_ZONE_VIDEO, "%s\n", __FUNCTION__); + if (w) + { + char *className = "W32Window"; + w->class.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW; + w->class.lpfnWndProc = (WNDPROC)w32window_proc; + w->class.cbClsExtra = 0; + w->class.cbWndExtra = 0; + w->class.hInstance = g_hInstance; + w->class.hIcon = LoadIcon(g_hInstance, IDI_APPLICATION); + w->class.hCursor = LoadCursor(g_hInstance, IDC_ARROW); + w->class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); + w->class.lpszClassName = w->className; + w->class.lpszMenuName = NULL; +#ifdef UNICODE + mbstowcs(w->className, className, strlen(className)); + mbstowcs(w->windowName, title, strlen(title)); +#else + strncpy(w->className, className, strlen(className)); + strncpy(w->windowName, title, strlen(title)); +#endif + w->atom = RegisterClass(&w->class); + if (w->atom) + { + DVP_PRINT(DVP_ZONE_VIDEO, "Creating Window %s:%s\n", className, title); + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Could not RegisterClass (error=%d)\n", GetLastError()); + free(w); + w = NULL; + } + } + return w; +} + +bool_e w32window_release(W32Window_t *w, void *ptr, uint32_t index) +{ + if (w) + { + bool_e ret = false_e; + mutex_lock(&w->lock); + if (index < w->numImg) + { + ret = bitfield_rls(&w->active, index); + } + else if (index == 0xFFFFFFFF) + { + uint32_t i = 0; + for (i = 0; i < w->numImg; i++) + { + if (w->images[i]->plane[0].ptr == ptr) + { + ret = bitfield_rls(&w->active, i); + } + } + } + mutex_unlock(&w->lock); + return ret; + } + return false_e; +} + +void *w32window_acquire(W32Window_t *w, uint32_t *index) +{ + if (w) + { + void *ptr = NULL; + mutex_lock(&w->lock); + if (bitfield_get(&w->active, index) == false_e) + { + DVP_PRINT(DVP_ZONE_VIDEO, "Failed to acquire an image!\n"); + } + else + { + ptr = w->images[*index]->plane[0].ptr; + } + mutex_unlock(&w->lock); + return ptr; + } + else + return NULL; +} + +bool_e w32window_free(W32Window_t *w) +{ + if (w) + { + uint32_t i; + w->bRendering = false_e; + queue_pop(w->dequeue); + queue_pop(w->queue); + thread_join(w->hRender); + queue_destroy(w->queue); + queue_destroy(w->dequeue); + + w->bRunning = false_e; + DestroyWindow(w->window); + thread_join(w->hMain); + + for (i = 0; i < dimof(w->fb); i++) { + image_unback(w->fb[i]); + image_free(&w->fb[i]); + } + for (i = 0; i < w->numImg; i++) { + image_unback(w->images[i]); + image_free(&w->images[i]); + } + free(w->images); + bitfield_deinit(&w->active); + event_deinit(&w->wait); + mutex_deinit(&w->lock); + return true_e; + } + else + return false_e; +} + +bool_e w32window_allocate(W32Window_t *w, uint32_t width, uint32_t height, uint32_t count, fourcc_t color) +{ + if (w) + { + uint32_t i; + + DVP_PRINT(DVP_ZONE_VIDEO, "Creating W32Window\n"); + w->window = CreateWindow(w->className, + w->windowName, + WS_VISIBLE | WS_OVERLAPPED, + CW_USEDEFAULT, CW_USEDEFAULT, + width, height, + NULL, + NULL, + w->class.hInstance, + w); + if (w->window == NULL) + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to create Windows (error=%d)\n",GetLastError()); + return false_e; + } + else + { + if (image_query_format(color) == false_e) + return false_e; + + mutex_init(&w->lock); + event_init(&w->wait, true_e); + + // remember values + w->width = width; + w->height = height; + + DVP_PRINT(DVP_ZONE_VIDEO, "Allocating %lu Frame Buffer Images\n", dimof(w->fb)); + w->fi = 0; + for (i = 0; i < dimof(w->fb); i++) + { + w->fb[i] = image_allocate(width, height, FOURCC_BGR); + image_back(w->fb[i]); + image_fill(w->fb[i], 0xFF, 0x00, 0x00); // RED + } + DVP_PRINT(DVP_ZONE_VIDEO, "Allocating %u User Images\n", count); + w->numImg = count; + w->images = (image_t **)calloc(count, sizeof(image_t *)); + for (i = 0 ; i < count; i++) { + w->images[i] = image_allocate(width, height, color); + image_back(w->images[i]); + image_print(w->images[i]); + } + bitfield_init(&w->active, count); + w->queue = queue_create(count, sizeof(image_t *)); + w->dequeue = queue_create(count, sizeof(image_t *)); + + // Start w32 Renderer + w->bRendering = true_e; + w->hRender = thread_create(threadw32Renderer, w); + + return true_e; + } + } + else + return false_e; +} + +uint32_t w32window_search_index(W32Window_t *w, void *ptr) +{ + if (w) + { + uint32_t i; + for (i = 0; i < w->numImg; i++) + { + if (w->images[i]->plane[0].ptr == ptr) + break; + } + if (i == w->numImg) + return 0xFFFFFFFF; + return i; + } + else + return 0xFFFFFFFF; +} + +void *w32window_search_buffer(W32Window_t *w, uint32_t index) +{ + if (w && index < w->numImg) + return w->images[index]->plane[0].ptr; + else + return NULL; +} + +bool_e w32window_queue(W32Window_t *w, uint32_t index) +{ + if (w && index < w->numImg) + { + DVP_PRINT(DVP_ZONE_VIDEO, "Queueing %u %p\n", index, w->images[index]); + return queue_write(w->queue, false_e, &w->images[index]); + } + else + return false_e; +} + +bool_e w32window_dequeue(W32Window_t *w, uint32_t *index) +{ + if (w) + { + image_t *img; + bool_e ret = false_e; + DVP_PRINT(DVP_ZONE_VIDEO, "Attempting to dequeue from w32\n"); + ret = queue_read(w->dequeue, true_e, &img); + if (ret) + { + DVP_PRINT(DVP_ZONE_VIDEO, "Dequeued %p\n", img); + *index = w32window_search_index(w, img->plane[0].ptr); + DVP_PRINT(DVP_ZONE_VIDEO, "Dequeueing %u\n", *index); + } + return ret; + } + else + return false_e; +} + +uint32_t w32window_length(W32Window_t *w, uint32_t index) +{ + if (w) + { + uint32_t len=0, p = 0; + for (p = 0; p < w->images[index]->numPlanes; p++) + { + len += w->images[index]->plane[p].numBytes; + } + return len; + } + else + return 0; +} + + + diff --git a/source/dvp/dvp_kgm_cpu/Android.mk b/source/dvp/dvp_kgm_cpu/Android.mk new file mode 100644 index 0000000..1308ea7 --- /dev/null +++ b/source/dvp/dvp_kgm_cpu/Android.mk @@ -0,0 +1,70 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH:=$(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(DVP_DEBUGGING) $(DVP_CFLAGS) $(DVP_FEATURES) +LOCAL_SRC_FILES := dvp_kgm_cpu.c dvp_ll.c +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_MODULE := libdvp_kgm_cpu +LOCAL_STATIC_LIBRARIES := +LOCAL_SHARED_LIBRARIES := libcutils libdvp + +# All the Features should have been defined in the dvp/libraries makefiles + +ifeq ($(TARGET_SCPU),C64T) +ifneq (,$(findstring c6xsim,$(VISION_LIBRARIES)) +LOCAL_STATIC_LIBRARIES += libc6xsim_$(TARGET_CPU) +endif +endif + +ifneq (,$(findstring vlib,$(VISION_LIBRARIES))) +LOCAL_STATIC_LIBRARIES += libvlib_$(TARGET_CPU) +endif + +ifneq (,$(findstring rvm,$(VISION_LIBRARIES))) +LOCAL_STATIC_LIBRARIES += librvm_$(TARGET_CPU) +endif + +ifneq (,$(findstring rvm_sunex,$(VISION_LIBRARIES))) +LOCAL_STATIC_LIBRARIES += librvm_sunex_$(TARGET_CPU) +endif + +ifneq (,$(findstring orb,$(VISION_LIBRARIES))) +LOCAL_STATIC_LIBRARIES += liborb_$(TARGET_CPU) +endif + +ifneq (,$(findstring tismo,$(VISION_LIBRARIES))) +LOCAL_STATIC_LIBRARIES += libtismo_$(TARGET_CPU) +endif + +ifneq (,$(findstring yuv,$(VISION_LIBRARIES))) +LOCAL_STATIC_LIBRARIES += libyuv +endif + +ifneq (,$(findstring imgfilter,$(VISION_LIBRARIES))) +LOCAL_STATIC_LIBRARIES += libimgfilter +endif + +ifneq (,$(findstring imglib,$(VISION_LIBRARIES))) +LOCAL_STATIC_LIBRARIES += libimglib_$(TARGET_CPU) +endif + +#$(info LOCAL_STATIC_LIBRARIES=$(LOCAL_STATIC_LIBRARIES)) + +include $(BUILD_SHARED_LIBRARY) + diff --git a/source/dvp/dvp_kgm_cpu/concerto.mak b/source/dvp/dvp_kgm_cpu/concerto.mak new file mode 100644 index 0000000..89bd816 --- /dev/null +++ b/source/dvp/dvp_kgm_cpu/concerto.mak @@ -0,0 +1,63 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(PRELUDE) +TARGET=dvp_kgm_cpu +DEFS+=$(DVP_FEATURES) DVP_USE_IMAGE +TARGETTYPE=dsmo +CSOURCES+=dvp_kgm_cpu.c dvp_ll.c +DEFFILE=dvp_kgm.def +SHARED_LIBS=dvp +STATIC_LIBS=sosal +IDIRS+=$(DVP_INC) $(DVP_INT_INC) +LDIRS+=$(VISION_LIB) + +ifeq ($(TARGET_CPU),ARM) + IDIRS+=$(MEM_INCS) +endif + +ifneq (,$(findstring vlib,$(VISION_LIBRARIES))) +SYS_STATIC_LIBS += vlib_$(TARGET_CPU) +endif + +ifneq (,$(findstring rvm,$(VISION_LIBRARIES))) +SYS_STATIC_LIBS += rvm_$(TARGET_CPU) +endif + +ifneq (,$(findstring rvm_sunex,$(VISION_LIBRARIES))) +SYS_STATIC_LIBS += rvm_sunex_$(TARGET_CPU) +endif + +ifneq (,$(findstring imglib,$(VISION_LIBRARIES))) +SYS_STATIC_LIBS += imglib_$(TARGET_CPU) +endif + +ifneq (,$(findstring orb,$(VISION_LIBRARIES))) +SYS_STATIC_LIBS += orb_$(TARGET_CPU) +endif + +ifneq (,$(findstring tismo,$(VISION_LIBRARIES))) +#SYS_STATIC_LIBS += tismo +endif + +ifneq (,$(findstring yuv,$(VISION_LIBRARIES))) +SYS_STATIC_LIBS += yuv +endif + +ifneq (,$(findstring imgfilter,$(VISION_LIBRARIES))) +SYS_STATIC_LIBS += imgfilter +endif + +include $(FINALE) + diff --git a/source/dvp/dvp_kgm_cpu/dvp_kgm.def b/source/dvp/dvp_kgm_cpu/dvp_kgm.def new file mode 100644 index 0000000..2fa8907 --- /dev/null +++ b/source/dvp/dvp_kgm_cpu/dvp_kgm.def @@ -0,0 +1,11 @@ +LIBRARY "dvp_kgm_cpu.dll" +EXPORTS + DVP_KernelGraphManagerInit + DVP_GetSupportedKernels + DVP_GetSupportedLocalCalls + DVP_GetSupportedRemoteCalls + DVP_GetSupportedRemoteCore + DVP_KernelGraphManager + DVP_KernelGraphManagerDeinit + DVP_GetMaximumLoad + diff --git a/source/dvp/dvp_kgm_cpu/dvp_kgm_cpu.c b/source/dvp/dvp_kgm_cpu/dvp_kgm_cpu.c new file mode 100644 index 0000000..82f1135 --- /dev/null +++ b/source/dvp/dvp_kgm_cpu/dvp_kgm_cpu.c @@ -0,0 +1,4221 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#include + +#if defined(DVP_USE_VLIB) +#include +#include +#include +#endif + +#if defined(DVP_USE_TILER) +#undef PAGE_SIZE // this is to remove a warning +#include +#endif + +// ARMv7 Optimized Routines +#define DVP_OPTIMIZED_KERNELS +#include + +#if defined(DVP_USE_YUV) +#include +#include +#endif + +#if defined(DVP_USE_IMGFILTER) +#include +#include +#endif + +#if defined(DVP_USE_RVM) +#include +#include +#endif + +#if defined(DVP_USE_IMGLIB) +#include +#include +#endif + +#if defined(DVP_USE_ORB) +#include +#include +static DVP_U08 *orbMem; +static DVP_U08 orbInit; +static CORBInput * orbInput; +#endif + +#define KGM_TAG "DVP KGM CPU" + +#if defined(DVP_USE_VLIB) || defined(DVP_USE_IMGLIB) +static DVP_S16 yuv2rgbMatrix[5] = {8192, 11229, -2757, -5720, 14192}; +#endif + +#if defined(DVP_USE_VLIB) +static S16 saturate_s16(S32 v) +{ + if (v > MAX_S16) + v = MAX_S16; + if (v < -MAX_S16) + v = -MAX_S16; + return v; +} +#endif + +#if defined(DVP_OPTIMIZED_KERNELS) && defined(DVP_USE_YUV) +typedef enum _dvp_optimized_kernels_e { + DVP_KN_OPT_UYVY_TO_RGBp_LUMA_YUV444p = DVP_KN_LOCAL_OPTIMIZED_BASE + 1, + DVP_KN_OPT_UYVY_TO_RGBp_YUV444p_LUMA, + DVP_KN_OPT_UYVY_TO_YUV444p_LUMA_RGBp, + DVP_KN_OPT_UYVY_TO_YUV444p_RGBp_LUMA, + DVP_KN_OPT_UYVY_TO_LUMA_YUV444p_RGBp, + DVP_KN_OPT_UYVY_TO_LUMA_RGBp_YUV444p, +} DVP_OptimizedKernels_e; + +typedef struct _dvp_optimized_kernels_t { + DVP_OptimizedKernels_e optkernel; + DVP_ENUM *kernels; + DVP_U32 numKernels; +} DVP_OptimizedKernels_t; + +DVP_ENUM opt1[] = {DVP_KN_UYVY_TO_RGBp, DVP_KN_XYXY_TO_Y800, DVP_KN_UYVY_TO_YUV444p}; +DVP_ENUM opt2[] = {DVP_KN_UYVY_TO_RGBp, DVP_KN_UYVY_TO_YUV444p, DVP_KN_XYXY_TO_Y800}; +DVP_ENUM opt3[] = {DVP_KN_UYVY_TO_YUV444p, DVP_KN_XYXY_TO_Y800, DVP_KN_UYVY_TO_RGBp}; +DVP_ENUM opt4[] = {DVP_KN_UYVY_TO_YUV444p, DVP_KN_UYVY_TO_RGBp, DVP_KN_XYXY_TO_Y800}; +DVP_ENUM opt5[] = {DVP_KN_XYXY_TO_Y800, DVP_KN_UYVY_TO_YUV444p, DVP_KN_UYVY_TO_RGBp}; +DVP_ENUM opt6[] = {DVP_KN_XYXY_TO_Y800, DVP_KN_UYVY_TO_RGBp, DVP_KN_UYVY_TO_YUV444p}; + +DVP_OptimizedKernels_t optkerns[] = { + {DVP_KN_OPT_UYVY_TO_RGBp_LUMA_YUV444p, opt1, dimof(opt1)}, + {DVP_KN_OPT_UYVY_TO_RGBp_YUV444p_LUMA, opt2, dimof(opt2)}, + {DVP_KN_OPT_UYVY_TO_YUV444p_LUMA_RGBp, opt3, dimof(opt3)}, + {DVP_KN_OPT_UYVY_TO_YUV444p_RGBp_LUMA, opt4, dimof(opt4)}, + {DVP_KN_OPT_UYVY_TO_LUMA_YUV444p_RGBp, opt5, dimof(opt5)}, + {DVP_KN_OPT_UYVY_TO_LUMA_RGBp_YUV444p, opt6, dimof(opt6)}, +}; +DVP_U32 numOptKerns = dimof(optkerns); +#endif + + +/*! \brief The list of locally supported kernels. + * \note Please list features first, then algo library specific versions. + * \note Also, please list any algo specific versions with the algo library + * name in the description. + */ +static DVP_CoreFunction_t local_kernels[] = { + // name, kernel, priority, load + + //*************************************** + // FEATURE LIST + //*************************************** + + {"No operation", DVP_KN_NOOP, 0}, + {"Threshold", DVP_KN_THRESHOLD, 0}, + {"XStrideConvert", DVP_KN_XSTRIDE_CONVERT, 0}, + {"XStrideShift", DVP_KN_XSTRIDE_SHIFT, 0}, + {"Image Copy", DVP_KN_ECHO, 0}, + {"Image Debug", DVP_KN_IMAGE_DEBUG, 0}, + {"Buffer Debug", DVP_KN_BUFFER_DEBUG, 0}, + {"Gamma", DVP_KN_GAMMA, 0}, + +#if defined(DVP_USE_VLIB) + {"\"C\" DilateCross", DVP_KN_DILATE_CROSS, 0}, + {"\"C\" DilateMask", DVP_KN_DILATE_MASK, 0}, + {"\"C\" DilateSquare", DVP_KN_DILATE_SQUARE, 0}, + {"\"C\" ErodeCross", DVP_KN_ERODE_CROSS, 0}, + {"\"C\" ErodeMask", DVP_KN_ERODE_MASK, 0}, + {"\"C\" ErodeSquare", DVP_KN_ERODE_SQUARE, 0}, + + {"\"C\" Canny2DGradient", DVP_KN_CANNY_2D_GRADIENT, 0}, + {"\"C\" CannyNonmaxSupress", DVP_KN_CANNY_NONMAX_SUPPRESSION, 0}, + {"\"C\" CannyHyst.Thresh", DVP_KN_CANNY_HYST_THRESHHOLD, 0}, + + {"\"C\" IIRHorz", DVP_KN_IIR_HORZ, 0}, + {"\"C\" IIRVert", DVP_KN_IIR_VERT, 0}, + + {"\"C\" IntegralImg8", DVP_KN_INTEGRAL_IMAGE_8, 0}, + + {"\"C\" Nonmaxsupress3x316", DVP_KN_NONMAXSUPPRESS_3x3_S16, 0}, + {"\"C\" Nonmaxsupress5x516", DVP_KN_NONMAXSUPPRESS_5x5_S16, 0}, + {"\"C\" Nonmaxsupress7x716", DVP_KN_NONMAXSUPPRESS_7x7_S16, 0}, + + {"\"C\" YXYX to LUMA", DVP_KN_YXYX_TO_Y800, 0}, + {"\"C\" YUV422p to UYVY", DVP_KN_YUV422p_TO_UYVY, 0}, + {"\"C\" UYVY to YUV422p", DVP_KN_UYVY_TO_YUV422p, 0}, +#endif + +#if defined(DVP_USE_IMGLIB) + {"\"C\" YUV420p to RGB565", DVP_KN_YUV422p_TO_RGB565, 0}, + {"\"C\" Sobel 3x3", DVP_KN_SOBEL_3x3_8, 0}, +// {"\"C\" Sobel 3x3_16s", DVP_KN_SOBEL_3x3_16s, 0}, //Removing due to mismatch with SIMCOP +// {"\"C\" Sobel 5x5_16s", DVP_KN_SOBEL_5x5_16s, 0}, +// {"\"C\" Sobel 7x7_16s", DVP_KN_SOBEL_7x7_16s, 0}, + {"\"C\" Conv 3x3", DVP_KN_CONV_3x3, 0}, + {"\"C\" Conv 5x5", DVP_KN_CONV_5x5, 0}, + {"\"C\" Conv 7x7", DVP_KN_CONV_7x7, 0}, + + {"\"C\" CannyImgSmooth", DVP_KN_CANNY_IMAGE_SMOOTHING, 0}, + + {"\"C\" YUV420p to RGB565", DVP_KN_IMG_YUV422p_TO_RGB565, 0}, + {"\"C\" Img Sobel 3x3", DVP_KN_IMG_SOBEL_3x3_8, 0}, + {"\"C\" Img sobel 3x3_16s", DVP_KN_IMG_SOBEL_3x3_16s, 0}, + {"\"C\" Img sobel 5x5_16s", DVP_KN_IMG_SOBEL_5x5_16s, 0}, + {"\"C\" Img sobel 7x7_16s", DVP_KN_IMG_SOBEL_7x7_16s, 0}, + {"\"C\" Img Clipping 16", DVP_KN_IMG_CLIPPING_16, 0}, + {"\"C\" Img Boundary8", DVP_KN_IMG_BOUNDARY_8, 0}, + {"\"C\" Img Boundary16s", DVP_KN_IMG_BOUNDARY_16s, 0}, + {"\"C\" Img Correlation 3x3", DVP_KN_IMG_CORR_3x3, 0}, + {"\"C\" Img Correlation 3x3 I8 C16s", DVP_KN_IMG_CORR_3x3_I8_C16s, 0}, + {"\"C\" Img Correlation 3x3 I16s C16s", DVP_KN_IMG_CORR_3x3_I16s_C16s, 0}, + {"\"C\" Img Correlation 5x5 I16s C16s", DVP_KN_IMG_CORR_5x5_I16s_C16s, 0}, + {"\"C\" Img Correlation 11x11 I8 C16s", DVP_KN_IMG_CORR_11x11_I8_C16s, 0}, + {"\"C\" Img Correlation 11x11 I16s C16s", DVP_KN_IMG_CORR_11x11_I16s_C16s, 0}, + {"\"C\" Img Correlation Gen I16 C16s", DVP_KN_IMG_CORR_GEN_I16s_C16s, 0}, + {"\"C\" Img Correlation Gen Iq", DVP_KN_IMG_CORR_GEN_IQ, 0}, + {"\"C\" Img Histogram8", DVP_KN_IMG_HISTOGRAM_8, 0}, + {"\"C\" Img Histogram16", DVP_KN_IMG_HISTOGRAM_16, 0}, + {"\"C\" Img Median 3x3 8", DVP_KN_IMG_MEDIAN_3x3_8, 0}, + {"\"C\" Img Median 3x3 16s", DVP_KN_IMG_MEDIAN_3x3_16s, 0}, + {"\"C\" Img Demux LE 8", DVP_KN_IMG_YC_DEMUX_LE16_8, 0}, + {"\"C\" Img Demux BE 8", DVP_KN_IMG_YC_DEMUX_BE16_8, 0}, + {"\"C\" Img Pix Sat ", DVP_KN_IMG_PIX_SAT, 0}, + {"\"C\" Img Pix Expand ", DVP_KN_IMG_PIX_EXPAND, 0}, + {"\"C\" Img SAD 3x3", DVP_KN_IMG_SAD_3x3, 0}, + {"\"C\" Img SAD 5x5", DVP_KN_IMG_SAD_5x5, 0}, + {"\"C\" Img SAD 7x7", DVP_KN_IMG_SAD_7x7, 0}, + {"\"C\" Img SAD 8x8", DVP_KN_IMG_SAD_8x8, 0}, + {"\"C\" Img SAD 16x16", DVP_KN_IMG_SAD_16x16, 0}, + {"\"C\" Img Conv 3x3", DVP_KN_IMG_CONV_3x3, 0}, + {"\"C\" Img Conv 5x5", DVP_KN_IMG_CONV_5x5, 0}, + {"\"C\" Img Conv 7x7", DVP_KN_IMG_CONV_7x7, 0}, + {"\"C\" Img Conv 11x11", DVP_KN_IMG_CONV_11x11, 0}, + {"\"C\" Img Conv 5x5 i8 c16s", DVP_KN_IMG_CONV_5x5_I8_C16, 0}, + {"\"C\" Img Conv 7x7 i8 c16s", DVP_KN_IMG_CONV_7x7_I8_C16, 0}, + {"\"C\" Img Conv 3x3 i16s c16s", DVP_KN_IMG_CONV_3x3_I16s_C16, 0}, + {"\"C\" Img Conv 5x5 i16 c16s", DVP_KN_IMG_CONV_5x5_I16s_C16, 0}, + {"\"C\" Img Conv 7x7 i16 c16s", DVP_KN_IMG_CONV_7x7_I16s_C16, 0}, + {"\"C\" Img Conv 11x11 i16s c16s", DVP_KN_IMG_CONV_11x11_I16s_C16, 0}, + {"\"C\" Thr gt2max8", DVP_KN_THR_GT2MAX_8, 0}, + {"\"C\" Thr gt2max16", DVP_KN_THR_GT2MAX_16, 0}, + {"\"C\" Thr gt2thr8", DVP_KN_THR_GT2THR_8, 0}, + {"\"C\" Thr gt2thr16", DVP_KN_THR_GT2THR_16, 0}, + {"\"C\" Thr le2min8", DVP_KN_THR_LE2MIN_8, 0}, + {"\"C\" Thr le2min16", DVP_KN_THR_LE2MIN_16, 0}, + {"\"C\" Thr le2thr8", DVP_KN_THR_LE2THR_8, 0}, + {"\"C\" Thr le2thr16", DVP_KN_THR_LE2THR_16, 0}, + {"\"C\" Img Boundary8", DVP_KN_IMG_BOUNDARY_8, 0}, + {"\"C\" Img Boundary16s", DVP_KN_IMG_BOUNDARY_16s, 0}, + {"\"C\" Img Perimeter8", DVP_KN_IMG_PERIMETER_8, 0}, + {"\"C\" Img Perimeter16", DVP_KN_IMG_PERIMETER_16, 0}, + {"\"C\" Img ErrDiff 8", DVP_KN_IMG_ERRDIFF_BIN_8, 0}, + {"\"C\" Img ErrDiff 16", DVP_KN_IMG_ERRDIFF_BIN_16, 0}, + {"\"C\" Img FDCT 8x8", DVP_KN_IMG_FDCT_8x8, 0}, + {"\"C\" Img IFDCT 8x8", DVP_KN_IMG_IDCT_8x8_12Q4, 0}, + {"\"C\" Img MAD 8x8", DVP_KN_IMG_MAD_8x8, 0}, + {"\"C\" Img MAD 16x16", DVP_KN_IMG_MAD_16x16, 0}, + {"\"C\" Img Quantization 16", DVP_KN_IMG_QUANTIZE_16, 0}, + {"\"C\" Img Wavelet Horz", DVP_KN_IMG_WAVE_HORZ, 0}, +#endif + +#if defined(DVP_USE_YUV) + {"NEON xYxY to LUMA", DVP_KN_XYXY_TO_Y800, 0}, + {"NEON UYVY to YUV420p", DVP_KN_UYVY_TO_YUV420p, 0}, + {"NEON UYVY to YUV444p", DVP_KN_UYVY_TO_YUV444p, 0}, + {"NEON UYVY to RGBp", DVP_KN_UYVY_TO_RGBp, 0}, +#elif defined(DVP_USE_VLIB) + {"\"C\" xYxY to LUMA", DVP_KN_XYXY_TO_Y800, 0}, + {"\"C\" UYVY to YUV420p", DVP_KN_UYVY_TO_YUV420p, 0}, + {"\"C\" UYVY to YUV444p", DVP_KN_UYVY_TO_YUV444p, 0}, + {"\"C\" UYVY to RGBp", DVP_KN_UYVY_TO_RGBp, 0}, +#endif + +#if defined(DVP_USE_YUV) + {"NEON NV12 to YUV444p Half Scale", DVP_KN_NV12_TO_YUV444p, 0}, + {"NEON BGR3 to UYVY", DVP_KN_BGR3_TO_UYVY, 0}, + {"NEON BGR3 to IYUV", DVP_KN_BGR3_TO_IYUV, 0}, +#elif defined(DVP_USE_IMAGE) + {"\"C\" NV12 to YUV444p", DVP_KN_NV12_TO_YUV444p, 0}, + {"\"C\" RGB3 to UYVY", DVP_KN_BGR3_TO_UYVY, 0}, + {"\"C\" BGR3 to IYUV", DVP_KN_BGR3_TO_IYUV, 0}, +#endif + +#if defined(DVP_USE_YUV) + {"NEON LUMA to xYxY", DVP_KN_Y800_TO_XYXY, 0}, + {"NEON YUV420 to RGBp", DVP_KN_YUV420p_TO_RGBp, 0}, + {"NEON UYVY to BGR", DVP_KN_UYVY_TO_BGR, 0}, +#endif + +#if defined(DVP_USE_IMAGE) + {"\"C\" YUV444 to RGBP", DVP_KN_YUV444p_TO_RGBp, 0}, + {"\"C\" YUV444p to UYVY ", DVP_KN_YUV444p_TO_UYVY, 0}, + {"\"C\" NV12 to UYVY", DVP_KN_NV12_TO_UYVY, 0}, + {"\"C\" RGB3 to NV12", DVP_KN_BGR3_TO_NV12, 0}, +#endif + +#if defined(DVP_USE_IMGFILTER) + {"NEON Sobel3x3", DVP_KN_SOBEL_8, 0}, + {"NEON Scharr3x3", DVP_KN_SCHARR_8, 0}, + {"NEON Kroon3x3", DVP_KN_KROON_8, 0}, + {"NEON Prewitt3x3", DVP_KN_PREWITT_8, 0}, +#elif defined(DVP_USE_VLIB) + {"\"C\" Sobel3x3", DVP_KN_SOBEL_8, 0}, + {"\"C\" Scharr3x3", DVP_KN_SCHARR_8, 0}, + {"\"C\" Kroon3x3", DVP_KN_KROON_8, 0}, + {"\"C\" Prewitt3x3", DVP_KN_PREWITT_8, 0}, +#endif + + //*************************************** + // ALGO LIBRARY SPECIFIC LIST + //*************************************** + +#if defined(DVP_USE_VLIB) + {"\"C\" VLIB UYVY to HSLp", DVP_KN_VLIB_UYVY_TO_HSLp, 0}, + {"\"C\" VLIB UYVY to LABp", DVP_KN_VLIB_UYVY_TO_LABp, 0}, + {"\"C\" VLIB YUV422p to UYVY", DVP_KN_VLIB_YUV422p_TO_UYVY, 0}, + {"\"C\" VLIB EWRMeanS16", DVP_KN_VLIB_EWR_MEAN_S16, 0}, + {"\"C\" VLIB EWRVarS16", DVP_KN_VLIB_EWR_VAR_S16, 0}, + {"\"C\" VLIB EWRMeanS32", DVP_KN_VLIB_EWR_MEAN_S32, 0}, + {"\"C\" VLIB EWRVarS32", DVP_KN_VLIB_EWR_VAR_S32, 0}, + {"\"C\" VLIB UWRMeanS16", DVP_KN_VLIB_UWR_MEAN_S16, 0}, + {"\"C\" VLIB UWRVarS16", DVP_KN_VLIB_UWR_VAR_S16, 0}, + + {"\"C\" VLIB BackSubS16", DVP_KN_VLIB_SUB_BACK_S16, 0}, + {"\"C\" VLIB BackSubS32", DVP_KN_VLIB_SUB_BACK_S32, 0}, + {"\"C\" VLIB MixofGaussS16", DVP_KN_VLIB_MOG_S16, 0}, + {"\"C\" VLIB MixofGaussS32", DVP_KN_VLIB_MOG_S32, 0}, + {"\"C\" VLIB ExtractBack16", DVP_KN_VLIB_EXTRACT_BACK_8_16, 0}, + + {"\"C\" VLIB PackMask32", DVP_KN_VLIB_PACK_MASK_32, 0}, + {"\"C\" VLIB UnPackMask32", DVP_KN_VLIB_UNPACK_MASK_32, 0}, + + {"\"C\" VLIB DilateCross", DVP_KN_VLIB_DILATE_CROSS, 0}, + {"\"C\" VLIB DilateMask", DVP_KN_VLIB_DILATE_MASK, 0}, + {"\"C\" VLIB DilateSquare", DVP_KN_VLIB_DILATE_SQUARE, 0}, + {"\"C\" VLIB ErodeCross", DVP_KN_VLIB_ERODE_CROSS, 0}, + {"\"C\" VLIB ErodeMask", DVP_KN_VLIB_ERODE_MASK, 0}, + {"\"C\" VLIB ErodeSquare", DVP_KN_VLIB_ERODE_SQUARE, 0}, + + {"\"C\" VLIB Erode1Pixel", DVP_KN_VLIB_ERODE_SINGLEPIXEL, 0}, + + {"\"C\" VLIB ConnectedComponent", DVP_KN_VLIB_CCL, 0}, + + {"\"C\" VLIB Canny2DGradient", DVP_KN_VLIB_CANNY_2D_GRADIENT, 0}, + {"\"C\" VLIB CannyNonmaxSupress", DVP_KN_VLIB_CANNY_NONMAX_SUPPRESSION, 0}, + {"\"C\" VLIB CannyHyst.Thresh", DVP_KN_VLIB_CANNY_HYST_THRESHHOLD, 0}, + + {"\"C\" VLIB ImgPyramid8", DVP_KN_VLIB_IMAGE_PYRAMID_8, 0}, + {"\"C\" VLIB ImgPyramid16", DVP_KN_VLIB_IMAGE_PYRAMID_16, 0}, + + {"\"C\" VLIB Gauss5x5Pyramid8", DVP_KN_VLIB_GAUSSIAN_5x5_PYRAMID_8, 0}, + {"\"C\" VLIB Gauss5x5Pyramid16", DVP_KN_VLIB_GAUSSIAN_5x5_PYRAMID_16, 0}, + + {"\"C\" VLIB GradientH5x5Pyramid8", DVP_KN_VLIB_GRADIENT_H5x5_PYRAMID_8, 0}, + {"\"C\" VLIB GradientV5x5Pyramid8", DVP_KN_VLIB_GRADIENT_V5x5_PYRAMID_8, 0}, + + {"\"C\" VLIB HarrisScore", DVP_KN_VLIB_HARRIS_SCORE_7x7, 0}, + {"\"C\" VLIB HarrisScore7x7_U32", DVP_KN_VLIB_HARRIS_SCORE_7x7_U32, 0}, + + {"\"C\" VLIB IIRHorz", DVP_KN_VLIB_IIR_HORZ, 0}, + {"\"C\" VLIB IIRHorz16", DVP_KN_VLIB_IIR_HORZ_16, 0}, + {"\"C\" VLIB IIRVert", DVP_KN_VLIB_IIR_VERT, 0}, + {"\"C\" VLIB IIRVert16", DVP_KN_VLIB_IIR_VERT_16, 0}, + + {"\"C\" VLIB Integral Image 8", DVP_KN_VLIB_INTEGRAL_IMAGE_8, 0}, + {"\"C\" VLIB Integral Image 16", DVP_KN_VLIB_INTEGRAL_IMAGE_16, 0}, + + {"\"C\" VLIB HoughLine", DVP_KN_VLIB_HOUGH_LINE_FROM_LIST, 0}, + {"\"C\" VLIB Hysterisis Threshold", DVP_KN_VLIB_HYST_THRESHOLD, 0}, + + {"\"C\" VLIB Nonmaxsuppress 3x3 S16", DVP_KN_VLIB_NONMAXSUPPRESS_3x3_S16, 0}, + {"\"C\" VLIB Nonmaxsuppress 5x5 S16", DVP_KN_VLIB_NONMAXSUPPRESS_5x5_S16, 0}, + {"\"C\" VLIB Nonmaxsuppress 7x7 S16", DVP_KN_VLIB_NONMAXSUPPRESS_7x7_S16, 0}, + {"\"C\" VLIB Nonmaxsuppress MxN U32", DVP_KN_VLIB_NONMAXSUPPRESS_U32, 0}, + + {"\"C\" VLIB NormalFlow 16", DVP_KN_VLIB_NORMALFLOW_16, 0}, + //{"\"C\" VLIB Kalman2x4", DVP_KN_VLIB_KALMAN_2x4, 0}, + //{"\"C\" VLIB Kalman4x6", DVP_KN_VLIB_KALMAN_4x6, 0}, + {"\"C\" VLIB Nelder-MeadSimplex16", DVP_KN_VLIB_NEDLER_MEAD_SIMPLEX_16, 0}, + {"\"C\" VLIB Nelder-MeanSimplex3D", DVP_KN_VLIB_NEDLER_MEAD_SIMPLEX_3D, 0}, + //{"\"C\" VLIB LegendreMoments", DVP_KN_VLIB_LEGENDRE_MOMENTS, 0}, + + {"\"C\" VLIB InitHistgram8", DVP_KN_VLIB_INIT_HISTOGRAM_8, 0}, + {"\"C\" VLIB Histogram8", DVP_KN_VLIB_HISTOGRAM_8, 0}, + {"\"C\" VLIB InitHistogram16", DVP_KN_VLIB_INIT_HISTOGRAM_16, 0}, + {"\"C\" VLIB Histogram16", DVP_KN_VLIB_HISTOGRAM_16, 0}, + {"\"C\" VLIB WeightedHistogram8", DVP_KN_VLIB_WEIGHTED_HISTOGRAM_8, 0}, + {"\"C\" VLIB WeightedHistogram16", DVP_KN_VLIB_WEIGHTED_HISTOGRAM_16, 0}, + + {"\"C\" VLIB HistogramnD16", DVP_KN_VLIB_HISTOGRAM_ND_16, 0}, + {"\"C\" VLIB BhattacharyyaDistance", DVP_KN_VLIB_BHATTACHAYA_DISTANCE, 0}, + + {"\"C\" VLIB L1Distance", DVP_KN_VLIB_L1DISTANCE, 0}, + + {"\"C\" VLIB Lucas Kanade Tracking", DVP_KN_VLIB_TRACK_FEATURES_LUCAS_7x7, 0}, +#if defined(VLIB_DISPARITY_FIXED) + {"\"C\" VLIB Disparity8", DVP_KN_VLIB_DISPARITY_SAD8, 0}, + {"\"C\" VLIB Disparity16", DVP_KN_VLIB_DISPARITY_SAD16, 0}, +#endif + {"\"C\" VLIB MeanLuma16", DVP_KN_VLIB_INIT_MEAN_LUMA_S16, 0}, + {"\"C\" VLIB MeanLuma32", DVP_KN_VLIB_INIT_MEAN_LUMA_S32, 0}, + {"\"C\" VLIB VarConst16", DVP_KN_VLIB_INIT_VAR_CONST_S16, 0}, + {"\"C\" VLIB VarConst32", DVP_KN_VLIB_INIT_VAR_CONST_S32, 0}, + + {"\"C\" VLIB YxYx to LUMA", DVP_KN_VLIB_YXYX_TO_Y800, 0}, + {"\"C\" VLIB YUV422p to UYVY", DVP_KN_VLIB_YUV422p_TO_UYVY, 0}, + {"\"C\" VLIB UYVY to YUV422p", DVP_KN_VLIB_UYVY_TO_YUV422p, 0}, + +#endif //DVP_USE_VLIB + +#if defined(DVP_USE_IMGLIB) + {"\"C\" IMGLIB Sobel 3x3", DVP_KN_IMG_SOBEL_3x3_8, 0}, + + {"\"C\" IMGLIB Conv 3x3", DVP_KN_IMG_CONV_3x3, 0}, + {"\"C\" IMGLIB Conv 5x5", DVP_KN_IMG_CONV_5x5, 0}, + {"\"C\" IMGLIB Conv 7x7", DVP_KN_IMG_CONV_7x7, 0}, + + {"\"C\" IMGLIB Thr gt2max8", DVP_KN_IMG_THR_GT2MAX_8, 0}, + {"\"C\" IMGLIB Thr gt2max16", DVP_KN_IMG_THR_GT2MAX_16, 0}, + {"\"C\" IMGLIB Thr gt2thr8", DVP_KN_IMG_THR_GT2THR_8, 0}, + {"\"C\" IMGLIB Thr gt2thr16", DVP_KN_IMG_THR_GT2THR_16, 0}, + {"\"C\" IMGLIB Thr le2min8", DVP_KN_IMG_THR_LE2MIN_8, 0}, + {"\"C\" IMGLIB Thr le2min16", DVP_KN_IMG_THR_LE2MIN_16, 0}, + {"\"C\" IMGLIB Thr le2thr8", DVP_KN_IMG_THR_LE2THR_8, 0}, + {"\"C\" IMGLIB Thr le2thr16", DVP_KN_IMG_THR_LE2THR_16, 0}, + + {"\"C\" IMGLIB Boundary8", DVP_KN_IMG_BOUNDARY_8, 0}, + {"\"C\" IMGLIB Boundary16s", DVP_KN_IMG_BOUNDARY_16s, 0}, + {"\"C\" IMGLIB Perimeter8", DVP_KN_IMG_PERIMETER_8, 0}, + {"\"C\" IMGLIB Perimeter16", DVP_KN_IMG_PERIMETER_16, 0}, +#endif + +#if defined(DVP_USE_YUV) + {"NEON \"YUV\" xYxY to LUMA", DVP_KN_YUV_XYXY_TO_Y800, 0}, + {"NEON \"YUV\" UYVY to YUV420p", DVP_KN_YUV_UYVY_TO_IYUV, 0}, + {"NEON \"YUV\" UYVY to YUV444p", DVP_KN_YUV_UYVY_TO_YU24, 0}, + {"NEON \"YUV\" UYVY to RGBp", DVP_KN_YUV_UYVY_TO_RGBp, 0}, +#elif defined(DVP_USE_VLIB) + {"\"C\" VLIB xYxY to LUMA", DVP_KN_VLIB_XYXY_TO_Y800, 0}, + {"\"C\" VLIB UYVY to YUV420p", DVP_KN_VLIB_UYVY_TO_YUV420p, 0}, + {"\"C\" VLIB UYVY to YUV444p", DVP_KN_VLIB_UYVY_TO_YUV444p, 0}, + {"\"C\" VLIB UYVY to RGBp", DVP_KN_VLIB_UYVY_TO_RGBp, 0}, +#endif + +#if defined(DVP_USE_YUV) + {"NEON \"YUV\" YUV444 to RGBp", DVP_KN_YUV_IYUV_TO_RGBp, 0}, + {"NEON \"YUV\" LUMA to xYxY", DVP_KN_YUV_Y800_TO_XYXY, 0}, + {"NEON \"YUV\" NV12 to YUV444p", DVP_KN_YUV_NV12_TO_YU24_HALF_SCALE, 0}, + {"NEON \"YUV\" UYVY HALF SCALE", DVP_KN_YUV_UYVY_HALF_SCALE, 0}, + {"NEON \"YUV\" UYVY QTR SCALE", DVP_KN_YUV_UYVY_QTR_SCALE, 0}, + {"NEON \"YUV\" PLANAR ROTATE CW90", DVP_KN_YUV_Y800_ROTATE_CW_90, 0}, + {"NEON \"YUV\" PLANAR ROTATE CCW90", DVP_KN_YUV_Y800_ROTATE_CCW_90, 0}, + {"NEON \"YUV\" UYVY ROTATE CW90", DVP_KN_YUV_UYVY_ROTATE_CW_90, 0}, + {"NEON \"YUV\" UYVY ROTATE CCW90", DVP_KN_YUV_UYVY_ROTATE_CCW_90, 0}, + {"NEON \"YUV\" UYVY to BGR", DVP_KN_YUV_UYVY_TO_BGR, 0}, + {"NEON \"YUV\" ARGB to UYVY", DVP_KN_YUV_ARGB_TO_UYVY, 0}, + + {"NEON \"YUV\" BGR3 to UYVY", DVP_KN_YUV_BGR_TO_UYVY, 0}, + {"NEON \"YUV\" BGR3 to IYUV", DVP_KN_YUV_BGR_TO_IYUV, 0}, +#endif + +#if defined(DVP_USE_IMGFILTER) + {"NEON IMGFILTER Sobel3x3", DVP_KN_IMGFILTER_SOBEL, 0}, + {"NEON IMGFILTER Scharr3x3", DVP_KN_IMGFILTER_SCHARR, 0}, + {"NEON IMGFILTER Kroon3x3", DVP_KN_IMGFILTER_KROON, 0}, + {"NEON IMGFILTER Prewitt3x3", DVP_KN_IMGFILTER_PREWITT, 0}, +#elif defined(DVP_USE_VLIB) + {"\"C\" VLIB Sobel3x3", DVP_KN_VLIB_SOBEL_8, 0}, + {"\"C\" VLIB Scharr3x3", DVP_KN_VLIB_SCHARR_8, 0}, + {"\"C\" VLIB Kroon3x3", DVP_KN_VLIB_KROON_8, 0}, + {"\"C\" VLIB Prewitt3x3", DVP_KN_VLIB_PREWITT_8, 0}, +#endif + +#if defined(DVP_USE_RVM) + {"\"C\" RVM", DVP_KN_RVM, 0}, +#endif +#if defined(DVP_USE_ORB) + {"\"C\" ORB", DVP_KN_ORB, 0}, +#endif +}; +static DVP_U32 numLocalKernels = dimof(local_kernels); + +void gamma_apply(DVP_Image_t *input, DVP_Image_t *output, DVP_U08* gammaLut); + +MODULE_EXPORT DVP_U32 DVP_GetSupportedKernels(DVP_CoreFunction_t **pFuncs) +{ + if (pFuncs != NULL) + *pFuncs = local_kernels; + DVP_PRINT(DVP_ZONE_KGM, "Retreiving "KGM_TAG" Kernel Information!\n"); +#if defined(DVP_USE_IMGLIB) + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG" DVP_USE_IMGLIB enabled!\n"); +#endif +#if defined(DVP_USE_VLIB) + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG" DVP_USE_VLIB enabled!\n"); +#endif +#if defined(DVP_USE_YUV) + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG" DVP_USE_YUV enabled!\n"); +#endif +#if defined(DVP_USE_IMAGE) + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG" DVP_USE_IMAGE enabled!\n"); +#endif +#if defined(DVP_USE_RVM) + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG" DVP_USE_RVM enabled!\n"); +#endif + return numLocalKernels; +} + +MODULE_EXPORT DVP_U32 DVP_GetSupportedRemoteCalls(DVP_Function_t **pRemote, DVP_U32 *pNum) +{ + *pRemote = 0; + *pNum = 0; + return 0; +} + +MODULE_EXPORT DVP_U32 DVP_GetSupportedLocalCalls(DVP_Function_t **pLocal, DVP_U32 *pNum) +{ + *pLocal = 0; + *pNum = 0; + return 0; +} + +MODULE_EXPORT DVP_Core_e DVP_GetSupportedRemoteCore() +{ + return DVP_CORE_CPU; +} + +MODULE_EXPORT DVP_U32 DVP_GetMaximumLoad(void) +{ + return TARGET_NUM_CORES * 1000; +} + +static thread_t workers[TARGET_NUM_CORES]; +static queue_t *workqueue; +static queue_t *retqueue; + +static void DVP_Image_to_image_t(image_t *img, DVP_Image_t *pImage) +{ + uint32_t p; + memset(img, 0, sizeof(image_t)); + img->color = pImage->color; + img->numPlanes = pImage->planes; + for (p = 0; p < pImage->planes; p++) + { + img->plane[p].ptr = pImage->pData[p]; + img->plane[p].xdim = pImage->width; + img->plane[p].ydim = pImage->height; + img->plane[p].xstep = 1; + img->plane[p].xscale = 1; + img->plane[p].yscale = 1; + img->plane[p].xstride = pImage->x_stride; + img->plane[p].ystride = pImage->y_stride; + } + switch (img->color) + { + case FOURCC_UYVY: + case FOURCC_YUY2: + case FOURCC_VYUY: + case FOURCC_YVYU: + img->plane[0].xstep = 2; + break; + case FOURCC_NV12: + img->plane[1].xstep = 2; + img->plane[1].xscale = 2; + img->plane[1].yscale = 2; + break; + case FOURCC_IYUV: + case FOURCC_YV12: + img->plane[1].xscale = 2; + img->plane[2].xscale = 2; + img->plane[1].yscale = 2; + img->plane[2].yscale = 2; + break; + case FOURCC_YU16: + case FOURCC_YV16: + img->plane[1].xscale = 2; + img->plane[2].xscale = 2; + break; + default: + break; + } + image_print(img); +} + +static DVP_U32 DVP_KernelGraphManager_CPU(DVP_KernelNode_t *pSubNodes, DVP_U32 startNode, DVP_U32 numNodes) +{ + DVP_U32 n,i = 0; + DVP_S32 processed = 0; + DVP_Perf_t *pPerf = NULL; + DVP_ENUM kernel = 0; + + if (pSubNodes) + { + for (n = startNode; n < (startNode + numNodes); n++) + { + // assume it's not optimized + kernel = pSubNodes[n].header.kernel; + +#if defined(DVP_OPTIMIZED_KERNELS) && defined(DVP_USE_YUV) + // check for optimized kernels + for (i = 0; i < numOptKerns; i++) + { + // if the first kernel in the optimized chain matches + if (optkerns[i].kernels[0] == kernel) + { + DVP_U32 j, k; + DVP_PRINT(DVP_ZONE_KGM, "Kernel %u is possibly optimized by OptKernel %u\n", kernel, optkerns[i].optkernel); + // continue to check + for (j = 1, k = n+1; j < optkerns[i].numKernels && k < numNodes; j++,k++) + { + if (pSubNodes[k].header.kernel != optkerns[i].kernels[j]) + break; + } + // do all kernels match? + if (j == optkerns[i].numKernels) + { + // match! reassign to optimized kernel + kernel = optkerns[i].optkernel; + // pre-increment index over to last relevant node + n += optkerns[i].numKernels - 1; + DVP_PRINT(DVP_ZONE_KGM, "Optimized Kernel %u will be used! It will save %u nodes! Moved to node %u\n", kernel, optkerns[i].numKernels,n); + break; + } + } + } +#endif + +#ifdef DVP_DEBUG + for (i = 0; i < dimof(local_kernels); i++) + { + if (local_kernels[i].kernel == (DVP_KernelNode_e)kernel) { + DVP_PRINT(DVP_ZONE_KGM, "Executing Kernel %s\n",local_kernels[i].name); + } + } +#endif + // initialize the perf pointer and clock rate + pPerf = &pSubNodes[n].header.perf; + pPerf->rate = rtimer_freq(); // fill in the clock rate used to capture data. + DVP_PerformanceStart(pPerf); + + // initialize the error status. Change to an error if one + // occurs. + pSubNodes[n].header.error = DVP_SUCCESS; + + switch (kernel) + { + case DVP_KN_NOOP: + { + break; + } + case DVP_KN_ECHO: + { + DVP_Transform_t *pIO = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + if (DVP_Image_Copy(&pIO->output, &pIO->input) == DVP_FALSE) + { + processed--; + pSubNodes[n].header.error = DVP_ERROR_INVALID_PARAMETER; + } + break; + } + case DVP_KN_THRESHOLD: // Assumes 8bits for now + { + DVP_U32 j, p, y = 0; + DVP_U08 *tmpIn, *tmpOut; + DVP_Transform_t *pIO = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + if (pIO->input.planes == pIO->output.planes && + pIO->input.height == pIO->output.height && + pIO->input.width == pIO->output.width && + pIO->input.x_stride == pIO->output.x_stride) + { + for (p = 0; p < pIO->input.planes; p++) + { + for (y = 0; y < pIO->input.height; y++) + { + tmpIn = (DVP_U08 *) (pIO->input.pData[p] + y*pIO->input.y_stride); + tmpOut = (DVP_U08 *) (pIO->output.pData[p] + y*pIO->output.y_stride); + for(j = 0; j < pIO->input.width; j++) + { + tmpOut[j] = (tmpIn[j] >> 7); // Make binary image + } + } + } + } + else + { + processed--; + pSubNodes[n].header.error = DVP_ERROR_INVALID_PARAMETER; + } + break; + } + case DVP_KN_XSTRIDE_CONVERT: + case DVP_KN_XSTRIDE_SHIFT: + { + DVP_U32 j, p, y = 0; + DVP_Transform_t *pIO = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + if (pIO->input.planes == pIO->output.planes && + pIO->input.height == pIO->output.height && + pIO->input.width == pIO->output.width) + { + for (p = 0; p < pIO->input.planes; p++) + { + if(pIO->input.x_stride == 1 && pIO->output.x_stride == 2) + { + for (y = 0; y < pIO->input.height; y++) + { + DVP_U08 *tmpIn = (DVP_U08 *) (pIO->input.pData[p] + y*pIO->input.y_stride); + DVP_U16 *tmpOut = (DVP_U16 *) (pIO->output.pData[p] + y*pIO->output.y_stride); + if(kernel == DVP_KN_XSTRIDE_CONVERT) + for(j = 0; j < pIO->input.width; j++) + { + tmpOut[j] = tmpIn[j]; + } + else + for(j = 0; j < pIO->input.width; j++) + { + tmpOut[j] = (DVP_U16)(tmpIn[j]<<8); + } + } + } + else if(pIO->input.x_stride == 2 && pIO->output.x_stride == 1) + { + for (y = 0; y < pIO->input.height; y++) + { + DVP_U16 *tmpIn = (DVP_U16 *) (pIO->input.pData[p] + y*pIO->input.y_stride); + DVP_U08 *tmpOut = (DVP_U08 *) (pIO->output.pData[p] + y*pIO->output.y_stride); + if(kernel == DVP_KN_XSTRIDE_CONVERT) + for(j = 0; j < pIO->input.width; j++) + { + tmpOut[j] = (DVP_U08)(tmpIn[j]); + } + else + for(j = 0; j < pIO->input.width; j++) + { + tmpOut[j] = (DVP_U08)(tmpIn[j] >> 8); + } + } + } + else + { + processed--; + pSubNodes[n].header.error = DVP_ERROR_INVALID_PARAMETER; + break; + } + } + } + else + { + processed--; + pSubNodes[n].header.error = DVP_ERROR_INVALID_PARAMETER; + } + break; + } + case DVP_KN_IMAGE_DEBUG: + { + DVP_ImageDebug_t *pImgdbg = dvp_knode_to(&pSubNodes[n], DVP_ImageDebug_t); + DVP_Image_t *pImage = &pImgdbg->image; + +#if defined(DVP_USE_FS) + if (pImgdbg->fp == NULL) + { + PYUV_GetFilename(pImgdbg->fullname, pImgdbg->path, pImgdbg->name, pImage->width, pImage->height, 1, pImage->color); + pImgdbg->fp = fopen(pImgdbg->fullname, "wb+"); + } + if (pImgdbg->fp) + { + DVP_U32 j,y,p,len,n = 0; + // for equal sized plane images + if (pImage->planes == 1) + { + for (p = 0; p < pImage->planes; p++) // loop for each plane + { + for (y = pImage->y_start; y < pImage->height; y++) // loop for each line + { + len = (pImage->x_stride * pImage->width); + j = (y * pImage->y_stride) + (pImage->x_start * pImage->x_stride); + n += (uint32_t)fwrite(&pImage->pData[p][j], 1, len, pImgdbg->fp); + } + fflush(pImgdbg->fp); + } + } + else // for non-isometric planes + { + DVP_U32 x_divisor = 1; + DVP_U32 y_divisor = 1; + if (pImage->color == FOURCC_YVU9 || + pImage->color == FOURCC_YUV9) + { + x_divisor = 4; + y_divisor = 1; + } + else if (pImage->color == FOURCC_YV16 || + pImage->color == FOURCC_YU16) + { + x_divisor = 2; + y_divisor = 1; + } + else if (pImage->color == FOURCC_YV12 || + pImage->color == FOURCC_IYUV) + { + x_divisor = 2; + y_divisor = 2; + } + else if (pImage->color == FOURCC_NV12 || + pImage->color == FOURCC_NV21) + { + y_divisor = 2; + } + for (y = 0; y < pImage->height; y++) + { + len = (pImage->x_stride * pImage->width); + j = (y * pImage->y_stride); + n += (DVP_U32)fwrite(&pImage->pData[0][j], 1, len, pImgdbg->fp); + } + fflush(pImgdbg->fp); + for (p = 1; p < pImage->planes; p++) + { + for (y = 0; y < pImage->height/y_divisor; y++) + { + len = (pImage->x_stride * pImage->width/x_divisor); +#if defined(DVP_USE_TILER) + if (pImage->y_stride == TILER_STRIDE_8BIT) + j = (y * pImage->y_stride); // @NOTE In this case subsampled images are overallocated and use the same stride + else + j = (y * pImage->y_stride/x_divisor); +#else + j = (y * pImage->y_stride/x_divisor); +#endif + n+= (DVP_U32)fwrite(&pImage->pData[p][j], 1, len, pImgdbg->fp); + } + } + fflush(pImgdbg->fp); + } + DVP_PRINT(DVP_ZONE_KGM, "Wrote %u bytes to %s\n", n, pImgdbg->fullname); + } +#endif // DVP_USE_FS + break; + } + case DVP_KN_BUFFER_DEBUG: + { + DVP_U32 n = 0; + DVP_BufferDebug_t *pBufdbg = dvp_knode_to(&pSubNodes[n], DVP_BufferDebug_t); + DVP_Buffer_t *pBuffer = &pBufdbg->buffer; +#if defined(DVP_USE_FS) + if (pBufdbg->fp == NULL) + { + pBufdbg->fp = fopen(pBufdbg->fullname, "wb+"); + } + if (pBufdbg->fp) + { + n += (uint32_t)fwrite(pBuffer->pData, 1, pBuffer->numBytes, pBufdbg->fp); + fflush(pBufdbg->fp); + } +#endif + break; + } + case DVP_KN_GAMMA: + { + DVP_Gamma_t *pGamma = dvp_knode_to(&pSubNodes[n], DVP_Gamma_t); + gamma_apply(&pGamma->input, &pGamma->output, pGamma->gammaLut); + break; + } +#if defined(DVP_USE_YUV) && defined(DVP_OPTIMIZED_KERNELS) + case DVP_KN_OPT_UYVY_TO_RGBp_LUMA_YUV444p: + { + DVP_Image_t *pUYVY = &dvp_knode_to(&pSubNodes[n-2], DVP_Transform_t)->input; + DVP_Image_t *pRGB = &dvp_knode_to(&pSubNodes[n-2], DVP_Transform_t)->output; + DVP_Image_t *pLuma = &dvp_knode_to(&pSubNodes[n-1], DVP_Transform_t)->output; + DVP_Image_t *pYUV444p = &dvp_knode_to(&pSubNodes[n-0], DVP_Transform_t)->output; + /// @todo check to make sure all inputs are identical! + __uyvy_to_rgbp_luma_yuv444p_image(pUYVY->width, + pUYVY->height, + pUYVY->pData[0], + pUYVY->y_stride, + pRGB->pData[0], + pRGB->pData[1], + pRGB->pData[2], + pLuma->pData[0], + pYUV444p->pData[0], + pYUV444p->pData[1], + pYUV444p->pData[2]); + processed += 2; + break; + } + case DVP_KN_OPT_UYVY_TO_YUV444p_LUMA_RGBp: + { + DVP_Image_t *pUYVY = &dvp_knode_to(&pSubNodes[n-2], DVP_Transform_t)->input; + DVP_Image_t *pYUV444p = &dvp_knode_to(&pSubNodes[n-2], DVP_Transform_t)->output; + DVP_Image_t *pLuma = &dvp_knode_to(&pSubNodes[n-1], DVP_Transform_t)->output; + DVP_Image_t *pRGB = &dvp_knode_to(&pSubNodes[n-0], DVP_Transform_t)->output; + /// @todo check to make sure all inputs are identical! + __uyvy_to_rgbp_luma_yuv444p_image(pUYVY->width, + pUYVY->height, + pUYVY->pData[0], + pUYVY->y_stride, + pRGB->pData[0], + pRGB->pData[1], + pRGB->pData[2], + pLuma->pData[0], + pYUV444p->pData[0], + pYUV444p->pData[1], + pYUV444p->pData[2]); + processed += 2; + break; + } +#endif +#if defined(DVP_USE_VLIB) + case DVP_KN_VLIB_MOG_S16: + { + DVP_Mog_t *mog = dvp_knode_to(&pSubNodes[n], DVP_Mog_t); + + VLIB_mixtureOfGaussiansS16((DVP_U08*)mog->image.pData[0], + (DVP_S16*)mog->wts.pData[0], + (DVP_S16*)mog->means.pData[0], + (DVP_S16*)mog->vars.pData[0], + (DVP_U08*)mog->compIndex.pData[0], + (DVP_U08*)mog->scratch.pData[0], + (U32*)mog->fgmask.pData[0], + (S32)(mog->image.width * mog->image.height), + (DVP_S16) mog->alpha, + (DVP_S16) mog->rho, + (DVP_S16) mog->delta, + (DVP_S16) mog->T, + (DVP_S16) mog->ini_wt, + (DVP_S16) mog->ini_var); + break; + } + + + case DVP_KN_VLIB_MOG_S32: + { + DVP_Mog_t *mog = dvp_knode_to(&pSubNodes[n], DVP_Mog_t); + + VLIB_mixtureOfGaussiansS32((DVP_U08*)mog->image.pData[0], + (DVP_S16*)mog->wts.pData[0], + (S32*)mog->means.pData[0], + (S32*)mog->vars.pData[0], + (DVP_U08*)mog->compIndex.pData[0], + (DVP_U08*)mog->scratch.pData[0], + (U32*)mog->fgmask.pData[0], + (S32)(mog->image.width * mog->image.height), + (DVP_S16) mog->alpha, + (S32) mog->rho, + (S32) mog->delta, + (DVP_S16) mog->T, + (DVP_S16) mog->ini_wt, + (S32) mog->ini_var); + break; + } + + + case DVP_KN_VLIB_EWR_MEAN_S16: + { + DVP_EMean_t *pM = dvp_knode_to(&pSubNodes[n], DVP_EMean_t); + DVP_U32 y; + for (y = 0; y < pM->data.height; y++) + { + VLIB_updateEWRMeanS16((S16 *)&pM->mean.pData[0][y * pM->mean.y_stride], + &pM->data.pData[0][y * pM->data.y_stride], + (U32 *)&pM->mask.pData[0][y * pM->mask.y_stride], + saturate_s16(pM->weight), + pM->data.width); + } + break; + } + case DVP_KN_VLIB_EWR_VAR_S16: + { + DVP_EMean_t *pM = dvp_knode_to(&pSubNodes[n], DVP_EMean_t); + DVP_U32 y; + for (y = 0; y < pM->data.height; y++) + { + VLIB_updateEWRVarianceS16((S16 *)&pM->var.pData[0][y * pM->var.y_stride], + (S16 *)&pM->mean.pData[0][y * pM->mean.y_stride], + &pM->data.pData[0][y * pM->data.y_stride], + (U32 *)&pM->mask.pData[0][y * pM->mask.y_stride], + saturate_s16(pM->weight), + pM->data.width); + } + break; + } + case DVP_KN_VLIB_EWR_MEAN_S32: + { + DVP_EMean_t *pM = dvp_knode_to(&pSubNodes[n], DVP_EMean_t); + DVP_U32 y; + for (y = 0; y < pM->data.height; y++) + { + VLIB_updateEWRMeanS32((S32 *)&pM->mean.pData[0][y * pM->mean.y_stride], + &pM->data.pData[0][y * pM->data.y_stride], + (U32 *)&pM->mask.pData[0][y * pM->mask.y_stride], + pM->weight, + pM->data.width); + }break; + } + case DVP_KN_VLIB_EWR_VAR_S32: + { + DVP_EMean_t *pM = dvp_knode_to(&pSubNodes[n], DVP_EMean_t); + DVP_U32 y; + for (y = 0; y < pM->data.height; y++) + { + VLIB_updateEWRVarianceS32((S32 *)&pM->var.pData[0][y * pM->var.y_stride], + (S32 *)&pM->mean.pData[0][y * pM->mean.y_stride], + &pM->data.pData[0][y * pM->data.y_stride], + (U32 *)&pM->mask.pData[0][y * pM->mask.y_stride], + pM->weight, + pM->data.width); + } + break; + } + case DVP_KN_VLIB_UWR_MEAN_S16: + { + DVP_UMean_t *pM = dvp_knode_to(&pSubNodes[n], DVP_UMean_t); + DVP_U32 y; + for (y = 0; y < pM->new_data.height; y++) + { + VLIB_updateUWRMeanS16((S16 *)&pM->new_mean.pData[0][y * pM->new_mean.y_stride], + (S16 *)&pM->old_mean.pData[0][y * pM->old_mean.y_stride], + &pM->new_data.pData[0][y * pM->new_data.y_stride], + &pM->old_data.pData[0][y * pM->old_data.y_stride], + (U32 *)&pM->new_mask.pData[0][y * pM->new_mask.y_stride], + (U32 *)&pM->old_mask.pData[0][y * pM->old_mask.y_stride], + pM->new_data.width, + pM->bufferLength); + } + break; + } + case DVP_KN_VLIB_UWR_VAR_S16: + { + DVP_UMean_t *pM = dvp_knode_to(&pSubNodes[n], DVP_UMean_t); + DVP_U32 y; + for (y = 0; y < pM->new_data.height; y++) + { + VLIB_updateUWRVarianceS16((S16 *)&pM->new_var.pData[0][y * pM->new_var.y_stride], + (S16 *)&pM->old_var.pData[0][y * pM->old_var.y_stride], + (S16 *)&pM->new_mean.pData[0][y * pM->new_mean.y_stride], + (S16 *)&pM->old_mean.pData[0][y * pM->old_mean.y_stride], + &pM->new_data.pData[0][y * pM->new_data.y_stride], + (U32 *)&pM->new_mask.pData[0][y * pM->new_mask.y_stride], + (U32 *)&pM->old_mask.pData[0][y * pM->old_mask.y_stride], + pM->new_data.width, + pM->bufferLength); + } + break; + } + case DVP_KN_VLIB_SUB_BACK_S16: + { + DVP_SubBackground_t *pSB = dvp_knode_to(&pSubNodes[n], DVP_SubBackground_t); + + /*number of output 32 packed values will be (frameSize/32) */ + VLIB_subtractBackgroundS16((U32 *)pSB->output32packed.pData[0], + (DVP_U08 *)pSB->newestData.pData[0], + (DVP_S16 *)pSB->currentMean.pData[0], + (DVP_S16 *)pSB->currentVar.pData[0], + (short)pSB->thresholdGlobal, + (short)pSB->thresholdFactor, + (U32)(pSB->newestData.width * pSB->newestData.height ) ); + break; + } + case DVP_KN_VLIB_SUB_BACK_S32: + { + DVP_SubBackground_t *pSB = dvp_knode_to(&pSubNodes[n], DVP_SubBackground_t); + + VLIB_subtractBackgroundS32((U32 *)pSB->output32packed.pData[0], + (DVP_U08 *)pSB->newestData.pData[0], + (S32 *)pSB->currentMean.pData[0], + (S32 *)pSB->currentVar.pData[0], + (S32)pSB->thresholdGlobal, + (S32)pSB->thresholdFactor, + (U32)(pSB->newestData.width * pSB->newestData.height ) ); + break; + } + case DVP_KN_VLIB_EXTRACT_BACK_8_16: + { + DVP_Transform_t *pEb = (DVP_Transform_t *)dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + DVP_U32 y = 0; + DVP_U08 *pBack = pEb->input.pData[0]; + DVP_U08 *Out = pEb->output.pData[0]; + + for (y = 0; y < pEb->input.height; y++) + { + VLIB_extract8bitBackgroundS16((DVP_S16 *)&pBack[y * pEb->input.y_stride], + &Out[y * pEb->output.y_stride], + pEb->input.width); + } + break; + } + case DVP_KN_VLIB_PACK_MASK_32: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + DVP_U32 y; + for (y = 0; y < pT->input.height; y++) + { + VLIB_packMask32(&pT->input.pData[0][y * pT->input.y_stride], + (U32 *)&pT->output.pData[0][y * pT->output.y_stride], + pT->input.width); + } + break; + } + case DVP_KN_VLIB_UNPACK_MASK_32: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + DVP_U32 y; + for (y = 0; y < pT->input.height; y++) + { + VLIB_unpackMask32((U32 *)&pT->input.pData[0][y * pT->input.y_stride], + &pT->output.pData[0][y * pT->output.y_stride], + pT->input.width); + } + break; + } + case DVP_KN_DILATE_CROSS: + case DVP_KN_DILATE_MASK: + case DVP_KN_DILATE_SQUARE: + case DVP_KN_ERODE_CROSS: + case DVP_KN_ERODE_MASK: + case DVP_KN_ERODE_SQUARE: + case DVP_KN_VLIB_DILATE_CROSS: + case DVP_KN_VLIB_DILATE_MASK: + case DVP_KN_VLIB_DILATE_SQUARE: + case DVP_KN_VLIB_ERODE_CROSS: + case DVP_KN_VLIB_ERODE_MASK: + case DVP_KN_VLIB_ERODE_SQUARE: + case DVP_KN_VLIB_ERODE_SINGLEPIXEL: + { + DVP_Morphology_t *pD = dvp_knode_to(&pSubNodes[n], DVP_Morphology_t); + DVP_U32 y, jv; + DVP_U32 *pPacked32in, *pPacked32out; + DVP_U08 *tmp; + DVP_U32 packed32Line; + size_t packed32Size; + + packed32Line = pD->input.width / 32; // How many 32bit words per line + packed32Size = pD->input.height * packed32Line * sizeof(DVP_U32); // How many byptes per image + +#if defined(ANDROID) + pPacked32in = (DVP_U32 *) memalign(64, packed32Size); + pPacked32out = (DVP_U32 *) memalign(64, packed32Size); +#elif defined(__QNX__) || defined(LINUX) + if (0 != posix_memalign((void *)&pPacked32in, 64, packed32Size)) + break; + if (0 != posix_memalign((void *)&pPacked32out, 64, packed32Size)) + break; +#else + pPacked32in = (DVP_U32 *)calloc(1, packed32Size); + pPacked32out = (DVP_U32 *)calloc(1, packed32Size); +#endif + tmp = pD->input.pData[0]; + for(jv=0; jvinput.height; jv++) + { + VLIB_packMask32(&tmp[jv*pD->input.y_stride], &pPacked32in[jv*packed32Line], pD->input.width); // Assuming 1 byte per input pixel + } +#if 0 + memcpy(pPacked32out, pPacked32in, packed32Size); // For testing the packing/unpacking functions +#else + switch(kernel) + { + case DVP_KN_DILATE_CROSS: + case DVP_KN_VLIB_DILATE_CROSS: + for (y = 0; y < (pD->input.height - 2); y++) + { + VLIB_dilate_bin_cross((U08 *)&pPacked32in[y * packed32Line], + (U08 *)&pPacked32out[y * packed32Line], + pD->input.width, + pD->input.width); + } + break; + case DVP_KN_DILATE_MASK: + case DVP_KN_VLIB_DILATE_MASK: + for (y = 0; y < (pD->input.height - 2); y++) + { + VLIB_dilate_bin_mask((U08 *)&pPacked32in[y * packed32Line], + (U08 *)&pPacked32out[y * packed32Line], + (S08 *)pD->mask.pData[0], + pD->input.width, + pD->input.width); + } + break; + case DVP_KN_DILATE_SQUARE: + case DVP_KN_VLIB_DILATE_SQUARE: + for (y = 0; y < (pD->input.height - 2); y++) + { + VLIB_dilate_bin_square((U08 *)&pPacked32in[y * packed32Line], + (U08 *)&pPacked32out[y * packed32Line], + pD->input.width, + pD->input.width); + } + break; + case DVP_KN_ERODE_CROSS: + case DVP_KN_VLIB_ERODE_CROSS: + for (y = 0; y < (pD->input.height - 2); y++) + { + VLIB_erode_bin_cross((U08 *)&pPacked32in[y * packed32Line], + (U08 *)&pPacked32out[y * packed32Line], + pD->input.width, + pD->input.width); + } + break; + case DVP_KN_ERODE_MASK: + case DVP_KN_VLIB_ERODE_MASK: + for (y = 0; y < (pD->input.height - 2); y++) + { + VLIB_erode_bin_mask((U08 *)&pPacked32in[y * packed32Line], + (U08 *)&pPacked32out[y * packed32Line], + (S08 *)pD->mask.pData[0], + pD->input.width, + pD->input.width); + } + break; + case DVP_KN_ERODE_SQUARE: + case DVP_KN_VLIB_ERODE_SQUARE: + for (y = 0; y < (pD->input.height - 2); y++) + { + VLIB_erode_bin_square((U08 *)&pPacked32in[y * packed32Line], + (U08 *)&pPacked32out[y * packed32Line], + pD->input.width, + pD->input.width); + } + break; + case DVP_KN_VLIB_ERODE_SINGLEPIXEL: + for (y = 0; y < (pD->input.height - 2); y++) + { + VLIB_erode_bin_singlePixel((U08 *)&pPacked32in[y * packed32Line], + (U08 *)&pPacked32out[y * packed32Line], + pD->input.width, + pD->input.width); + } + break; + default: + break; + } +#endif + tmp = pD->output.pData[0]; + for(jv=0; jvoutput.height; jv++) + { + VLIB_unpackMask32(&pPacked32out[jv*packed32Line], &tmp[jv*pD->output.y_stride], pD->output.width); // Assuming 1 byte per input pixel + } + free(pPacked32in); + free(pPacked32out); + break; + } + case DVP_KN_VLIB_CCL: + { + DVP_CCL_t *pC = dvp_knode_to(&pSubNodes[n], DVP_CCL_t); + DVP_S32 scratchSize; + VLIB_STATUS status; + DVP_S32 numCCs; + DVP_PTR pScratch; + DVP_U32 *pPacked32; + DVP_U32 packed32Line; + DVP_U32 packed32Size; + VLIB_CCHandle * handle; + DVP_U32 jv; + DVP_U08 *tmp = NULL; + VLIB_calcConnectedComponentsMaxBufferSize(pC->input.width, + pC->input.height, + pC->minBlobAreaInPixels, + &scratchSize); + + /* Set-up Memory Buffers */ + handle = (VLIB_CCHandle *) malloc(VLIB_GetSizeOfCCHandle()); +#if defined(ANDROID) + pScratch = (DVP_PTR) memalign(64, scratchSize); +#elif defined(__QNX__) || defined(LINUX) + if (0 != posix_memalign((void *)&pScratch, 64, scratchSize)) + break; +#else + pScratch = (DVP_PTR)calloc(1, scratchSize); +#endif + status = VLIB_initConnectedComponentsList(handle, pScratch, scratchSize); + if (status != VLIB_NO_ERROR) + { + DVP_PRINT(DVP_ZONE_ERROR, "VLIB_initConnectedComponentsList() failed with error code %d\n", status); + pSubNodes[n].header.error = DVP_ERROR_INVALID_PARAMETER; + processed--; + break; + } + + /* Pack data */ + packed32Line = pC->input.width / 32; // How many 32bit words per line + packed32Size = pC->input.height * packed32Line * sizeof(DVP_U32); // How many byptes per image +#if defined(ANDROID) + pPacked32 = (DVP_U32 *) memalign(64, packed32Size); +#elif defined(__QNX__) || defined(LINUX) + if (0 != posix_memalign((void *)&pPacked32, 64, packed32Size)) + break; +#else + pPacked32 = (DVP_U32 *) calloc(1, packed32Size); +#endif + tmp = pC->input.pData[0]; + for(jv=0; jvinput.height; jv++) + { + VLIB_packMask32(&tmp[jv*pC->input.y_stride], &pPacked32[jv*packed32Line], pC->input.width); // Assuming 1 byte per input pixel + } + + status = VLIB_createConnectedComponentsList(handle, + pC->input.width, + pC->input.height, + (U32*)(&pPacked32[0]), + pC->minBlobAreaInPixels, + pC->connected8Flag); + + if (status == VLIB_WARNING_LOW_MEMORY) + { + DVP_PRINT(DVP_ZONE_KGM, "\nConnected Components low memory warning!!! Buffer within 1kbyte of allocation!!!\n"); + } + else if (status != VLIB_NO_ERROR) + { + DVP_PRINT(DVP_ZONE_ERROR, "\nCreation of Connected Components failed!!!\n"); + pSubNodes[n].header.error = DVP_ERROR_INVALID_PARAMETER; + processed--; + break; + } + + /* Retreive number of connected components */ + VLIB_getNumCCs(handle, &numCCs); + pC->numCCs = numCCs; + + /* Create Connected component Output Map */ + memset(pC->output.pData[0], 0, pC->input.width*pC->input.height); // Clearing output since function only writes to blobs. + status = VLIB_createCCMap8Bit(handle, + pC->output.pData[0], + pC->input.width, + pC->input.height); + + if (status != 0) + { + DVP_PRINT(DVP_ZONE_ERROR, "Creation of 8-bit Connected Components Map failed!!!\n"); + pSubNodes[n].header.error = DVP_ERROR_NO_MEMORY; + processed--; + break; + } + free(pPacked32); + free(pScratch); + free(handle); + break; + } + case DVP_KN_CANNY_2D_GRADIENT: + case DVP_KN_VLIB_CANNY_2D_GRADIENT: + { + DVP_Canny2dGradient_t *pG = dvp_knode_to(&pSubNodes[n], DVP_Canny2dGradient_t); + VLIB_xyGradientsAndMagnitude(pG->input.pData[0], + (S16 *)pG->outGradX.pData[0], + (S16 *)pG->outGradY.pData[0], + (S16 *)pG->outMag.pData[0], + (U16)pG->input.width, + (U16)pG->input.height); + break; + } + case DVP_KN_CANNY_NONMAX_SUPPRESSION: // Assumes 1D buffer + case DVP_KN_VLIB_CANNY_NONMAX_SUPPRESSION: + { + DVP_CannyNonMaxSuppression_t *cnonmax = dvp_knode_to(&pSubNodes[n], DVP_CannyNonMaxSuppression_t); + + VLIB_nonMaximumSuppressionCanny((S16 *)cnonmax->inMag.pData[0], + (S16 *)cnonmax->inGradX.pData[0], + (S16 *)cnonmax->inGradY.pData[0], + cnonmax->output.pData[0], + (U16)cnonmax->inMag.width, + (U16)cnonmax->inMag.y_stride/2, + (U16)cnonmax->inMag.height); + break; + } + case DVP_KN_CANNY_HYST_THRESHHOLD: + case DVP_KN_VLIB_CANNY_HYST_THRESHHOLD: + { + DVP_CannyHystThresholding_t *dthresh = dvp_knode_to(&pSubNodes[n], DVP_CannyHystThresholding_t); + VLIB_doublethresholding((DVP_S16 *)dthresh->inMag.pData[0], + dthresh->inEdgeMap.pData[0], + (DVP_U32 *)dthresh->output.pData[0], + (DVP_S32 *)&dthresh->numEdges, + (DVP_U16)dthresh->inMag.width, + (DVP_U16)(dthresh->inMag.y_stride/dthresh->inMag.x_stride), + (DVP_U16)dthresh->inMag.height, + dthresh->loThresh, + dthresh->hiThresh, + dthresh->numEdges); + DVP_PRINT(DVP_ZONE_KGM, "There were %u strong edges found!\n", dthresh->numEdges); + break; + } + case DVP_KN_VLIB_IMAGE_PYRAMID_8: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + VLIB_imagePyramid8(pT->input.pData[0], + (U16)pT->input.width, + (U16)pT->input.height, + pT->output.pData[0]); + break; + } + case DVP_KN_VLIB_IMAGE_PYRAMID_16: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + VLIB_imagePyramid16((U16 *)pT->input.pData[0], + (U16)pT->input.width, + (U16)pT->input.height, + (U16 *)pT->output.pData[0]); + break; + } + case DVP_KN_VLIB_GAUSSIAN_5x5_PYRAMID_8: + { + DVP_Gradient_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Gradient_t); + + for(i=0; iinput.height/2; i+=1) + { + VLIB_gauss5x5PyramidKernel_8(&pT->input.pData[0][2*i*pT->input.y_stride], + (DVP_U16 *)pT->scratch.pData[0], + pT->input.width, + pT->input.width, + 1, + &pT->output.pData[0][i*pT->output.y_stride]); + } + break; + } + case DVP_KN_VLIB_GAUSSIAN_5x5_PYRAMID_16: + { + DVP_Gradient_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Gradient_t); + for(i=0; iinput.height/2; i+=1) + { + VLIB_gauss5x5PyramidKernel_16((DVP_U16 *)&pT->input.pData[0][2*i*pT->input.y_stride], + (DVP_U32 *)pT->scratch.pData[0], + pT->input.width, + pT->input.width, + 1, + (DVP_U16 *)&pT->output.pData[0][i*pT->output.y_stride]); + } + break; + } + case DVP_KN_VLIB_GRADIENT_H5x5_PYRAMID_8: + { + DVP_Gradient_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Gradient_t); + VLIB_gradientH5x5PyramidKernel_8(pT->input.pData[0], + (S16 *)pT->scratch.pData[0], + pT->input.width, + pT->input.y_stride/pT->input.x_stride, + pT->input.height, + pT->output.pData[0]); + break; + } + case DVP_KN_VLIB_GRADIENT_V5x5_PYRAMID_8: + { + DVP_Gradient_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Gradient_t); + VLIB_gradientV5x5PyramidKernel_8(pT->input.pData[0], + (S16 *)pT->scratch.pData[0], + pT->input.width, + pT->input.y_stride/pT->input.x_stride, + pT->input.height, + pT->output.pData[0]); + break; + } + case DVP_KN_VLIB_HARRIS_SCORE_7x7: + { + DVP_HarrisDSP_t *pH = dvp_knode_to(&pSubNodes[n], DVP_HarrisDSP_t); + VLIB_harrisScore_7x7((DVP_S16 *)pH->inGradX.pData[0], + (DVP_S16 *)pH->inGradY.pData[0], + pH->inGradX.width, + pH->inGradX.height, + (DVP_S16 *)pH->harrisScore.pData[0], + pH->k, + pH->scratch.pData); + break; + } + case DVP_KN_VLIB_HARRIS_SCORE_7x7_U32: + { + DVP_HarrisDSP_t *pH = dvp_knode_to(&pSubNodes[n], DVP_HarrisDSP_t); + VLIB_harrisScore_U32_7x7((DVP_S16 *)pH->inGradX.pData[0], + (DVP_S16 *)pH->inGradY.pData[0], + pH->inGradX.width, + pH->inGradX.height, + (DVP_U32 *)pH->harrisScore.pData[0], + pH->k, + pH->scratch.pData); + break; + } + case DVP_KN_VLIB_TRACK_FEATURES_LUCAS_7x7: + { + DVP_TrackFeatures_t *pTF = dvp_knode_to(&pSubNodes[n], DVP_TrackFeatures_t); + VLIB_trackFeaturesLucasKanade_7x7(pTF->im1.pData[0], + pTF->im2.pData[0], + (DVP_S16 *)pTF->gradx.pData[0], + (DVP_S16 *)pTF->grady.pData[0], + pTF->im1.width, + pTF->im1.height, + pTF->nfeatures, + (DVP_S16 *)pTF->x.pData, + (DVP_S16 *)pTF->y.pData, + (DVP_S16 *)pTF->outx.pData, + (DVP_S16 *)pTF->outy.pData, + pTF->max_iters, + pTF->scratch.pData); + break; + } + case DVP_KN_IIR_HORZ: + case DVP_KN_VLIB_IIR_HORZ: + { + DVP_IIR_t *pT = dvp_knode_to(&pSubNodes[n], DVP_IIR_t); + DVP_U32 y; + if((int)pT->input.width == pT->input.y_stride) + { + VLIB_recursiveFilterHoriz1stOrder(pT->output.pData[0], + pT->input.pData[0], + pT->input.width, + pT->input.height, + pT->weight, + pT->bounds[0].pData, + pT->bounds[1].pData, + pT->scratch.pData[0]); + }else + { + DVP_U08 *tmpBuf = (DVP_U08 *)malloc(pT->input.width * 8); + DVP_U32 i; + for(y=0; yinput.height; y+=8) + { + for(i=0; i<8; i++) + memcpy(&tmpBuf[i*pT->input.width], &pT->input.pData[0][(y+i)*pT->input.y_stride], pT->input.width); + + VLIB_recursiveFilterHoriz1stOrder(&pT->output.pData[0][y*pT->output.y_stride], + tmpBuf, + pT->input.width, + 8, + pT->weight, + pT->bounds[0].pData, + pT->bounds[1].pData, + pT->scratch.pData[0]); + } + free(tmpBuf); + } + break; + } + case DVP_KN_VLIB_IIR_HORZ_16: + { + DVP_IIR_t *pT = dvp_knode_to(&pSubNodes[n], DVP_IIR_t); + DVP_U32 y; + if((int)(2*pT->input.width) == pT->input.y_stride) + { + VLIB_recursiveFilterHoriz1stOrderS16((S16 *)pT->output.pData[0], + (S16 *)pT->input.pData[0], + pT->input.width, + pT->input.height, + pT->weight, + (S16 *)pT->bounds[0].pData, + (S16 *)pT->bounds[1].pData, + (S16 *)pT->scratch.pData[0]); + }else + { + DVP_U08 *tmpBuf = (DVP_U08 *)malloc(pT->input.width*8*sizeof(S16)); + DVP_U32 i; + for(y=0; yinput.height; y+=8) + { + for(i=0; i<8; i++) + memcpy(&tmpBuf[i*pT->input.width*sizeof(S16)], &pT->input.pData[0][(y+i)*pT->input.y_stride], pT->input.width*sizeof(S16)); + + VLIB_recursiveFilterHoriz1stOrderS16((S16 *)&pT->output.pData[0][y*pT->output.y_stride], + (S16 *)tmpBuf, + pT->input.width, + 8, + pT->weight, + (S16 *)pT->bounds[0].pData, + (S16 *)pT->bounds[1].pData, + (S16 *)pT->scratch.pData[0]); + } + free(tmpBuf); + } + break; + } + case DVP_KN_IIR_VERT: + case DVP_KN_VLIB_IIR_VERT: + { + DVP_IIR_t *pT = dvp_knode_to(&pSubNodes[n], DVP_IIR_t); + if((int)pT->input.width == pT->input.y_stride) + { + VLIB_recursiveFilterVert1stOrder(pT->output.pData[0], + pT->input.pData[0], + pT->input.width, + pT->input.height, + pT->weight, + pT->bounds[0].pData, + pT->bounds[1].pData, + pT->scratch.pData[0]); + }else + { + DVP_U08 *tmpBufIn = (DVP_U08 *)malloc(pT->input.height * pT->input.width); + DVP_U32 i; + for(i=0; iinput.height; i++) + memcpy(&tmpBufIn[i*pT->input.width], pT->input.pData[0] + (i*pT->input.y_stride), pT->input.width); + + VLIB_recursiveFilterVert1stOrder(pT->output.pData[0], + tmpBufIn, + pT->input.width, + pT->input.height, + pT->weight, + pT->bounds[0].pData, + pT->bounds[1].pData, + pT->scratch.pData[0]); + free(tmpBufIn); + } + break; + } + case DVP_KN_VLIB_IIR_VERT_16: + { + DVP_IIR_t *pT = dvp_knode_to(&pSubNodes[n], DVP_IIR_t); + if((int)(2*pT->input.width) == pT->input.y_stride) + { + VLIB_recursiveFilterVert1stOrderS16((S16 *)pT->output.pData[0], + (S16 *)pT->input.pData[0], + pT->input.width, + pT->input.height, + pT->weight, + (S16 *)pT->bounds[0].pData, + (S16 *)pT->bounds[1].pData, + (S16 *)pT->scratch.pData[0]); + }else + { + DVP_U08 *tmpBufIn = (DVP_U08 *)malloc(pT->input.height * pT->input.width * sizeof(DVP_U16)); + DVP_U32 i; + for(i=0; iinput.height; i++) + memcpy(&tmpBufIn[i*pT->input.width*sizeof(DVP_U16)], pT->input.pData[0] + (i*pT->input.y_stride), pT->input.width* sizeof(DVP_U16)); + + VLIB_recursiveFilterVert1stOrderS16((S16 *)pT->output.pData[0], + (S16 *)tmpBufIn, + pT->input.width, + pT->input.height, + pT->weight, + (S16 *)pT->bounds[0].pData, + (S16 *)pT->bounds[1].pData, + (S16 *)pT->scratch.pData[0]); + free(tmpBufIn); + } + break; + } + case DVP_KN_INTEGRAL_IMAGE_8: + case DVP_KN_VLIB_INTEGRAL_IMAGE_8: + { + // param check (U32 width of output buffer). + // no stride + + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + for(i=0; iinput.height-1; i++) + { + VLIB_integralImage8(&pT->input.pData[0][i*pT->input.y_stride], + (U16)pT->input.width, + 1, + (U32 *)&pT->output.pData[0][(pT->output.height-1)*pT->output.y_stride], + (U32 *)&pT->output.pData[0][i*pT->output.y_stride]); + } + break; + } + case DVP_KN_VLIB_INTEGRAL_IMAGE_16: + { + // param check (U32 width of output buffer). + // no stride + + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + VLIB_integralImage16((U16 *)pT->input.pData[0], + pT->input.width, + pT->input.height, + (U32 *)&pT->output.pData[0][(pT->output.height-1)*pT->output.y_stride], + (U32 *)pT->output.pData[0]); + break; + } + case DVP_KN_VLIB_HOUGH_LINE_FROM_LIST: + { + DVP_HoughLine_t *pHl = dvp_knode_to(&pSubNodes[n], DVP_HoughLine_t); + + VLIB_houghLineFromList((DVP_U16 *)pHl->pEdgeMapList.pData, + (DVP_U16 *)pHl->pOutHoughSpace.pData[0], + (DVP_U16)pHl->outBlkWidth, + (DVP_U16)pHl->outBlkHeight, + (U32)pHl->listSize, + (DVP_U16)pHl->thetaRange, + (DVP_U16)pHl->rhoMaxLength, + (DVP_S16 *)pHl->pSIN.pData, + (DVP_S16 *)pHl->pCOS.pData, + (DVP_U16 *)pHl->ping.pData, + (DVP_U16 *)pHl->pong.pData, + (DVP_U16 *)pHl->pang.pData, + (DVP_U16 *)pHl->peng.pData); + break; + } + case DVP_KN_VLIB_HYST_THRESHOLD: + { + DVP_CannyHystThresholding_t *dthresh = dvp_knode_to(&pSubNodes[n], DVP_CannyHystThresholding_t); + + VLIB_hysteresisThresholding((DVP_S16 *)dthresh->inMag.pData[0], + (DVP_U08 *)dthresh->inEdgeMap.pData[0], + (DVP_U08 *)dthresh->output.pData[0], //used as SCRATCH + (DVP_U16)dthresh->inMag.height, + (DVP_U16)dthresh->inMag.width, + dthresh->loThresh, + dthresh->hiThresh); + break; + } + case DVP_KN_NONMAXSUPPRESS_3x3_S16: + case DVP_KN_VLIB_NONMAXSUPPRESS_3x3_S16: + { + DVP_Threshold_t *pM = dvp_knode_to(&pSubNodes[n], DVP_Threshold_t); + VLIB_nonMaxSuppress_3x3_S16((S16 *)pM->input.pData[0], + (U16) pM->input.width, + (U16)pM->input.height, + pM->thresh, + (U08 *)(pM->output.pData[0]+pM->output.width*2)); // In order to match simcop, output starts masksize-1 lines in + break; + } + case DVP_KN_NONMAXSUPPRESS_5x5_S16: + case DVP_KN_VLIB_NONMAXSUPPRESS_5x5_S16: + { + DVP_Threshold_t *pM = dvp_knode_to(&pSubNodes[n], DVP_Threshold_t); + VLIB_nonMaxSuppress_5x5_S16((S16 *)pM->input.pData[0], + (U16)pM->input.width, + (U16)pM->input.height, + pM->thresh, + (U08 *)(pM->output.pData[0]+pM->output.width*4)); // In order to match simcop, output starts masksize-1 lines in + break; + } + case DVP_KN_NONMAXSUPPRESS_7x7_S16: + case DVP_KN_VLIB_NONMAXSUPPRESS_7x7_S16: + { + DVP_Threshold_t *pM = dvp_knode_to(&pSubNodes[n], DVP_Threshold_t); + VLIB_nonMaxSuppress_7x7_S16((S16 *)pM->input.pData[0], + (U16)pM->input.width, + (U16)pM->input.height, + pM->thresh, + (U08 *)(pM->output.pData[0]+pM->output.width*6)); // In order to match simcop, output starts masksize-1 lines in + break; + } + case DVP_KN_VLIB_NORMALFLOW_16: + { + DVP_NormalFlow_t *pF = dvp_knode_to(&pSubNodes[n], DVP_NormalFlow_t); + VLIB_normalFlow_16((S16 *)pF->input.pData[0], + (S16 *)pF->mag.pData[0], + (S16 *)pF->x.pData[0], + (S16 *)pF->y.pData[0], + (S16 *)pF->lut.pData[0], + pF->thresh, + pF->input.width * pF->input.height, + (S16 *)pF->u.pData[0], + (S16 *)pF->v.pData[0]); + break; + } + /// @todo case DVP_KN_VLIB_KALMAN_2x4: + /// @todo case DVP_KN_VLIB_KALMAN_4x6: + case DVP_KN_VLIB_NEDLER_MEAD_SIMPLEX_16: + { + DVP_Simplex_t *pSmx = dvp_knode_to(&pSubNodes[n], DVP_Simplex_t); + void *addtlArgsPtr; + addtlArgsPtr = (void*)&(pSmx->addtlArgs); + + VLIB_simplex(rosenbrock32, + (DVP_S16 *)pSmx->start.pData, + (DVP_S16 *)pSmx->step.pData, + pSmx->N_val, + pSmx->N_INV, + pSmx->MaxIteration, + pSmx->EPSILON, + (DVP_S16 *)pSmx->intBuf[0].pData, + (DVP_S32 *)pSmx->intBuf[1].pData, + (DVP_S16 *)pSmx->intBuf[2].pData, + (DVP_S16 *)pSmx->intBuf[3].pData, + (DVP_S16 *)pSmx->intBuf[4].pData, + (DVP_S16 *)pSmx->intBuf[5].pData, + addtlArgsPtr, + (DVP_S16 *)pSmx->stop.pData, + &(pSmx->minValue)); + break; + } + case DVP_KN_VLIB_NEDLER_MEAD_SIMPLEX_3D: + { + DVP_Simplex_t *pSmx = dvp_knode_to(&pSubNodes[n], DVP_Simplex_t); + void *addtlArgsPtr; + + addtlArgsPtr = (void*)&(pSmx->addtlArgs); + + VLIB_simplex_3D(rosenbrock32, + (DVP_S16 *)pSmx->start.pData, + (DVP_S16 *)pSmx->step.pData, + pSmx->MaxIteration, + pSmx->EPSILON, + (DVP_S16 *)pSmx->intBuf[0].pData, + (DVP_S32 *)pSmx->intBuf[1].pData, + (DVP_S16 *)pSmx->intBuf[2].pData, + (DVP_S16 *)pSmx->intBuf[3].pData, + (DVP_S16 *)pSmx->intBuf[4].pData, + (DVP_S16 *)pSmx->intBuf[5].pData, + addtlArgsPtr, + (DVP_S16 *)pSmx->stop.pData, + &(pSmx->minValue)); + break; + } + /// @todo case DVP_KN_VLIB_LEGENDRE_MOMENTS: + case DVP_KN_VLIB_INIT_HISTOGRAM_8: + { + DVP_Histogram_t *pH = dvp_knode_to(&pSubNodes[n], DVP_Histogram_t); + VLIB_histogram_1D_Init_U8(pH->edges.pData, + pH->numBins, + pH->histArray.pData); + break; + } + case DVP_KN_VLIB_HISTOGRAM_8: + { + DVP_Histogram_t *pH = dvp_knode_to(&pSubNodes[n], DVP_Histogram_t); + + if(pSubNodes[n].header.resv[0] == 0) + { + VLIB_histogram_1D_Init_U8(pH->edges.pData, + pH->numBins, + pH->histArray.pData); + pSubNodes[n].header.resv[0] = 1; + } + if(pH->clearFlag) + { + memset(pH->h[0].pData, 0, pH->numBins*2); + memset(pH->h[1].pData, 0, pH->numBins*2); + memset(pH->h[2].pData, 0, pH->numBins*2); + memset(pH->hOut.pData, 0, pH->numBins*2); + } + VLIB_histogram_1D_U8(pH->input.pData[0], + pH->input.numBytes, + pH->numBins, + pH->binWeight, + pH->histArray.pData, + (U16 *)pH->h[0].pData, + (U16 *)pH->h[1].pData, + (U16 *)pH->h[2].pData, + (U16 *)pH->hOut.pData); + break; + } + case DVP_KN_VLIB_WEIGHTED_HISTOGRAM_8: + { + DVP_Histogram_t *pH = dvp_knode_to(&pSubNodes[n], DVP_Histogram_t); + + if(pSubNodes[n].header.resv[0] == 0) + { + VLIB_histogram_1D_Init_U8(pH->edges.pData, + pH->numBins, + pH->histArray.pData); + pSubNodes[n].header.resv[0] = 1; + } + if(pH->clearFlag) + { + memset(pH->h[0].pData, 0, pH->numBins*2); + memset(pH->h[1].pData, 0, pH->numBins*2); + memset(pH->h[2].pData, 0, pH->numBins*2); + memset(pH->hOut.pData, 0, pH->numBins*2); + } + VLIB_weightedHistogram_1D_U8(pH->input.pData[0], + pH->input.numBytes, + pH->numBins, + (U16 *)pH->binWeights.pData, + pH->histArray.pData, + (U16 *)pH->h[0].pData, + (U16 *)pH->h[1].pData, + (U16 *)pH->h[2].pData, + (U16 *)pH->hOut.pData); + break; + } + case DVP_KN_VLIB_INIT_HISTOGRAM_16: + { + DVP_Histogram_t *pH = dvp_knode_to(&pSubNodes[n], DVP_Histogram_t); + VLIB_histogram_1D_Init_U16((U16 *)pH->edges.pData, + pH->numBins, + (U16 *)pH->histArray.pData); + break; + } + case DVP_KN_VLIB_HISTOGRAM_16: + { + DVP_Histogram_t *pH = dvp_knode_to(&pSubNodes[n], DVP_Histogram_t); + + if(pSubNodes[n].header.resv[0] == 0) + { + VLIB_histogram_1D_Init_U16((U16 *)pH->edges.pData, + pH->numBins, + (U16 *) pH->histArray.pData); + pSubNodes[n].header.resv[0] = 1; + } + if(pH->clearFlag) + { + memset(pH->h[0].pData, 0, pH->numBins*2); + memset(pH->hOut.pData, 0, pH->numBins*2); + } + VLIB_histogram_1D_U16((U16 *)pH->input.pData[0], + pH->input.numBytes/2, + pH->numBins, + pH->binWeight, + (U16 *)pH->histArray.pData, + (U16 *)pH->h[0].pData, + (U16 *)pH->hOut.pData); + break; + } + case DVP_KN_VLIB_WEIGHTED_HISTOGRAM_16: + { + DVP_Histogram_t *pH = dvp_knode_to(&pSubNodes[n], DVP_Histogram_t); + + if(pSubNodes[n].header.resv[0] == 0) + { + VLIB_histogram_1D_Init_U16((U16 *)pH->edges.pData, + pH->numBins, + (U16 *) pH->histArray.pData); + pSubNodes[n].header.resv[0] = 1; + } + if(pH->clearFlag) + { + memset(pH->h[0].pData, 0, pH->numBins*2); + memset(pH->hOut.pData, 0, pH->numBins*2); + } + VLIB_weightedHistogram_1D_U16((U16 *)pH->input.pData[0], + pH->input.numBytes/2, + pH->numBins, + (U16 *)pH->binWeights.pData, + (U16 *)pH->histArray.pData, + (U16 *)pH->h[0].pData, + (U16 *)pH->hOut.pData); + break; + } + case DVP_KN_VLIB_HISTOGRAM_ND_16: + { + DVP_Histogram_t *pH = dvp_knode_to(&pSubNodes[n], DVP_Histogram_t); + DVP_U32 totBins = 1; + + for(i=0; idimX; i++) + totBins *= pH->numBinsArray.pData[i]; + if(pH->clearFlag) + { + memset(pH->hOut.pData, 0, totBins*2); + } + VLIB_histogram_nD_U16((DVP_U16 *)pH->input.pData[0], + (pH->input.numBytes/2)/pH->dimX, + pH->dimX, + pH->binWeight, + (DVP_U16 *)pH->numBinsArray.pData, + (DVP_U16 *)pH->h[0].pData, + (DVP_U16 *)pH->h[1].pData, + (DVP_U16 *)pH->h[2].pData, + (DVP_U16 *)pH->hOut.pData); + break; + } + case DVP_KN_VLIB_NONMAXSUPPRESS_U32: + { + DVP_Nonmax_NxN_t *nonmax32 = dvp_knode_to(&pSubNodes[n], DVP_Nonmax_NxN_t); + VLIB_nonMaxSuppress_U32((DVP_U32 *)nonmax32->input.pData[0], + (DVP_S32)nonmax32->input.width, + (DVP_S32)nonmax32->input.height, + (DVP_S32)nonmax32->p, + (DVP_U32)nonmax32->threshold, + (DVP_U32 *)nonmax32->scratch.pData, + (DVP_S16 *)nonmax32->pixIndex.pData); + break; + } + +#if 0 // @todo Must test and enable these features + case DVP_KN_VLIB_HISTOGRAM_ND_16: + { + // @todo Must support more than 1 dimension! + DVP_Histogram_t *pH = dvp_knode_to(&pSubNodes[n], DVP_Histogram_t); + VLIB_weightedHistogram_nD_U16((U16 *)pH->input.pData[0], + pH->input.numBytes, + 1, + pH->numBins, + (U16 *)pH->binWeights.pData, + (U16 *)pH->histArray.pData, + (U16 *)pH->h[1].pData, + (U16 *)pH->h[2].pData, + (U16 *)pH->h[3].pData, + (U16 *)pH->h[0].pData); + break; + } +#endif + case DVP_KN_VLIB_BHATTACHAYA_DISTANCE: + { + DVP_Distance_t *pD = dvp_knode_to(&pSubNodes[n], DVP_Distance_t); + DVP_U08* inX = pD->X.pData[0]; + DVP_U08* inY = pD->Y.pData[0]; + + DVP_U32 y = 0; + DVP_U32 distance = 0; + for (y = 0; y < pD->X.height; y++) + { + distance = 0; + VLIB_bhattacharyaDistance_U32( + (U16 *)&inX[y*pD->X.y_stride], + (U16 *)&inY[y*pD->Y.y_stride], + pD->X.width, + &distance); + pD->distance += distance; + } + + break; + } + case DVP_KN_VLIB_L1DISTANCE: + { + DVP_U32 y = 0; + DVP_U32 distance; + DVP_Distance_t *pD = dvp_knode_to(&pSubNodes[n], DVP_Distance_t); + pD->distance = 0; + for (y = 0; y < pD->X.height; y++) + { + distance = 0; + VLIB_L1DistanceS16((S16 *)&pD->X.pData[0][y*pD->X.y_stride], + (S16 *)&pD->Y.pData[0][y*pD->Y.y_stride], + pD->X.width, + &distance); + pD->distance += distance; + } + break; + } +#endif +#if defined(DVP_USE_ORB) + case DVP_KN_ORB: + { + DVP_PRINT(DVP_ZONE_KGM, "Executing Kernel \"ARM\" ORB"); + DVP_PRINT(DVP_ZONE_ALWAYS, "Running ORB on CPU"); + + CORBResult orbStatus = CORB_OK; + //Obtain the orbConfiguration data from Host side dvp struct + DVP_Orb_t * orbData = dvp_knode_to(&pSubNodes[n], DVP_Orb_t); + DVP_U32 imgWidth, imgHeight, x_stride, y_stride; + //local variables + CORBOutput orbOutput; + unsigned char * outImage[3]; //3 planes for output + + if (orbInit == 0) + { + orbInput = (CORBInput *)malloc(sizeof(CORBInput)*8); + if(orbInput == NULL) + { + DVP_PRINT(DVP_ZONE_ERROR, "ORB Input allocation failed. Exiting."); + break; + } + } + + imgWidth = orbData->inputImage.width; + imgHeight = orbData->inputImage.height; + orbInput->image = (unsigned char *)orbData->inputImage.pData[0]; + orbInput->harrisImage = (short *) orbData->harrisImage.pData[0]; + orbInput->integralImage = (unsigned int *) orbData->integralImage.pData[0]; + orbInput->orbPattern31 = (signed char *) orbData->orbPattern31.pData; + + orbOutput.features = (CORBFeature *) orbData->orbOutput.orbData.pData; + orbOutput.n_features = orbData->orbOutput.nfeatures; + //Copy plane pointers + outImage[0] = orbData->orbOutput.outImage.pData[0]; + outImage[1] = orbData->orbOutput.outImage.pData[1]; + outImage[2] = orbData->orbOutput.outImage.pData[2]; + x_stride = orbData->orbOutput.outImage.x_stride; + y_stride = orbData->orbOutput.outImage.y_stride; + const CORBParameters orbParams = getCORBParameters(imgWidth, imgHeight, 35, 20, FAST_9, BOOL_TRUE, 1311, orbOutput.n_features); + + if (orbInit == 0) + { + orbInit = 1; + + //Returns the amount of required scratch memory + int orbScratchSize = getRequiredScratchSize(&orbParams, BOOL_FALSE, BOOL_TRUE);//adding flag for computing harris, integral image + DVP_PRINT(DVP_ZONE_KGM, "ORB Scratch size = %d bytes", orbScratchSize); + orbMem = (DVP_U08 *)malloc(orbScratchSize); + DVP_PRINT(DVP_ZONE_KGM, "ORB Scratch allocated in external memory"); + + if(orbMem != NULL) + { + //Call ORB + orbStatus = cORB_init(&orbParams, orbInput); + } + else + { + DVP_PRINT(DVP_ZONE_KGM, "ORB Scratch allocation failed. Exiting."); + break; + } + } + + if ((orbMem != NULL) && (orbInput != NULL)) + { + orbInput->scratchBuffer = (char*) orbMem; + + if(orbStatus == CORB_OK) + { + orbStatus = cORB_computeORB(&orbParams, orbInput, &orbOutput); + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Error initializing ORB \n"); + } + + if(orbStatus == CORB_OK) + { + orbData->orbOutput.nfeatures = orbOutput.n_features; + orbStatus = cORB_showFeatures(&orbOutput, outImage, y_stride, x_stride, imgWidth, imgHeight); + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Error running ORB \n"); + } + + if(orbStatus != CORB_OK) + { + DVP_PRINT(DVP_ZONE_ERROR, "Error displaying ORB features \n"); + } + } + processed++; + break; + } +#endif//DVP_USE_ORB + +#if defined(DVP_USE_YUV) + //****************************************************** + // YUV ONLY CASES + //****************************************************** + + case DVP_KN_YUV_UYVY_HALF_SCALE: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + // the conversion call is based on the input to output formats + if (pT->input.color == FOURCC_UYVY && + pT->output.color == FOURCC_UYVY && + pT->input.width == (2*pT->output.width) && + pT->input.height == (2*pT->output.height)) + { + DVP_PrintImage(DVP_ZONE_KGM, &pT->input); + DVP_PrintImage(DVP_ZONE_KGM, &pT->output); + __uyvy_half_scale_image(pT->input.width, + pT->input.height, + pT->input.pData[0], + pT->input.y_stride, + pT->output.pData[0], + pT->output.y_stride); + } + else + processed -=1; + break; + } + case DVP_KN_YUV_UYVY_QTR_SCALE: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + // the conversion call is based on the input to output formats + if (pT->input.color == FOURCC_UYVY && + pT->output.color == FOURCC_UYVY && + pT->input.width == (4*pT->output.width) && + pT->input.height == (4*pT->output.height)) + { + DVP_PrintImage(DVP_ZONE_KGM, &pT->input); + DVP_PrintImage(DVP_ZONE_KGM, &pT->output); + __uyvy_qtr_scale_image(pT->input.width, + pT->input.height, + pT->input.pData[0], + pT->input.y_stride, + pT->output.pData[0], + pT->output.y_stride); + } + else + processed -=1; + break; + } + case DVP_KN_NV12_TO_YUV444p: + case DVP_KN_YUV_NV12_TO_YU24_HALF_SCALE: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + //DVP_PrintImage(DVP_ZONE_KGM, &pT->input); + //DVP_PrintImage(DVP_ZONE_KGM, &pT->output); + if (pT->input.color == FOURCC_NV12 && + pT->output.color == FOURCC_YV24) + { + __nv12_to_half_yuv444_image(pT->input.width, + pT->input.height, + pT->input.pData[0], + pT->input.pData[1], + pT->input.y_stride, + pT->output.pData[0], + pT->output.pData[2], + pT->output.pData[1], + pT->output.y_stride); + } + else if (pT->input.color == FOURCC_NV12 && + pT->output.color == FOURCC_YU24) + { + __nv12_to_half_yuv444_image(pT->input.width, + pT->input.height, + pT->input.pData[0], + pT->input.pData[1], + pT->input.y_stride, + pT->output.pData[0], + pT->output.pData[1], + pT->output.pData[2], + pT->output.y_stride); + } + break; + } + case DVP_KN_YUV420p_TO_RGBp: + case DVP_KN_YUV_IYUV_TO_RGBp: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + if (pT->input.color == FOURCC_IYUV && + pT->output.color == FOURCC_RGBP) + { + __iyuv_to_rgbp_image_bt601(pT->input.width, + pT->input.height, + pT->input.pData[0], + pT->input.pData[1], + pT->input.pData[2], + pT->input.y_stride, + pT->output.pData[0], + pT->output.pData[1], + pT->output.pData[2], + pT->output.y_stride); + } + else if (pT->input.color == FOURCC_YV12 && + pT->output.color == FOURCC_RGBP) + { + __iyuv_to_rgbp_image_bt601(pT->input.width, + pT->input.height, + pT->input.pData[0], + pT->input.pData[2], + pT->input.pData[1], + pT->input.y_stride, + pT->output.pData[0], + pT->output.pData[1], + pT->output.pData[2], + pT->output.y_stride); + } + break; + } + case DVP_KN_YUV_Y800_ROTATE_CW_90: + case DVP_KN_YUV_Y800_ROTATE_CCW_90: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + if (pT->input.color == pT->output.color && + pT->input.width == pT->output.height && + pT->input.height == pT->output.width && + pT->input.planes == pT->output.planes && + (DVP_U32)pT->input.y_stride == pT->input.width && + (DVP_U32)pT->output.y_stride == pT->output.width) + { + uint32_t p = 0; + for (p = 0; p < pT->input.planes; p++) + { + uint32_t div_x = 1; + uint32_t div_y = 1; + if (p > 0 ) + { + if (pT->input.color == FOURCC_IYUV || + pT->input.color == FOURCC_YV12) + { + div_x = 2; + div_y = 2; + } + else if (pT->input.color == FOURCC_YU16 || + pT->input.color == FOURCC_YV16) + { + div_x = 2; + } + } + + if (kernel == DVP_KN_YUV_Y800_ROTATE_CW_90) + __planar_rotate_cw90(pT->input.width/div_x, + pT->input.height/div_y, + pT->input.pData[p], + pT->output.pData[p]); + else if (kernel == DVP_KN_YUV_Y800_ROTATE_CCW_90) + __planar_rotate_ccw90(pT->input.width/div_x, + pT->input.height/div_y, + pT->input.pData[p], + pT->output.pData[p]); + } + } + else + processed -= 1; + break; + } + case DVP_KN_YUV_UYVY_ROTATE_CW_90: + case DVP_KN_YUV_UYVY_ROTATE_CCW_90: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + if (pT->input.color == pT->output.color && + pT->input.color == FOURCC_UYVY && + pT->input.width == pT->output.height && + pT->input.height == pT->output.width) + { + if (kernel == DVP_KN_YUV_UYVY_ROTATE_CW_90) + __uyvy_rotate_cw90(pT->input.width, + pT->input.height, + pT->input.pData[0], + pT->output.pData[0], + pT->input.y_stride, + pT->output.y_stride); + else if (kernel == DVP_KN_YUV_UYVY_ROTATE_CCW_90) + __uyvy_rotate_ccw90(pT->input.width, + pT->input.height, + pT->input.pData[0], + pT->output.pData[0], + pT->input.y_stride, + pT->output.y_stride); + } + else + processed -= 1; + break; + } + case DVP_KN_Y800_TO_XYXY: + case DVP_KN_YUV_Y800_TO_XYXY: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + if (pT->input.color == FOURCC_Y800 && + pT->output.color == FOURCC_UYVY) + { + __luma_to_uyvy_image(pT->input.width, + pT->input.height, + pT->input.pData[0], + pT->input.y_stride, + pT->output.pData[0], + pT->output.y_stride); + } + break; + } + case DVP_KN_UYVY_TO_BGR: + case DVP_KN_YUV_UYVY_TO_BGR: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + if (pT->input.color == FOURCC_UYVY && + pT->output.color == FOURCC_BGR) + { + __uyvy_to_bgr_image_bt601(pT->input.width, pT->input.height, + pT->input.pData[0], pT->input.y_stride, + pT->output.pData[0], pT->output.y_stride); + } + break; + } + case DVP_KN_YUV_ARGB_TO_UYVY: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + if (pT->input.color == FOURCC_ARGB && + pT->output.color == FOURCC_UYVY) + { + DVP_PrintImage(DVP_ZONE_KGM, &pT->input); + DVP_PrintImage(DVP_ZONE_KGM, &pT->output); + __argb_to_uyvy_image_bt601(pT->input.width, pT->input.height, + pT->input.pData[0], pT->input.y_stride, + pT->output.pData[0], pT->output.y_stride); + } + break; + } +#endif // YUV ONLY CASES + +#if defined(DVP_USE_YUV) || defined(DVP_USE_VLIB) + //****************************************************** + // YUV OR VLIB CASES + //****************************************************** + + + case DVP_KN_UYVY_TO_YUV420p: +#if defined(DVP_USE_YUV) + case DVP_KN_YUV_UYVY_TO_IYUV: +#elif defined(DVP_USE_VLIB) + case DVP_KN_VLIB_UYVY_TO_YUV420p: +#endif + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + if (pT->input.color == FOURCC_UYVY && + (pT->output.color == FOURCC_IYUV || pT->output.color == FOURCC_YV12)) + { + DVP_U08 *pU, *pV; + int y_stride = pT->output.y_stride; + int uv_stride = y_stride >> 1; +#if defined(DVP_USE_TILER) + if (y_stride == TILER_STRIDE_8BIT) + uv_stride = y_stride; +#endif + if (pT->output.color == FOURCC_YV12) + { + pV = pT->output.pData[1]; + pU = pT->output.pData[2]; + } + else + { + pU = pT->output.pData[1]; + pV = pT->output.pData[2]; + } +#if defined(DVP_USE_YUV) + __uyvy_to_yuv420_image(pT->input.width, + pT->input.height, + pT->input.pData[0], + pT->input.y_stride, + pT->output.pData[0], + pU, + pV, + y_stride, + uv_stride); +#elif defined(DVP_USE_VLIB) + if (uv_stride != pT->output.y_stride) + { + VLIB_convertUYVYint_to_YUV420pl(pT->input.pData[0], + pT->input.width, + pT->input.y_stride/pT->input.x_stride, + pT->input.height, + pT->output.pData[0], + pV, + pU); + } + else + { + DVP_U08* in = pT->input.pData[0]; + DVP_U08* Y = pT->output.pData[0]; + for(i=0; iinput.height/2; i++) + { + VLIB_convertUYVYint_to_YUV420pl(in, + pT->input.width, + pT->input.y_stride/pT->input.x_stride, + 2, + Y, + pV, + pU); + in += pT->input.y_stride*2; + Y += pT->output.y_stride*2; + pU += uv_stride; + pV += uv_stride; + } + } +#endif + } + break; + } + case DVP_KN_UYVY_TO_RGBp: +#if defined(DVP_USE_YUV) + case DVP_KN_YUV_UYVY_TO_RGBp: +#elif defined(DVP_USE_VLIB) + case DVP_KN_VLIB_UYVY_TO_RGBp: +#endif + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + if (pT->input.color == FOURCC_UYVY && + pT->output.color == FOURCC_RGBP) + { +#if defined(DVP_USE_YUV) + __uyvy_to_rgbp_image_bt601(pT->input.width, + pT->input.height, + pT->input.pData[0], + pT->input.y_stride, + pT->output.pData[0], + pT->output.pData[1], + pT->output.pData[2], + pT->output.y_stride); +#elif defined(DVP_USE_VLIB) + // Convert UYVY to RGB (planar) + S16 coeff[] = {8192, 11229, -2757, -5720, 14192}; // 2^13*coeff + VLIB_convertUYVYint_to_RGBpl(pT->input.pData[0], + pT->input.width, + pT->input.y_stride/pT->input.x_stride, + pT->input.height, + coeff, + pT->output.pData[0], + pT->output.pData[1], + pT->output.pData[2]); +#endif + } + break; + } + + case DVP_KN_XYXY_TO_Y800: +#if defined(DVP_USE_YUV) + case DVP_KN_YUV_XYXY_TO_Y800: +#endif +#if defined(DVP_USE_VLIB) + case DVP_KN_VLIB_XYXY_TO_Y800: +#endif + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + if (pT->input.color == FOURCC_UYVY) + { +#if defined(DVP_USE_YUV) + __uyvy_luma_extract(pT->input.width, pT->input.height, + pT->input.pData[0], pT->input.y_stride, + pT->output.pData[0], pT->output.y_stride); +#elif defined(DVP_USE_VLIB) + VLIB_extractLumaFromxYxY(pT->input.pData[0], + pT->input.width, + pT->input.y_stride/pT->input.x_stride, + pT->input.height, + pT->output.pData[0]); +#endif + } + break; + } + + case DVP_KN_UYVY_TO_YUV444p: +#if defined(DVP_USE_YUV) + case DVP_KN_YUV_UYVY_TO_YU24: +#elif defined(DVP_USE_VLIB) + case DVP_KN_VLIB_UYVY_TO_YUV444p: +#endif + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + // the conversion call is based on the input to output formats + if (pT->input.color == FOURCC_UYVY && + (pT->output.color == FOURCC_YV24 || pT->output.color == FOURCC_YU24)) + { + // Convert UYVY to YUV444(planar) + DVP_U08 *pU, *pV; + if (pT->output.color == FOURCC_YV24) + { + pV = pT->output.pData[1]; + pU = pT->output.pData[2]; + } + else + { + pU = pT->output.pData[1]; + pV = pT->output.pData[2]; + } +#if defined(DVP_USE_YUV) + __uyvy_to_yuv444p_image(pT->input.width, pT->input.height, + pT->input.pData[0], pT->input.y_stride, + pT->output.pData[0], pT->output.pData[1],pT->output.pData[2], + pT->output.y_stride); +#elif defined(DVP_USE_VLIB) + VLIB_convertUYVYint_to_YUV444pl(pT->input.pData[0], + pT->input.width, + pT->input.y_stride/pT->input.x_stride, + pT->input.height, + pT->output.pData[0],pU,pV); +#endif + } + break; + } +#endif // YUV OR VLIB + +#if defined(DVP_USE_VLIB) + //****************************************************** + // VLIB ONLY CASES + //****************************************************** + + case DVP_KN_YXYX_TO_Y800: + case DVP_KN_VLIB_YXYX_TO_Y800: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + if (pT->input.color == FOURCC_YUY2) + { + VLIB_extractLumaFromYxYx(pT->input.pData[0], + pT->input.width, + pT->input.y_stride/pT->input.x_stride, + pT->input.height, + pT->output.pData[0]); + } + break; + } + case DVP_KN_YUV422p_TO_UYVY: + case DVP_KN_VLIB_YUV422p_TO_UYVY: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + if ((pT->input.color == FOURCC_YV16 || pT->input.color == FOURCC_YU16) && + pT->output.color == FOURCC_UYVY) + { + DVP_U08 *pU, *pV; + if (pT->input.color == FOURCC_YV16) + { + pV = pT->input.pData[1]; + pU = pT->input.pData[2]; + } + else + { + pU = pT->input.pData[1]; + pV = pT->input.pData[2]; + } + VLIB_ConvertUYVYpl_to_YUVint(pT->input.pData[0],pU,pV, + pT->input.width, + pT->input.y_stride/pT->input.x_stride, + pT->input.height, + pT->output.pData[0]); + } + break; + } + case DVP_KN_UYVY_TO_YUV422p: + case DVP_KN_VLIB_UYVY_TO_YUV422p: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + if (pT->input.color == FOURCC_UYVY && + (pT->output.color == FOURCC_YV16 || pT->output.color == FOURCC_YU16)) + { + DVP_U08 *pU, *pV; + if (pT->output.color == FOURCC_YV16) + { + pV = pT->output.pData[1]; + pU = pT->output.pData[2]; + } + else + { + pU = pT->output.pData[1]; + pV = pT->output.pData[2]; + } + VLIB_convertUYVYint_to_YUV422pl(pT->input.pData[0], + pT->input.width, + pT->input.y_stride/pT->input.x_stride, + pT->input.height, + pT->output.pData[0],pU,pV); + + } + break; + } +#endif + +#if defined(DVP_USE_YUV) || defined(DVP_USE_IMAGE) + // YUV OR IMAGE_t + + case DVP_KN_BGR3_TO_UYVY: + case DVP_KN_BGR3_TO_IYUV: +#if defined(DVP_USE_YUV) + case DVP_KN_YUV_BGR_TO_UYVY: + case DVP_KN_YUV_BGR_TO_IYUV: +#endif +#if !defined(DVP_USE_YUV) && defined(DVP_USE_IMAGE) + case DVP_KN_NV12_TO_YUV444p: +#endif +#if defined(DVP_USE_IMAGE) + case DVP_KN_YUV444p_TO_RGBp: + case DVP_KN_YUV444p_TO_UYVY: + case DVP_KN_NV12_TO_UYVY: + case DVP_KN_BGR3_TO_NV12: +#endif + { +#if defined(DVP_USE_YUV) + DVP_Transform_t *pIO = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + if (kernel == DVP_KN_YUV_BGR_TO_UYVY || + kernel == DVP_KN_BGR3_TO_UYVY) + { + __bgr_to_uyvy_image_bt601(pIO->input.width, + pIO->input.height, + pIO->input.pData[0], + pIO->input.y_stride, + pIO->output.pData[0], + pIO->output.y_stride); + break; + } + else if (kernel == DVP_KN_YUV_BGR_TO_IYUV || + kernel == DVP_KN_BGR3_TO_IYUV) + { + __bgr_to_iyuv_image_bt601(pIO->input.width, + pIO->input.height, + pIO->input.pData[0], + pIO->input.y_stride, + pIO->output.pData[0], + pIO->output.pData[1], + pIO->output.pData[2]); + break; + } + else +#endif + { + image_t src, dst; + DVP_Image_to_image_t(&src, &dvp_knode_to(&pSubNodes[n], DVP_Transform_t)->input); + DVP_Image_to_image_t(&dst, &dvp_knode_to(&pSubNodes[n], DVP_Transform_t)->output); + image_convert(&dst, &src); + break; + } + } + + +#endif + +#if defined(DVP_USE_VLIB) +#if defined(VLIB_DISPARITY_FIXED) + // these disparity calculations seem to be broken, we'll reenable once they are fixed. + case DVP_KN_VLIB_DISPARITY_SAD8: + { + DVP_U32 y = 0, d = 0; + DVP_Disparity_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Disparity_t); + S32 disparityWindow = (20*pT->left.width)/100; // 20% of the width + U08 *scratch = (U08 *)calloc(1, pT->left.width); + if (scratch) + { + for (d = 1; d < pT->displacement; d++) + { + memset(scratch, 0, pT->left.width); + VLIB_disparity_SAD_firstRow8(&pT->left.pData[0][disparityWindow/2], + &pT->right.pData[0][disparityWindow/2], + pT->cost.pData[0], + pT->mincost.pData[0], + scratch, + pT->disparity.pData[0], + d, + pT->left.width, + pT->left.y_stride, + disparityWindow); + + for (y = 1; y < pT->left.height; y++) + { + VLIB_disparity_SAD8(&pT->left.pData[0][y*pT->left.y_stride + disparityWindow/2], + &pT->right.pData[0][y*pT->right.y_stride + disparityWindow/2], + (U16 *)&pT->cost.pData[0][y*pT->cost.y_stride], + (U16 *)&pT->mincost.pData[0][y*pT->mincost.y_stride], + (S08 *)&pT->disparity.pData[0][y*pT->disparity.y_stride], + d, + pT->left.width, + pT->left.y_stride, + disparityWindow); + } + + } + free(scratch); + } + break; + } + case DVP_KN_VLIB_DISPARITY_SAD16: + { + DVP_U32 y = 0; + DVP_Disparity_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Disparity_t); + for (y = 0; y < pT->left.height; y++) + { + VLIB_disparity_SAD16((U16 *)&pT->left.pData[0][y*pT->left.y_stride], + (U16 *)&pT->right.pData[0][y*pT->right.y_stride], + (U16 *)&pT->cost.pData[0][y*pT->cost.y_stride], + (U16 *)&pT->mincost.pData[0][y*pT->mincost.y_stride], + (S08 *)&pT->disparity.pData[0][y*pT->disparity.y_stride], + pT->displacement, + pT->left.width, + pT->left.y_stride/pT->left.x_stride, + 1); + } + break; + } +#endif + case DVP_KN_VLIB_UYVY_TO_HSLp: //Supports both 2D and 1D inputs/outputs (160x120!!) + { + DVP_Int2Pl_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Int2Pl_t); + + if (pT->input.color == FOURCC_UYVY) + { + DVP_U08* in = pT->input.pData[0]; + DVP_U08* out0 = pT->output1.pData[0]; + DVP_U08* out1 = pT->output2.pData[0]; + DVP_U08* out2 = pT->output3.pData[0]; + DVP_U32 inStride = pT->input.y_stride; + DVP_U32 outStride1 = pT->output1.y_stride; + DVP_U32 outStride2 = pT->output2.y_stride; + if(outStride1 > pT->output1.width) // If the output does not have stride == width, call the function in a loop + { + for(i=0; iinput.height; i++) + { + VLIB_convertUYVYint_to_HSLpl( in, + pT->input.width, + 1, + 1, + yuv2rgbMatrix, + div_table_DDR2, + (DVP_U16*)out0, + out1, + out2); + in += inStride; + out0 += outStride1; + out1 += outStride2; + out2 += outStride2; + } + } + else // The VLIB function can handle strided inputs, but not outputs + { + VLIB_convertUYVYint_to_HSLpl( in, + pT->input.width, + inStride/pT->input.x_stride, + pT->input.height, + yuv2rgbMatrix, + div_table_DDR2, + (DVP_U16*)out0, + out1, + out2); + } + } + break; + } + case DVP_KN_VLIB_UYVY_TO_LABp: + { + DVP_Int2Pl_t *pLAB = dvp_knode_to(&pSubNodes[n], DVP_Int2Pl_t); + + if (pLAB->input.color == FOURCC_UYVY) + { + DVP_U08* in = pLAB->input.pData[0]; + DVP_U08* L = pLAB->output1.pData[0]; + DVP_U08* a = pLAB->output2.pData[0]; + DVP_U08* b = pLAB->output3.pData[0]; + DVP_U08* LUT = pLAB->scratch.pData; + DVP_U32 inStride = pLAB->input.y_stride; + DVP_U32 outStride = pLAB->output1.y_stride; + + if(outStride > pLAB->output1.width) // If the output does not have stride == width, call the function in a loop + { + VLIB_initUYVYint_to_LABpl_LUT((S32) pLAB->factor, + yuv2rgbMatrix, + whitePoint, + (U16*)LUT); + + for(i=0; iinput.height; i++) + { + VLIB_convertUYVYint_to_LABpl_LUT( in, + pLAB->input.width, + pLAB->input.width, + 1, + (S32) pLAB->factor, + (U16*)LUT, + (U16*)L, + (U16*)a, + (U16*)b); + in += inStride; + L += outStride; + a += outStride; + b += outStride; + } + } + else // The VLIB function can handle strided inputs, but not outputs + { + VLIB_convertUYVYint_to_LABpl_LUT( in, + pLAB->input.width, + pLAB->input.width, + pLAB->input.height, + (S32) pLAB->factor, + (U16*)LUT, + (U16*)L, + (U16*)a, + (U16*)b); + } + } + break; + } + case DVP_KN_VLIB_INIT_MEAN_LUMA_S16: + { + DVP_U32 y = 0; + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + for (y = 0; y < pT->input.height; y++) + { + VLIB_initMeanWithLumaS16((S16 *)&pT->output.pData[0][y*pT->output.y_stride], + &pT->input.pData[0][y*pT->input.y_stride], + pT->input.width); + } + break; + } + case DVP_KN_VLIB_INIT_MEAN_LUMA_S32: + { + DVP_U32 y = 0; + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + for (y = 0; y < pT->input.height; y++) + { + VLIB_initMeanWithLumaS32((S32 *)&pT->output.pData[0][y*pT->output.y_stride], + &pT->input.pData[0][y*pT->input.y_stride], + pT->input.width); + } + break; + } + case DVP_KN_VLIB_INIT_VAR_CONST_S16: + { + DVP_U32 y = 0; + DVP_ConstVar_t *pV = dvp_knode_to(&pSubNodes[n], DVP_ConstVar_t); + for (y = 0; y < pV->var.height; y++) + { + VLIB_initVarWithConstS16((S16 *)&pV->var.pData[0][y*pV->var.y_stride], + pV->constVar, + pV->var.width); + } + break; + } + case DVP_KN_VLIB_INIT_VAR_CONST_S32: + { + DVP_U32 y = 0; + DVP_ConstVar_t *pV = dvp_knode_to(&pSubNodes[n], DVP_ConstVar_t); + for (y = 0; y < pV->var.height; y++) + { + VLIB_initVarWithConstS32((S32 *)&pV->var.pData[0][y*pV->var.y_stride], + pV->constVar, + pV->var.width); + } + break; + } +#endif + +#if defined(DVP_USE_IMGFILTER) || defined(DVP_USE_VLIB) + //************************************* + // IMGFILTER OR VLIB + //************************************* + + case DVP_KN_SOBEL_8: +#if defined(DVP_USE_IMGFILTER) + case DVP_KN_IMGFILTER_SOBEL: +#elif defined(DVP_USE_VLIB) + case DVP_KN_VLIB_SOBEL_8: +#endif + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); +#if defined(DVP_USE_IMGFILTER) + DVP_imgFilter(&pT->input, DVP_IMGFILTER_SOBEL, &pT->output); +#elif defined(DVP_USE_VLIB) + VLIB_sobelFilter_U8(pT->input.pData[0], + pT->input.width, + pT->input.height, + pT->input.y_stride, + pT->output.pData[0]); +#endif + break; + } + case DVP_KN_SCHARR_8: +#if defined(DVP_USE_IMGFILTER) + case DVP_KN_IMGFILTER_SCHARR: +#elif defined(DVP_USE_VLIB) + case DVP_KN_VLIB_SCHARR_8: +#endif + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); +#if defined(DVP_USE_IMGFILTER) + DVP_imgFilter(&pT->input, DVP_IMGFILTER_SCHARR, &pT->output); +#elif defined(DVP_USE_VLIB) + VLIB_scharrFilter_U8(pT->input.pData[0], + pT->input.width, + pT->input.height, + pT->input.y_stride, + pT->output.pData[0]); +#endif + break; + } + case DVP_KN_KROON_8: +#if defined(DVP_USE_IMGFILTER) + case DVP_KN_IMGFILTER_KROON: +#elif defined(DVP_USE_VLIB) + case DVP_KN_VLIB_KROON_8: +#endif + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); +#if defined(DVP_USE_IMGFILTER) + DVP_imgFilter(&pT->input, DVP_IMGFILTER_KROON, &pT->output); +#elif defined(DVP_USE_VLIB) + VLIB_kroonFilter_U8(pT->input.pData[0], + pT->input.width, + pT->input.height, + pT->input.y_stride, + pT->output.pData[0]); +#endif + break; + } + case DVP_KN_PREWITT_8: +#if defined(DVP_USE_IMGFILTER) + case DVP_KN_IMGFILTER_PREWITT: +#elif defined(DVP_USE_VLIB) + case DVP_KN_VLIB_PREWITT_8: +#endif + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); +#if defined(DVP_USE_IMGFILTER) + DVP_imgFilter(&pT->input, DVP_IMGFILTER_PREWITT, &pT->output); +#elif defined(DVP_USE_VLIB) + VLIB_prewittFilter_U8(pT->input.pData[0], + pT->input.width, + pT->input.height, + pT->input.y_stride, + pT->output.pData[0]); +#endif + break; + } +#endif // IMGFILTER || VLIB + +#if defined(DVP_USE_RVM) + case DVP_KN_RVM: + { + DVP_Rvm_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Rvm_t); + Rvm_Image_t input, output; + RVM_colorformat_e color; + DVP_U32 scratchSize; + void *scratch; + + input.pData[0] = pT->input.pData[0]; + input.stride[0] = pT->input.y_stride; + output.pData[0] = pT->output.pData[0]; + output.stride[0] = pT->output.y_stride; + + if(pT->input.color == FOURCC_UYVY) + color = RVM_COLORFORMAT_YUV422; + else if (pT->input.color == FOURCC_Y800) + color = RVM_COLORFORMAT_LUMA8; + else if (pT->input.color == FOURCC_NV12) + { + color = RVM_COLORFORMAT_NV12; + input.pData[1] = pT->input.pData[1]; + input.stride[1] = pT->input.y_stride; + output.pData[1] = pT->output.pData[1]; + output.stride[1] = pT->output.y_stride; + } + else + { + processed--; + pSubNodes[n].header.error = DVP_ERROR_INVALID_PARAMETER; + break; + } + + scratchSize = RVM_getScratchSize(pT->lut.pData, color); + scratch = malloc(scratchSize); + + if(scratch) + { + RVM_wrapper(&input, + &output, + color, + pT->lut.pData, + (uint8_t *)scratch, + scratchSize, + 0); + free(scratch); + } + else + { + processed--; + pSubNodes[n].header.error = DVP_ERROR_NO_MEMORY; + } + break; + } +#endif +#if defined(DVP_USE_IMGLIB) + case DVP_KN_SOBEL_3x3_8: + case DVP_KN_IMG_SOBEL_3x3_8: + { + DVP_Transform_t *pIO = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + + if (pIO->input.y_stride == (int)pIO->input.width) + { + IMG_sobel_3x3_8(pIO->input.pData[0], + pIO->output.pData[0], + pIO->input.width, + pIO->input.height); + } + else + { + DVP_U08 *tmpBuf = (DVP_U08 *)malloc(pIO->input.width * (16 + (3 -1))); + DVP_U08* in = pIO->input.pData[0]; + DVP_U08* out = pIO->output.pData[0]; + DVP_U32 y; + DVP_U32 newheight = pIO->input.height -(3 -1); + DVP_U08 blockHeight = 16; + + for(y=0; y newheight) + blockHeight = newheight-y; + + for(i=0; i<(blockHeight + (3 -1)); i++) + memcpy(&tmpBuf[i*pIO->input.width], &pIO->input.pData[0][(y+i)*pIO->input.y_stride], pIO->input.width); + + IMG_sobel_3x3_8(tmpBuf, + &out[y*pIO->output.y_stride], + pIO->input.width, + blockHeight+2); + } + free(tmpBuf); + } + + break; + } + case DVP_KN_SOBEL_3x3_16s: + case DVP_KN_IMG_SOBEL_3x3_16s: + { + DVP_Transform_t *pSb = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + + IMG_sobel_3x3_16s((short *)pSb->input.pData[0], + (short *)pSb->output.pData[0], + (short)(pSb->input.width), + (short)(pSb->input.height ) ); + break; + } + case DVP_KN_SOBEL_5x5_16s: + case DVP_KN_IMG_SOBEL_5x5_16s: + { + DVP_Transform_t *pSb = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + + IMG_sobel_5x5_16s((short *)pSb->input.pData[0], + (short *)pSb->output.pData[0], + (short)(pSb->input.width) , + (short)(pSb->input.height )); + break; + } + case DVP_KN_SOBEL_7x7_16s: + case DVP_KN_IMG_SOBEL_7x7_16s: + { + DVP_Transform_t *pSb = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + + IMG_sobel_7x7_16s((short *)pSb->input.pData[0], + (short *)pSb->output.pData[0], + (short)(pSb->input.width) , + (short)(pSb->input.height ) ); + break; + } + case DVP_KN_CONV_3x3: // Assumes 1D buffer + case DVP_KN_IMG_CONV_3x3: // Assumes 1D buffer + { + DVP_ImageConvolution_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageConvolution_t); + DVP_U32 filterSize = 3; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + DVP_U32 y; + if((int)pImg->input.width == pImg->input.y_stride) + { + for(i=0; iinput.width, + (const char*)pImg->mask.pData[0], + (int)pImg->shiftMask); + in += pImg->input.y_stride; + out += pImg->output.y_stride; + } + }else + { + DVP_U08 *tmpBuf = (DVP_U08 *)malloc(pImg->input.width * (16 + (filterSize -1))); + DVP_U08 blockHeight = 16; + for(y=0; y newheight) + blockHeight = newheight-y; + + for(i=0; i<(blockHeight + (filterSize -1)); i++) + memcpy(&tmpBuf[i*pImg->input.width], &pImg->input.pData[0][(y+i)*pImg->input.y_stride], pImg->input.width); + + for(i=0; iinput.width], + out, + (int)pImg->input.width, + (const char*)pImg->mask.pData[0], + (int)pImg->shiftMask); + out += pImg->output.y_stride; + } + } + free(tmpBuf); + } + + break; + } + case DVP_KN_CONV_5x5: // 1D or 2D buffers + case DVP_KN_IMG_CONV_5x5: // 1D or 2D buffers + { + DVP_ImageConvolution_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageConvolution_t); + DVP_U32 filterSize = 5; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + + for(i=0; iinput.width -(filterSize -1)), + (short)pImg->input.y_stride, + (const char *)pImg->mask.pData[0], + (short)pImg->shiftMask); + in += pImg->input.y_stride; + out += pImg->output.y_stride; + } + break; + } + case DVP_KN_CONV_7x7: // 1D or 2D buffers + case DVP_KN_IMG_CONV_7x7: // 1D or 2D buffers + case DVP_KN_CANNY_IMAGE_SMOOTHING: + { + DVP_ImageConvolution_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageConvolution_t); + DVP_U32 filterSize = 7; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + + for(i=0; iinput.width -(filterSize -1)), + (short)pImg->input.y_stride, + (const signed char *)pImg->mask.pData[0], + (short)pImg->shiftMask); + in += pImg->input.y_stride; + out += pImg->output.y_stride; + } + break; + } + case DVP_KN_IMG_CONV_3x3_I16s_C16: + { + DVP_ImageConvolution_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageConvolution_t); + DVP_U32 filterSize = 3; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + DVP_U32 outStride = pImg->output.y_stride; + + for(i=0; iinput.width -(filterSize -1)), + (int)pImg->input.width, + (short*)pImg->mask.pData[0], + (int)pImg->shiftMask); + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_CONV_5x5_I8_C16: + { + DVP_ImageConvolution_with_buffer_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageConvolution_with_buffer_t); + DVP_U32 filterSize = 5; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + DVP_U32 outStride = pImg->output.y_stride; + for(i=0; iinput.width -(filterSize -1)), + (short)pImg->input.width, + (DVP_S16*)pImg->mask.pData[0], + (short)pImg->shiftMask); + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_CONV_5x5_I16s_C16: + { + DVP_ImageConvolution_with_buffer_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageConvolution_with_buffer_t); + DVP_U32 filterSize = 5; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + DVP_U32 outStride = pImg->output.y_stride; + for(i=0; iinput.width -(filterSize -1)), + (short)pImg->input.width, + (short*)pImg->mask.pData[0], + (short)pImg->shiftMask); + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_CONV_7x7_I8_C16: + { + DVP_ImageConvolution_with_buffer_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageConvolution_with_buffer_t); + DVP_U32 filterSize = 7; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + DVP_U32 outStride = pImg->output.y_stride; + for(i=0; iinput.width -(filterSize -1)), + (short)pImg->input.width, + (short*)pImg->mask.pData[0], + (short)pImg->shiftMask); + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_CONV_7x7_I16s_C16: + { + DVP_ImageConvolution_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageConvolution_t); + DVP_U32 filterSize = 7; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + DVP_U32 outStride = pImg->output.y_stride; + for(i=0; iinput.width -(filterSize -1)), + (short)pImg->input.width, + (short*)pImg->mask.pData[0], + (short)pImg->shiftMask); + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_CONV_11x11: + { + DVP_ImageConvolution_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageConvolution_t); + DVP_U32 filterSize = 11; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + DVP_U32 outStride = pImg->output.y_stride; + for(i=0; iinput.width -(filterSize -1)), + (short)pImg->input.width, + (char*)pImg->mask.pData[0], + (short)pImg->shiftMask); + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_CONV_11x11_I16s_C16: + { + DVP_ImageConvolution_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageConvolution_t); + DVP_U32 filterSize = 11; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + DVP_U32 outStride = pImg->output.y_stride; + for(i=0; iinput.width -(filterSize -1)), + (short)pImg->input.width, + (short*)pImg->mask.pData[0], + (short)pImg->shiftMask); + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_CORR_3x3: + { + DVP_ImageCorrelation_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageCorrelation_t); + DVP_U32 filterSize = 3; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + DVP_U32 outStride = pImg->output.y_stride; + for(i=0; iinput.width - (filterSize - 1), + (int)pImg->input.width, + (DVP_U08*)pImg->mask.pData[0], + (int)pImg->shift, + (int)pImg->round); + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_CORR_3x3_I8_C16s: + { + DVP_ImageCorrelation_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageCorrelation_t); + DVP_U32 filterSize = 3; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + DVP_U32 outStride = pImg->output.y_stride; + for(i=0; iinput.width - (filterSize - 1), + (short)pImg->input.width, + (short*)pImg->mask.pData[0]); + + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_CORR_3x3_I16s_C16s: + { + DVP_ImageCorrelation_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageCorrelation_t); + DVP_U32 filterSize = 3; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + DVP_U32 outStride = pImg->output.y_stride; + for(i=0; iinput.width - (filterSize - 1), + (short)pImg->input.width, + (short*)pImg->mask.pData[0], + (short)pImg->shift, + (int)pImg->round); + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_CORR_5x5_I16s_C16s: + { + DVP_ImageCorrelation_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageCorrelation_t); + DVP_U32 filterSize = 5; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + DVP_U32 outStride = pImg->output.y_stride; + for(i=0; iinput.width - (filterSize - 1), + (short)pImg->input.width, + (short*)pImg->mask.pData[0], + (short)pImg->shift, + (int)pImg->round); + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_CORR_11x11_I8_C16s: //yet to be defined + { + DVP_ImageCorrelation_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageCorrelation_t); + DVP_U32 filterSize = 11; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + DVP_U32 outStride = pImg->output.y_stride; + for(i=0; iinput.width - (filterSize - 1), + (short)pImg->input.width, + (short*)pImg->mask.pData[0]); + + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_CORR_11x11_I16s_C16s: + { + DVP_ImageCorrelation_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageCorrelation_t); + DVP_U32 filterSize = 11; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + DVP_U32 outStride = pImg->output.y_stride; + for(i=0; iinput.width - (filterSize - 1), + (short)pImg->input.width, + (short*)pImg->mask.pData[0], + (short)pImg->shift, + (int)pImg->round); + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_CORR_GEN_I16s_C16s: + { + DVP_ImageCorrelation_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageCorrelation_t); + DVP_U32 filterSize = pImg->m; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + DVP_U32 outStride = pImg->output.y_stride; + for(i=0; imask.pData[0], + (short*)out, + filterSize, + (short)pImg->input.width); + + + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_CORR_GEN_IQ: + { + DVP_ImageCorrelation_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_ImageCorrelation_t); + DVP_U32 filterSize = pImg->m; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + DVP_U32 outStride = pImg->output.y_stride; + for(i=0; imask.pData[0], + (int*)out, + filterSize, + (short)pImg->input.width, + pImg->x_qpt, + pImg->h_qpt, + pImg->y_qpt); + + + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_HISTOGRAM_8: + { + DVP_Histogram_t *pH = dvp_knode_to(&pSubNodes[n], DVP_Histogram_t); + IMG_histogram_8(pH->input.pData[0], + pH->input.width * pH->input.height, + (int)pH->binWeight, + (short*)pH->histArray.pData, + (short*)pH->hOut.pData); + break; + } + case DVP_KN_IMG_HISTOGRAM_16: + { + DVP_Histogram_t *pH = dvp_knode_to(&pSubNodes[n], DVP_Histogram_t); + memset(pH->histArray.pData, 0, (1 << pH->numBins)*4); + IMG_histogram_16((DVP_U16 *)pH->input.pData[0], + pH->input.width * pH->input.height, + (int)pH->binWeight, + (short*)pH->histArray.pData, + (short*)pH->hOut.pData, + (int)pH->numBins); + break; + } + case DVP_KN_IMG_CLIPPING_16: + { + DVP_CannyHystThresholding_t *pClp = dvp_knode_to(&pSubNodes[n], DVP_CannyHystThresholding_t); + IMG_clipping_16s((short *)pClp->inMag.pData[0], + (short)(pClp->inMag.height), + (short)(pClp->inMag.width), + (short *)pClp->output.pData[0], + (short)(pClp->hiThresh) , + (short)(pClp->loThresh )); + break; + } + case DVP_KN_IMG_MEDIAN_3x3_8: + { + DVP_Transform_t *pMd = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + DVP_U08* in = pMd->input.pData[0]; + DVP_U08* out = pMd->output.pData[0]; + DVP_U32 newheight = pMd->input.height - 2; + DVP_U32 inStride = pMd->input.y_stride; + DVP_U32 outStride = pMd->output.y_stride; + for(i=0; iinput.width, + (DVP_U08*)out); + + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_MEDIAN_3x3_16s: + { + DVP_Transform_t *pMd = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + DVP_U08* in = pMd->input.pData[0]; + DVP_U08* out = pMd->output.pData[0]; + DVP_U32 newheight = pMd->input.height - 2; + DVP_U32 inStride = pMd->input.y_stride; + DVP_U32 outStride = pMd->output.y_stride; + for(i=0; iinput.width, + (DVP_S16*)out); + + in += inStride; + out += outStride; + } + break; + } + case DVP_KN_IMG_PIX_EXPAND: + { + DVP_Transform_t *pMd = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + IMG_pix_expand((int)(pMd->input.width*pMd->input.height), + (DVP_U08 *)pMd->input.pData[0], + (DVP_S16 *)pMd->output.pData[0] ); + break; + } + case DVP_KN_IMG_PIX_SAT: + { + DVP_Transform_t *pMd = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + IMG_pix_sat((int)(pMd->input.width*pMd->input.height), + (DVP_S16 *)pMd->input.pData[0], + (DVP_U08 *)pMd->output.pData[0] ); + break; + } + case DVP_KN_IMG_YC_DEMUX_BE16_8: //Supports both 2D and 1D inputs/outputs + { + DVP_Int2Pl_t *pYc = dvp_knode_to(&pSubNodes[n], DVP_Int2Pl_t); + DVP_U08* in = pYc->input.pData[0]; + DVP_U08* y = (DVP_U08*)pYc->output1.pData[0]; + DVP_U08* cr = (DVP_U08*)pYc->output2.pData[0]; + DVP_U08* cb = (DVP_U08*)pYc->output3.pData[0]; + DVP_U32 i; + for(i=0; iinput.height; i++) + { + IMG_yc_demux_be16_8(pYc->input.width, + &in[i*pYc->input.y_stride], + (DVP_S16*)&y[i*pYc->output1.y_stride], + (DVP_S16*)&cr[i*pYc->output2.y_stride], + (DVP_S16*)&cb[i*pYc->output3.y_stride]); + } + break; + } + case DVP_KN_IMG_YC_DEMUX_LE16_8: //Supports both 2D and 1D inputs/outputs + { + DVP_Int2Pl_t *pYc = dvp_knode_to(&pSubNodes[n], DVP_Int2Pl_t); + DVP_U08* in = pYc->input.pData[0]; + DVP_U08* y = (DVP_U08*)pYc->output1.pData[0]; + DVP_U08* cr = (DVP_U08*)pYc->output2.pData[0]; + DVP_U08* cb = (DVP_U08*)pYc->output3.pData[0]; + DVP_U32 i; + for(i=0; iinput.height; i++) + { + IMG_yc_demux_le16_8(pYc->input.width, + &in[i*pYc->input.y_stride], + (DVP_S16*)&y[i*pYc->output1.y_stride], + (DVP_S16*)&cr[i*pYc->output2.y_stride], + (DVP_S16*)&cb[i*pYc->output3.y_stride]); + } + break; + } + case DVP_KN_IMG_YUV422p_TO_RGB565: //Supports both 2D and 1D inputs/outputs + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + DVP_U08* y = pT->input.pData[0]; + DVP_U08 *cb, *cr; + DVP_U08* rgb = (DVP_U08*)pT->output.pData[0]; + if (pT->input.color == FOURCC_YU16) + { + cb = pT->input.pData[1]; + cr = pT->input.pData[2]; + } + else + { + cr = pT->input.pData[1]; + cb = pT->input.pData[2]; + } + + IMG_ycbcr422pl_to_rgb565( yuv2rgbMatrix, + y, + cb, + cr, + (DVP_U16*)rgb, + pT->input.width*pT->input.height); + processed++; + break; + } + case DVP_KN_IMG_SAD_8x8: // Assumes 1D buffer + { + DVP_SAD_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_SAD_t); + DVP_U32 filterSize = 8; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + IMG_sad_8x8_i8_c8(in, + (unsigned char*)pImg->refImg.pData[0], + out, + (int)pImg->input.width, + (int)newheight, + (int)pImg->shiftMask, + 0, + 8); + break; + } + case DVP_KN_IMG_SAD_16x16: // Assumes 1D buffer + { + DVP_SAD_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_SAD_t); + DVP_U32 filterSize = 16; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + IMG_sad_16x16_i8_c8(in, + (unsigned char*)pImg->refImg.pData[0], + out, + (int)pImg->input.width, + (int)newheight, + (int)pImg->shiftMask, + 0, + 8); + break; + } + case DVP_KN_IMG_SAD_3x3: // Assumes 1D buffer + { + DVP_SAD_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_SAD_t); + DVP_U32 filterSize = 3; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + IMG_sad_3x3_i8_c8(in, + (unsigned char*)pImg->refImg.pData[0], + out, + (int)pImg->input.width, + (int)newheight, + 0, + 3); + break; + } + case DVP_KN_IMG_SAD_5x5: // Assumes 1D buffer + { + // DVP_SAD_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_SAD_t); + // DVP_U32 filterSize = 5; + // DVP_U32 newheight = pImg->input.height -(filterSize -1); + // DVP_U08* in = pImg->input.pData[0]; + // DVP_U08* out = pImg->output.pData[0]; + // IMG_sad_5x5_i8_c8(in, + // (unsigned char*)pImg->refImg.pData[0], + // out, + // (int)pImg->input.width, + // (int)newheight, + // 0, + // 5); + break; + } + case DVP_KN_IMG_SAD_7x7: // Assumes 1D buffer + { + DVP_SAD_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_SAD_t); + DVP_U32 filterSize = 7; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + IMG_sad_7x7_i8_c8(in, + (unsigned char*)pImg->refImg.pData[0], + out, + (int)pImg->input.width, + (int)newheight, + 0, + 7); + break; + } + case DVP_KN_IMG_MAD_8x8: // Assumes 1D buffer + { + DVP_SAD_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_SAD_t); + DVP_U32 filterSize = 8; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + IMG_mad_8x8((unsigned char*)in, + (unsigned char*)pImg->refImg.pData[0], + (int)pImg->input.width, + (int)pImg->input.width - (filterSize - 1), + (int)newheight, + (unsigned int*)out); + break; + } + case DVP_KN_IMG_MAD_16x16: // Assumes 1D buffer + { + DVP_SAD_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_SAD_t); + DVP_U32 filterSize = 16; + DVP_U32 newheight = pImg->input.height -(filterSize -1); + DVP_U08* in = pImg->input.pData[0]; + DVP_U08* out = pImg->output.pData[0]; + IMG_mad_16x16((unsigned char*)in, + (unsigned char*)pImg->refImg.pData[0], + (int)pImg->input.width, + (int)pImg->input.width - (filterSize - 1), + (int)newheight, + (unsigned int*)out); + break; + } + case DVP_KN_THR_GT2MAX_8: + case DVP_KN_IMG_THR_GT2MAX_8: + { + DVP_Threshold_t *pThresh = dvp_knode_to(&pSubNodes[n], DVP_Threshold_t); + DVP_U08* in = pThresh->input.pData[0]; + DVP_U08* out = pThresh->output.pData[0]; + + for(i=0; iinput.height; i++) + { + IMG_thr_gt2max_8(in, + out, + (short)(pThresh->input.width), + 1, + (unsigned char)(pThresh->thresh)); + in += pThresh->input.y_stride; + out += pThresh->output.y_stride; + } + break; + } + case DVP_KN_THR_GT2MAX_16: + case DVP_KN_IMG_THR_GT2MAX_16: + { + DVP_Threshold_t *pThresh = dvp_knode_to(&pSubNodes[n], DVP_Threshold_t); + DVP_U08* in = pThresh->input.pData[0]; + DVP_U08* out = pThresh->output.pData[0]; + + for(i=0; iinput.height; i++) + { + IMG_thr_gt2max_16((const unsigned short*)in, + (unsigned short*)out, + (short)(pThresh->input.width), + 1, + (unsigned short)(pThresh->thresh)); + in += pThresh->input.y_stride; + out += pThresh->output.y_stride; + } + break; + } + case DVP_KN_THR_GT2THR_8: + case DVP_KN_IMG_THR_GT2THR_8: + { + DVP_Threshold_t *pThresh = dvp_knode_to(&pSubNodes[n], DVP_Threshold_t); + DVP_U08* in = pThresh->input.pData[0]; + DVP_U08* out = pThresh->output.pData[0]; + + for(i=0; iinput.height; i++) + { + IMG_thr_gt2thr_8(in, + out, + (short)(pThresh->input.width), + 1, + (unsigned char)(pThresh->thresh)); + in += pThresh->input.y_stride; + out += pThresh->output.y_stride; + } + break; + } + case DVP_KN_THR_GT2THR_16: + case DVP_KN_IMG_THR_GT2THR_16: + { + DVP_Threshold_t *pThresh = dvp_knode_to(&pSubNodes[n], DVP_Threshold_t); + DVP_U08* in = pThresh->input.pData[0]; + DVP_U08* out = pThresh->output.pData[0]; + + for(i=0; iinput.height; i++) + { + IMG_thr_gt2thr_16((const unsigned short*)in, + (unsigned short*)out, + (short)(pThresh->input.width), + 1, + (unsigned short)(pThresh->thresh)); + in += pThresh->input.y_stride; + out += pThresh->output.y_stride; + } + break; + } + case DVP_KN_THR_LE2MIN_8: + case DVP_KN_IMG_THR_LE2MIN_8: + { + DVP_Threshold_t *pThresh = dvp_knode_to(&pSubNodes[n], DVP_Threshold_t); + DVP_U08* in = pThresh->input.pData[0]; + DVP_U08* out = pThresh->output.pData[0]; + + for(i=0; iinput.height; i++) + { + IMG_thr_le2min_8(in, + out, + (short)(pThresh->input.width), + 1, + (unsigned char)(pThresh->thresh)); + in += pThresh->input.y_stride; + out += pThresh->output.y_stride; + } + break; + } + case DVP_KN_THR_LE2MIN_16: + case DVP_KN_IMG_THR_LE2MIN_16: + { + DVP_Threshold_t *pThresh = dvp_knode_to(&pSubNodes[n], DVP_Threshold_t); + DVP_U08* in = pThresh->input.pData[0]; + DVP_U08* out = pThresh->output.pData[0]; + + for(i=0; iinput.height; i++) + { + IMG_thr_le2min_16((const unsigned short*)in, + (unsigned short*)out, + (short)(pThresh->input.width), + 1, + (unsigned short)(pThresh->thresh)); + in += pThresh->input.y_stride; + out += pThresh->output.y_stride; + } + break; + } + case DVP_KN_THR_LE2THR_8: + case DVP_KN_IMG_THR_LE2THR_8: + { + DVP_Threshold_t *pThresh = dvp_knode_to(&pSubNodes[n], DVP_Threshold_t); + DVP_U08* in = pThresh->input.pData[0]; + DVP_U08* out = pThresh->output.pData[0]; + + for(i=0; iinput.height; i++) + { + IMG_thr_le2thr_8(in, + out, + (short)(pThresh->input.width), + 1, + (unsigned char)(pThresh->thresh)); + in += pThresh->input.y_stride; + out += pThresh->output.y_stride; + } + break; + } + case DVP_KN_THR_LE2THR_16: + case DVP_KN_IMG_THR_LE2THR_16: + { + DVP_Threshold_t *pThresh = dvp_knode_to(&pSubNodes[n], DVP_Threshold_t); + DVP_U08* in = pThresh->input.pData[0]; + DVP_U08* out = pThresh->output.pData[0]; + + for(i=0; iinput.height; i++) + { + IMG_thr_le2thr_16((const unsigned short*)in, + (unsigned short*)out, + (short)(pThresh->input.width), + 1, + (unsigned short)(pThresh->thresh)); + in += pThresh->input.y_stride; + out += pThresh->output.y_stride; + } + break; + } + case DVP_KN_IMG_BOUNDARY_8: // Assumes image is in 1D buffer + { + DVP_Boundary_t *pBoundary = dvp_knode_to(&pSubNodes[n], DVP_Boundary_t); + + IMG_boundary_8((const unsigned char*)pBoundary->input.pData[0], + (int)pBoundary->input.height, + (int)pBoundary->input.width, + (int*)pBoundary->outCoord.pData, + (int*)pBoundary->outGray.pData); + break; + } + case DVP_KN_IMG_BOUNDARY_16s: // Assumes image is in 1D buffer + { + DVP_Boundary_t *pBoundary = dvp_knode_to(&pSubNodes[n], DVP_Boundary_t); + + IMG_boundary_16s((const short*)pBoundary->input.pData[0], + (int)pBoundary->input.height, + (int)pBoundary->input.width, + (unsigned int*)pBoundary->outCoord.pData, + (short*)pBoundary->outGray.pData); + break; + } + case DVP_KN_IMG_PERIMETER_8: // Assumes image is in 1D buffer + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + DVP_U08* in = pT->input.pData[0] + pT->input.y_stride; // Start at second line + DVP_U08* out = pT->output.pData[0]; + + for(i=0; iinput.height-2; i++) + { + IMG_perimeter_8 ((const unsigned char*)in, + (int)pT->input.width, + (unsigned char*)out); + in += pT->input.y_stride; + out += pT->output.y_stride; + } + break; + } + case DVP_KN_IMG_PERIMETER_16: // Assumes image is in 1D buffer + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + DVP_U16* in = (DVP_U16*)(pT->input.pData[0] + pT->input.y_stride); // Start at second line + DVP_U16* out = (DVP_U16*)pT->output.pData[0]; + + for(i=0; iinput.height-2; i++) + { + IMG_perimeter_16 ((const unsigned short*)in, + (int)pT->input.width, + (unsigned short*)out); + in += pT->input.y_stride/2; + out += pT->output.y_stride/2; + } + break; + } + case DVP_KN_IMG_ERRDIFF_BIN_8: + { + DVP_Threshold_t *pED = dvp_knode_to(&pSubNodes[n], DVP_Threshold_t); + DVP_U08* in = pED->input.pData[0]; + int tmp_height = 0; + DVP_U32 inStride = pED->input.y_stride; + if(pED->input.y_stride > (int)pED->input.width) + tmp_height = pED->input.height; + else + tmp_height = 1; + + for(i=0; i<(pED->input.height/tmp_height); i++) + { + IMG_errdif_bin_8(in, + (int)pED->input.width, + tmp_height, + (short*)pED->output.pData[0], + pED->thresh); + in += inStride; + } + break; + } + case DVP_KN_IMG_ERRDIFF_BIN_16: + { + DVP_Threshold_t *pED = dvp_knode_to(&pSubNodes[n], DVP_Threshold_t); + DVP_U08* in = pED->input.pData[0]; + int tmp_height = 0; + DVP_U32 inStride = pED->input.y_stride; + if(pED->input.y_stride > (int)(2*pED->input.width)) + tmp_height = pED->input.height; + else + tmp_height = 1; + + for(i=0; i<(pED->input.height/tmp_height); i++) + { + IMG_errdif_bin_16((unsigned short*)in, + (int)pED->input.width, + tmp_height, + (short*)pED->output.pData[0], + pED->thresh); + in += inStride; + } + break; + } + case DVP_KN_IMG_FDCT_8x8: + { + DVP_Transform_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + DVP_U08* in = pImg->input.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + int num_fdcts = (pImg->input.width/8)*(pImg->input.height/8); + if(inStride == 2*pImg->input.width) + { + IMG_fdct_8x8((short*)in, num_fdcts); + } + break; + } + case DVP_KN_IMG_IDCT_8x8_12Q4: + { + DVP_Transform_t *pImg = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + DVP_U08* in = pImg->input.pData[0]; + DVP_U32 inStride = pImg->input.y_stride; + int num_fdcts = (pImg->input.width/8)*(pImg->input.height/8); + if(inStride == 2*pImg->input.width) + { + IMG_idct_8x8_12q4((short*)in, num_fdcts); + } + break; + } + case DVP_KN_IMG_QUANTIZE_16: + { + DVP_ImageQuantization_t *pQnt = dvp_knode_to(&pSubNodes[n], DVP_ImageQuantization_t); + DVP_U08* data = pQnt->input.pData[0]; + DVP_U32 inStride = pQnt->input.y_stride; + DVP_U32 n_blocks = 0; + DVP_U32 loop_cnt = 0; + DVP_U32 i; + if(inStride == 2*pQnt->input.width) + { + n_blocks = (pQnt->input.width*pQnt->input.height)/pQnt->block_size; + loop_cnt = 1; + } + else + { + n_blocks = pQnt->input.width/pQnt->block_size; + loop_cnt = pQnt->input.height; + } + for(i=0; iblock_size, + (short*)pQnt->recip_tbl.pData, + pQnt->q_pt); + data += inStride; + } + break; + } +#endif + default: + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: DVP KGM CPU Unknown Kernel %u\n",kernel); + pSubNodes[n].header.error = DVP_ERROR_INVALID_PARAMETER; + processed--; + break; + } + } + processed++; + DVP_PerformanceStop(pPerf); + } + DVP_PRINT(DVP_ZONE_KGM, "DVP KGM CPU: Processed %u nodes!\n", processed); + } + return processed; +} + +static thread_ret_t DVP_KernelGraphManagerThread_CPU(void *arg __attribute__((unused))) +{ + DVP_KGM_Thread_t kgmt; + DVP_S32 processed = 0; + + thread_nextaffinity(); + + while (queue_read(workqueue, true_e, &kgmt) == true_e) + { + DVP_KernelNode_t *pSubNodes = kgmt.pSubNodes; + DVP_U32 startNode = kgmt.startNode; + DVP_U32 numNodes = kgmt.numNodes; + kgmt.numNodesExecuted = 0; + processed = 0; + + DVP_PRINT(DVP_ZONE_KGM, "DVP KGM CPU Thread Read a Work Item! %p[%d] (%p) for %d nodes\n", + pSubNodes, startNode, &pSubNodes[startNode], numNodes); + + processed = DVP_KernelGraphManager_CPU(pSubNodes, startNode, numNodes); + + kgmt.numNodesExecuted = processed; + queue_write(retqueue, true_e, &kgmt); + } + DVP_PRINT(DVP_ZONE_KGM, "DVP KGM CPU: Worker Thread Exitting!\n"); + thread_exit(0); +} + +MODULE_EXPORT void DVP_KernelGraphManagerRestart(void *arg __attribute__((unused))) +{ + // do nothing, since this should never be called. +} + +MODULE_EXPORT DVP_BOOL DVP_KernelGraphManagerDeinit(void) +{ + DVP_U32 i; + queue_pop(workqueue); + queue_pop(retqueue); + for (i = 0; i < dimof(workers); i++) + thread_join(workers[i]); + queue_destroy(workqueue); + queue_destroy(retqueue); + return DVP_TRUE; +} + +MODULE_EXPORT DVP_BOOL DVP_KernelGraphManagerInit(DVP_RPC_t *pRPC __attribute__ ((unused)), + DVP_RPC_Core_t *pCore __attribute__ ((unused))) +{ + DVP_U32 i = 0; + workqueue = queue_create(10, sizeof(DVP_KGM_Thread_t)); + retqueue = queue_create(10, sizeof(DVP_KGM_Thread_t)); + for (i = 0; i < dimof(workers); i++) + workers[i] = thread_create(DVP_KernelGraphManagerThread_CPU, NULL); + return DVP_TRUE; +} + +MODULE_EXPORT DVP_U32 DVP_KernelGraphManager(DVP_KernelNode_t *pSubNodes, DVP_U32 startNode, DVP_U32 numNodes, DVP_BOOL sync) +{ + DVP_PRINT(DVP_ZONE_KGM, "Entered "KGM_TAG" Kernel Manager! (%s)\n",(sync?"SYNC":"QUEUED")); + if (sync == DVP_FALSE) + { + DVP_KGM_Thread_t kgmt = {pSubNodes, startNode, numNodes, 0}; + if (queue_write(workqueue, true_e, &kgmt) == true_e) // this is internally a copy + { + do { + DVP_KGM_Thread_t kgmr; + + if (queue_read(retqueue, true_e, &kgmr) == true_e) + { + if (kgmt.pSubNodes == kgmr.pSubNodes && + kgmt.startNode == kgmr.startNode && + kgmt.numNodes == kgmr.numNodes) // this is ours, return. + { + DVP_PRINT(DVP_ZONE_KGM, "Work Thread returned %u nodes!\n", kgmr.numNodesExecuted); + return kgmr.numNodesExecuted; + } + else // it's not ours, put it back in the queue + queue_write(retqueue, true_e, &kgmr); + } + else + break; + } while (1); + } + return 0; + } + else + { + return DVP_KernelGraphManager_CPU(pSubNodes, startNode, numNodes); + } +} + + +#if defined(SYSBIOS_SL) +static static_function_t dvp_kgm_functions[] = { + {"DVP_KernelGraphManagerInit", (function_f)DVP_KernelGraphManagerInit}, + {"DVP_KernelGraphManager", (function_f)DVP_KernelGraphManager}, + {"DVP_GetSupportedKernels", (function_f)DVP_GetSupportedKernels}, + {"DVP_GetSupportedLocalCalls", (function_f)DVP_GetSupportedLocalCalls}, + {"DVP_GetSupportedRemoteCalls", (function_f)DVP_GetSupportedRemoteCalls}, + {"DVP_GetSupportedRemoteCore", (function_f)DVP_GetSupportedRemoteCore}, + {"DVP_GetMaximumLoad", (function_f)DVP_GetMaximumLoad}, + {"DVP_KernelGraphManagerDenit", (function_f)DVP_KernelGraphManagerDeinit}, +}; + +static_module_table_t dvp_kgm_cpu_table = { + "dvp_kgm_cpu", + dimof(dvp_kgm_functions), + dvp_kgm_functions +}; +#endif + +void gamma_apply(DVP_Image_t *input, DVP_Image_t *output, DVP_U08* gammaLut) +{ + DVP_U08 *in, *out; + DVP_U32 width, height; + uint32_t i,j,indx,start_in_pixel = 0, start_out_pixel = 0,cur_in_pixel, cur_out_pixel; + + if (gammaLut == NULL) + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to apply gamma mapping: invalid LUT.\n"); + return; + } + + if (input == NULL || output == NULL) + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to apply gamma mapping: invalid input and/or output images.\n"); + return; + } + + in = input->pData[0]; + out = output->pData[0]; + + width = input->width; + height = input->height; + + + if (width != output->width || height != output->height) + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to apply gamma mapping: input and output images must have the same dimensions.\n"); + return; + } + + for ( + i = 0; + i < height; + i++, start_in_pixel += input->y_stride, start_out_pixel += output->y_stride + ) + { + cur_in_pixel = start_in_pixel; + cur_out_pixel = start_out_pixel; + for ( + j = 0; + j < width; + j++, cur_in_pixel += input->x_stride, cur_out_pixel += output->x_stride + ) + { + indx = in[cur_in_pixel]; + out[cur_out_pixel] = gammaLut[indx]; + } + } +} diff --git a/source/dvp/dvp_kgm_cpu/dvp_ll.c b/source/dvp/dvp_kgm_cpu/dvp_ll.c new file mode 100644 index 0000000..5b3e1ce --- /dev/null +++ b/source/dvp/dvp_kgm_cpu/dvp_ll.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#ifdef DVP_USE_IMGFILTER +#include +#endif + +void DVP_imgFilter(DVP_Image_t *pLuma, + DVP_ImageFilter_e type, + DVP_Image_t *pOut) +{ + int limit = 255; +#ifdef DVP_USE_IMGFILTER + if (type == DVP_IMGFILTER_SOBEL) + { + int sobel_3[3] = {1,2,1}; + int range = SOBEL_RANGE; + __planar_edge_filter_3x3(pLuma->width, + pLuma->height, + pLuma->pData[0], + pLuma->y_stride, + sobel_3, + pOut->pData[0], + pOut->y_stride, + range, limit); + } + else if (type == DVP_IMGFILTER_SCHARR) + { + int scharr_3[3] = {3,10,3}; + int range = SCHARR_RANGE; + __planar_edge_filter_3x3(pLuma->width, + pLuma->height, + pLuma->pData[0], + pLuma->y_stride, + scharr_3, + pOut->pData[0], + pOut->y_stride, + range, limit); + } + else if (type == DVP_IMGFILTER_KROON) + { + int kroon_3[3] = {17,61,17}; + int range = KROON_RANGE; + __planar_edge_filter_3x3(pLuma->width, + pLuma->height, + pLuma->pData[0], + pLuma->y_stride, + kroon_3, + pOut->pData[0], + pOut->y_stride, + range, limit); + } + else if (type == DVP_IMGFILTER_PREWITT) + { + int prewitt_3[3] = {1,1,1}; + int range = PREWITT_RANGE; + __planar_edge_filter_3x3(pLuma->width, + pLuma->height, + pLuma->pData[0], + pLuma->y_stride, + prewitt_3, + pOut->pData[0], + pOut->y_stride, + range, limit); + } +#endif +} + diff --git a/source/dvp/dvp_kgm_cpu/dvp_ll.h b/source/dvp/dvp_kgm_cpu/dvp_ll.h new file mode 100644 index 0000000..2588f9c --- /dev/null +++ b/source/dvp/dvp_kgm_cpu/dvp_ll.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DVP_LL_H_ +#define _DVP_LL_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum _dvp_imgfilter_e { + DVP_IMGFILTER_SOBEL, + DVP_IMGFILTER_SCHARR, + DVP_IMGFILTER_KROON, + DVP_IMGFILTER_PREWITT, +} DVP_ImageFilter_e; + +void DVP_imgFilter(DVP_Image_t *pLuma, DVP_ImageFilter_e type, DVP_Image_t *pO); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/source/dvp/dvp_kgm_dsp/Android.mk b/source/dvp/dvp_kgm_dsp/Android.mk new file mode 100644 index 0000000..3fe3de5 --- /dev/null +++ b/source/dvp/dvp_kgm_dsp/Android.mk @@ -0,0 +1,26 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH:=$(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(DVP_DEBUGGING) $(DVP_CFLAGS) $(DVP_FEATURES) +LOCAL_SRC_FILES := dvp_kgm_dsp.c +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_MODULE := libdvp_kgm_dsp +LOCAL_SHARED_LIBRARIES := libdvp $(DVP_SYSLIBS) libcutils +include $(BUILD_SHARED_LIBRARY) + diff --git a/source/dvp/dvp_kgm_dsp/concerto.mak b/source/dvp/dvp_kgm_dsp/concerto.mak new file mode 100644 index 0000000..de4237a --- /dev/null +++ b/source/dvp/dvp_kgm_dsp/concerto.mak @@ -0,0 +1,36 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_CPU),ARM) + +include $(PRELUDE) +TARGET=dvp_kgm_dsp +TARGETTYPE=dsmo +CSOURCES=dvp_kgm_dsp.c +DEFFILE=dvp_kgm.def +DEFS+=$(DVP_FEATURES) +IDIRS+=$(DVP_INC) $(IPC_INC) $(TILER_INC) $(DVP_INT_INC) +SHARED_LIBS+=dvp +ifeq ($(TARGET_OS),LINUX) + ifeq ($(TARGET_CPU), ARM) + SYS_SHARED_LIBS+=$(IPC_LIBS) $(TILER_LIB) + endif +else ifeq ($(TARGET_OS),__QNX__) + SYS_SHARED_LIBS+=syslink_client memmgr +endif + +include $(FINALE) + +endif + diff --git a/source/dvp/dvp_kgm_dsp/dvp_kgm.def b/source/dvp/dvp_kgm_dsp/dvp_kgm.def new file mode 100644 index 0000000..2b33339 --- /dev/null +++ b/source/dvp/dvp_kgm_dsp/dvp_kgm.def @@ -0,0 +1,10 @@ +LIBRARY "dvp_kgm_dsp.dll" +EXPORTS + DVP_KernelGraphManagerInit + DVP_GetSupportedKernels + DVP_GetSupportedLocalCalls + DVP_GetSupportedRemoteCalls + DVP_GetSupportedRemoteCore + DVP_KernelGraphManager + DVP_KernelGraphManagerDeinit + DVP_GetMaximumLoad diff --git a/source/dvp/dvp_kgm_dsp/dvp_kgm_dsp.c b/source/dvp/dvp_kgm_dsp/dvp_kgm_dsp.c new file mode 100644 index 0000000..ea8e4b8 --- /dev/null +++ b/source/dvp/dvp_kgm_dsp/dvp_kgm_dsp.c @@ -0,0 +1,2538 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#if defined(DVP_USE_VLIB) +#include +#endif + +#if defined(DVP_USE_IMGLIB) +#include +#endif + +#if defined(DVP_USE_TISMO) +#include +#endif + +#if defined(DVP_USE_RVM) +#include +#endif + +#if defined(DVP_USE_ORB) +#include +#endif + +#if defined(DVP_USE_DSPLIB) +#include +#endif + +#if defined(DVP_USE_DEI) +#include +#endif + +#define KGM_TAG "DVP KGM DSP" + +static DVP_CoreFunction_t remote_kernels[] = { +#ifdef DVP_USE_IPC + {"c64t No operation", DVP_KN_NOOP, 0}, +#ifdef DVP_USE_VLIB + // name kernel priority, load + {"c64t EWRMeanS16", DVP_KN_VLIB_EWR_MEAN_S16, 0}, + {"c64t EWRVarS16", DVP_KN_VLIB_EWR_VAR_S16, 0}, + {"c64t EWRMeanS32", DVP_KN_VLIB_EWR_MEAN_S32, 0}, + {"c64t EWRVarS32", DVP_KN_VLIB_EWR_VAR_S32, 0}, + {"c64t UWRMeanS16", DVP_KN_VLIB_UWR_MEAN_S16, 0}, + {"c64t UWRVarS16", DVP_KN_VLIB_UWR_VAR_S16, 0}, + {"c64t BackSubS16", DVP_KN_VLIB_SUB_BACK_S16, 0}, + {"c64t BackSubS32", DVP_KN_VLIB_SUB_BACK_S32, 0}, + + {"c64t MixofGaussS16", DVP_KN_VLIB_MOG_S16, 0}, + {"c64t MixofGaussS32", DVP_KN_VLIB_MOG_S32, 0}, + + {"c64t ExtractBack16", DVP_KN_VLIB_EXTRACT_BACK_8_16, 0}, + + {"c64t PackMask32", DVP_KN_VLIB_PACK_MASK_32, 0}, + {"c64t UnPackMask32", DVP_KN_VLIB_UNPACK_MASK_32, 0}, + + // Generic Morph + {"c64t DilateCross", DVP_KN_DILATE_CROSS, 0}, + {"c64t DilateMask", DVP_KN_DILATE_MASK, 0}, + {"c64t DilateSquare", DVP_KN_DILATE_SQUARE, 0}, + {"c64t ErodeCross", DVP_KN_ERODE_CROSS, 0}, + {"c64t ErodeMask", DVP_KN_ERODE_MASK, 0}, + {"c64t ErodeSquare", DVP_KN_ERODE_SQUARE, 0}, + + {"c64t DilateCross", DVP_KN_VLIB_DILATE_CROSS, 0}, + {"c64t DilateMask", DVP_KN_VLIB_DILATE_MASK, 0}, + {"c64t DilateSquare", DVP_KN_VLIB_DILATE_SQUARE, 0}, + {"c64t ErodeCross", DVP_KN_VLIB_ERODE_CROSS, 0}, + {"c64t ErodeMask", DVP_KN_VLIB_ERODE_MASK, 0}, + {"c64t ErodeSquare", DVP_KN_VLIB_ERODE_SQUARE, 0}, + {"c64t Erode1Pixel", DVP_KN_VLIB_ERODE_SINGLEPIXEL, 0}, + + {"c64t ConnectedComponent", DVP_KN_VLIB_CCL, 0}, + + {"c64t Canny2DGradient", DVP_KN_CANNY_2D_GRADIENT, 0}, + {"c64t CannyNonmaxSupress", DVP_KN_CANNY_NONMAX_SUPPRESSION, 0}, +// {"c64t CannyHystThresh", DVP_KN_CANNY_HYST_THRESHHOLD, 0}, + + {"c64t Canny2DGradient", DVP_KN_VLIB_CANNY_2D_GRADIENT, 0}, + {"c64t CannyNonmaxSupress", DVP_KN_VLIB_CANNY_NONMAX_SUPPRESSION, 0}, +// {"c64t CannyHystThresh", DVP_KN_VLIB_CANNY_HYST_THRESHHOLD, 0}, + {"c64t HystThresh", DVP_KN_VLIB_HYST_THRESHOLD, 0}, + + {"c64t ImgPyramid8", DVP_KN_VLIB_IMAGE_PYRAMID_8, 0}, + {"c64t ImgPyramid16", DVP_KN_VLIB_IMAGE_PYRAMID_16, 0}, + + {"c64t Gauss5x5Pyramid8", DVP_KN_VLIB_GAUSSIAN_5x5_PYRAMID_8, 0}, + {"c64t Gauss5x5Pyramid16", DVP_KN_VLIB_GAUSSIAN_5x5_PYRAMID_16, 0}, + + {"c64t GradientH5x5Pyramid8", DVP_KN_VLIB_GRADIENT_H5x5_PYRAMID_8, 0}, + {"c64t GradientV5x5Pyramid8", DVP_KN_VLIB_GRADIENT_V5x5_PYRAMID_8, 0}, + + {"c64t HarrisScore7x7", DVP_KN_VLIB_HARRIS_SCORE_7x7, 0}, + {"c64t Track Features Lucas 7x7", DVP_KN_VLIB_TRACK_FEATURES_LUCAS_7x7, 0}, + + {"c64t IIRHorz", DVP_KN_IIR_HORZ, 0}, + {"c64t IIRHorz", DVP_KN_VLIB_IIR_HORZ, 0}, + {"c64t IIRHorz16", DVP_KN_VLIB_IIR_HORZ_16, 0}, + {"c64t IIRVert", DVP_KN_IIR_VERT, 0}, + {"c64t IIRVert", DVP_KN_VLIB_IIR_VERT, 0}, + {"c64t IIRVert16", DVP_KN_VLIB_IIR_VERT_16, 0}, + {"c64t IntegralImg8", DVP_KN_INTEGRAL_IMAGE_8, 0}, + {"c64t IntegralImg8", DVP_KN_VLIB_INTEGRAL_IMAGE_8, 0}, + + {"c64t IntegralImg16", DVP_KN_VLIB_INTEGRAL_IMAGE_16, 0}, + + {"c64t HoughLine", DVP_KN_VLIB_HOUGH_LINE_FROM_LIST, 0}, + + {"c64t Nonmaxsupress3x316", DVP_KN_NONMAXSUPPRESS_3x3_S16, 0}, + {"c64t Nonmaxsupress5x516", DVP_KN_NONMAXSUPPRESS_5x5_S16, 0}, + {"c64t Nonmaxsupress7x716", DVP_KN_NONMAXSUPPRESS_7x7_S16, 0}, + + {"c64t Nonmaxsupress3x316", DVP_KN_VLIB_NONMAXSUPPRESS_3x3_S16, 0}, + {"c64t Nonmaxsupress5x516", DVP_KN_VLIB_NONMAXSUPPRESS_5x5_S16, 0}, + {"c64t Nonmaxsupress7x716", DVP_KN_VLIB_NONMAXSUPPRESS_7x7_S16, 0}, + + {"c64t NormalFlow", DVP_KN_VLIB_NORMALFLOW_16, 0}, + {"c64t Kalman2x4", DVP_KN_VLIB_KALMAN_2x4, 0}, + {"c64t Kalman4x6", DVP_KN_VLIB_KALMAN_4x6, 0}, + {"c64t Nelder-MeadSimplex16", DVP_KN_VLIB_NEDLER_MEAD_SIMPLEX_16, 0}, + {"c64t Nelder-MeanSimplex3D", DVP_KN_VLIB_NEDLER_MEAD_SIMPLEX_3D, 0}, + {"c64t LegendreMoments", DVP_KN_VLIB_LEGENDRE_MOMENTS, 0}, + {"c64t InitHistgram8", DVP_KN_VLIB_INIT_HISTOGRAM_8, 0}, + {"c64t Histogram8", DVP_KN_VLIB_HISTOGRAM_8, 0}, + {"c64t WeightedHistogram8", DVP_KN_VLIB_WEIGHTED_HISTOGRAM_8, 0}, + {"c64t InitHistogram16", DVP_KN_VLIB_INIT_HISTOGRAM_16, 0}, + {"c64t Histogram16", DVP_KN_VLIB_HISTOGRAM_16, 0}, + {"c64t WeightedHistogram16", DVP_KN_VLIB_WEIGHTED_HISTOGRAM_16, 0}, + {"c64t HistogramnD16", DVP_KN_VLIB_HISTOGRAM_ND_16, 0}, + {"c64t BhattacharyyaDistance", DVP_KN_VLIB_BHATTACHAYA_DISTANCE, 0}, + {"c64t L1Distance", DVP_KN_VLIB_L1DISTANCE, 0}, + + {"c64t xYxY to LUMA", DVP_KN_XYXY_TO_Y800, 0}, + {"c64t UYVY to YUV420p", DVP_KN_UYVY_TO_YUV420p, 0}, + {"c64t UYVY to YUV422p", DVP_KN_UYVY_TO_YUV422p, 0}, + {"c64t UYVY to RGBp", DVP_KN_UYVY_TO_RGBp, 0}, + {"c64t UYVY to HSLp", DVP_KN_UYVY_TO_HSLp, 0}, + {"c64t UYVY to LABp", DVP_KN_UYVY_TO_LABp, 0}, + {"c64t YUV422p to UYVY", DVP_KN_YUV422p_TO_UYVY, 0}, + {"c64t NV12 to UYVY444p", DVP_KN_NV12_TO_YUV444p, 0}, + + {"c64t xYxY to LUMA", DVP_KN_VLIB_XYXY_TO_Y800, 0}, + {"c64t UYVY to YUV420p", DVP_KN_VLIB_UYVY_TO_YUV420p, 0}, + {"c64t UYVY to YUV422p", DVP_KN_VLIB_UYVY_TO_YUV422p, 0}, + {"c64t UYVY to RGBp", DVP_KN_VLIB_UYVY_TO_RGBp, 0}, + {"c64t UYVY to HSLp", DVP_KN_VLIB_UYVY_TO_HSLp, 0}, + {"c64t UYVY to LABp", DVP_KN_VLIB_UYVY_TO_LABp, 0}, + {"c64t YUV422p to UYVY", DVP_KN_VLIB_YUV422p_TO_UYVY, 0}, + + {"c64t Disparity8", DVP_KN_VLIB_DISPARITY_SAD8, 0}, + {"c64t Disparity16", DVP_KN_VLIB_DISPARITY_SAD16, 0}, + {"c64t MeanLuma16", DVP_KN_VLIB_INIT_MEAN_LUMA_S16, 0}, + {"c64t MeanLuma32", DVP_KN_VLIB_INIT_MEAN_LUMA_S32, 0}, + {"c64t VarConst16", DVP_KN_VLIB_INIT_VAR_CONST_S16, 0}, + {"c64t VarConst32", DVP_KN_VLIB_INIT_VAR_CONST_S32, 0}, + {"c64t Legendre Moments Init", DVP_KN_VLIB_LEGENDRE_MOMENTS_INIT, 0}, + {"c64t HarrisScore7x7 32bit", DVP_KN_VLIB_HARRIS_SCORE_7x7_U32, 0}, + {"c64t Nonmaxsupress 32bit", DVP_KN_VLIB_NONMAXSUPPRESS_U32, 0}, +#endif +#ifdef DVP_USE_IMGLIB + {"c64t YUV420p to RGB565", DVP_KN_YUV422p_TO_RGB565, 0}, + {"c64t YUV420p to RGB565", DVP_KN_IMG_YUV422p_TO_RGB565, 0}, + + {"c64t Img Conv 3x3", DVP_KN_CONV_3x3, 0}, + {"c64t Img Conv 5x5", DVP_KN_CONV_5x5, 0}, + {"c64t Img Conv 7x7", DVP_KN_CONV_7x7, 0}, + + {"c64t Img Conv 3x3", DVP_KN_IMG_CONV_3x3, 0}, + {"c64t Img Conv 5x5", DVP_KN_IMG_CONV_5x5, 0}, + {"c64t Img Conv 7x7", DVP_KN_IMG_CONV_7x7, 0}, + {"c64t Img Conv 11x11", DVP_KN_IMG_CONV_11x11, 0}, + {"c64t Img Conv 5x5 i8 c16s", DVP_KN_IMG_CONV_5x5_I8_C16, 0}, + {"c64t Img Conv 7x7 i8 c16s", DVP_KN_IMG_CONV_7x7_I8_C16, 0}, + {"c64t Img Conv 3x3 i16s c16s", DVP_KN_IMG_CONV_3x3_I16s_C16, 0}, + {"c64t Img Conv 5x5 i16 c16s", DVP_KN_IMG_CONV_5x5_I16s_C16, 0}, + {"c64t Img Conv 7x7 i16 c16s", DVP_KN_IMG_CONV_7x7_I16s_C16, 0}, + {"c64t Img Conv 11x11 i16s c16s", DVP_KN_IMG_CONV_11x11_I16s_C16, 0}, + + {"c64t Img Thr gt2max8", DVP_KN_THR_GT2MAX_8, 0}, + {"c64t Img Thr gt2max16", DVP_KN_THR_GT2MAX_16, 0}, + {"c64t Img Thr gt2thr8", DVP_KN_THR_GT2THR_8, 0}, + {"c64t Img Thr gt2thr16", DVP_KN_THR_GT2THR_16, 0}, + {"c64t Img Thr le2min8", DVP_KN_THR_LE2MIN_8, 0}, + {"c64t Img Thr le2min16", DVP_KN_THR_LE2MIN_16, 0}, + {"c64t Img Thr le2thr8", DVP_KN_THR_LE2THR_8, 0}, + {"c64t Img Thr le2thr16", DVP_KN_THR_LE2THR_16, 0}, + {"c64t Img sobel 3x3_8", DVP_KN_SOBEL_3x3_8, 0}, + + {"c64t Img Thr gt2max8", DVP_KN_IMG_THR_GT2MAX_8, 0}, + {"c64t Img Thr gt2max16", DVP_KN_IMG_THR_GT2MAX_16, 0}, + {"c64t Img Thr gt2thr8", DVP_KN_IMG_THR_GT2THR_8, 0}, + {"c64t Img Thr gt2thr16", DVP_KN_IMG_THR_GT2THR_16, 0}, + {"c64t Img Thr le2min8", DVP_KN_IMG_THR_LE2MIN_8, 0}, + {"c64t Img Thr le2min16", DVP_KN_IMG_THR_LE2MIN_16, 0}, + {"c64t Img Thr le2thr8", DVP_KN_IMG_THR_LE2THR_8, 0}, + {"c64t Img Thr le2thr16", DVP_KN_IMG_THR_LE2THR_16, 0}, + {"c64t Img sobel 3x3_8", DVP_KN_IMG_SOBEL_3x3_8, 0}, + {"c64t Img sobel 3x3_16s", DVP_KN_IMG_SOBEL_3x3_16s, 0}, + {"c64t Img sobel 5x5_16s", DVP_KN_IMG_SOBEL_5x5_16s, 0}, + {"c64t Img sobel 5x5_16s", DVP_KN_IMG_SOBEL_7x7_16s, 0}, + {"c64t CannyImgSmooth", DVP_KN_CANNY_IMAGE_SMOOTHING, 0}, + {"c64t Img Clipping 16", DVP_KN_IMG_CLIPPING_16, 0}, + {"c64t Img Boundary8", DVP_KN_IMG_BOUNDARY_8, 0}, + {"c64t Img Boundary16s", DVP_KN_IMG_BOUNDARY_16s, 0}, + {"c64t Img Correlation 3x3", DVP_KN_IMG_CORR_3x3, 0}, + {"c64t Img Correlation 3x3 I8 C16s", DVP_KN_IMG_CORR_3x3_I8_C16s, 0}, + {"c64t Img Correlation 3x3 I16s C16s", DVP_KN_IMG_CORR_3x3_I16s_C16s, 0}, + {"c64t Img Correlation 5x5 I16s C16s", DVP_KN_IMG_CORR_5x5_I16s_C16s, 0}, + {"c64t Img Correlation 11x11 I8 C16s", DVP_KN_IMG_CORR_11x11_I8_C16s, 0}, + {"c64t Img Correlation 11x11 I16s C16s", DVP_KN_IMG_CORR_11x11_I16s_C16s, 0}, + {"c64t Img Correlation Gen I16 C16s", DVP_KN_IMG_CORR_GEN_I16s_C16s, 0}, + {"c64t Img Correlation Gen Iq", DVP_KN_IMG_CORR_GEN_IQ, 0}, + {"c64t Img Histogram8", DVP_KN_IMG_HISTOGRAM_8, 0}, + {"c64t Img Histogram16", DVP_KN_IMG_HISTOGRAM_16, 0}, + {"c64t Img Median 3x3 8", DVP_KN_IMG_MEDIAN_3x3_8, 0}, + {"c64t Img Median 3x3 16s", DVP_KN_IMG_MEDIAN_3x3_16s, 0}, + {"c64t Img Perimeter 8", DVP_KN_IMG_PERIMETER_8, 0}, + {"c64t Img Perimeter 16", DVP_KN_IMG_PERIMETER_16, 0}, + {"c64t Img Demux LE 8", DVP_KN_IMG_YC_DEMUX_LE16_8, 0}, + {"c64t Img Demux BE 8", DVP_KN_IMG_YC_DEMUX_BE16_8, 0}, + {"c64t Img Pix Sat ", DVP_KN_IMG_PIX_SAT, 0}, + {"c64t Img Pix Expand ", DVP_KN_IMG_PIX_EXPAND, 0}, + {"c64t Img SAD 3x3", DVP_KN_IMG_SAD_3x3, 0}, + {"c64t Img SAD 5x5", DVP_KN_IMG_SAD_5x5, 0}, + {"c64t Img SAD 7x7", DVP_KN_IMG_SAD_7x7, 0}, + {"c64t Img SAD 8x8", DVP_KN_IMG_SAD_8x8, 0}, + {"c64t Img SAD 16x16", DVP_KN_IMG_SAD_16x16, 0}, + {"c64t Img ErrDiff 8", DVP_KN_IMG_ERRDIFF_BIN_8, 0}, + {"c64t Img ErrDiff 16", DVP_KN_IMG_ERRDIFF_BIN_16, 0}, + {"c64t Img FDCT 8x8", DVP_KN_IMG_FDCT_8x8, 0}, + {"c64t Img IFDCT 8x8", DVP_KN_IMG_IDCT_8x8_12Q4, 0}, + {"c64t Img MAD 8x8", DVP_KN_IMG_MAD_8x8, 0}, + {"c64t Img MAD 16x16", DVP_KN_IMG_MAD_16x16, 0}, + {"c64t Img Quantization 16", DVP_KN_IMG_QUANTIZE_16, 0}, + {"c64t Img Wavelet Horz", DVP_KN_IMG_WAVE_HORZ, 0}, + +#endif +#ifdef DVP_USE_DSPLIB + {"c64t DSP Add 16 ", DVP_KN_DSP_ADD16, 0}, + {"c64t DSP Add 32 ", DVP_KN_DSP_ADD32, 0}, + {"c64t DSP Autocorrelation ", DVP_KN_DSP_AUTOCORR16, 0}, + {"c64t DSP Bit exp ", DVP_KN_DSP_BITEXP32, 0}, + {"c64t DSP Block swap 16 ", DVP_KN_DSP_BLKESWAP16, 0}, + {"c64t DSP Block swap 32 ", DVP_KN_DSP_BLKESWAP32, 0}, + {"c64t DSP Block swap 64 ", DVP_KN_DSP_BLKESWAP64, 0}, + {"c64t DSP Block move ", DVP_KN_DSP_BLKMOVE, 0}, + {"c64t DSP Dot product square ", DVP_KN_DSP_DOTPRODSQR, 0}, + {"c64t DSP Dot product ", DVP_KN_DSP_DOTPROD, 0}, + {"c64t DSP FFT 16x16 ", DVP_KN_DSP_FFT_16x16, 0}, + {"c64t DSP FFT 16x16R ", DVP_KN_DSP_FFT_16x16R, 0}, + {"c64t DSP FFT 16x16IMRE ", DVP_KN_DSP_FFT_16x16_IMRE, 0}, + {"c64t DSP FFT 16x32 ", DVP_KN_DSP_FFT_16x32, 0}, + {"c64t DSP FFT 32x32 ", DVP_KN_DSP_FFT_32x32, 0}, + {"c64t DSP FFT 32x32s ", DVP_KN_DSP_FFT_32x32s, 0}, + + {"c64t DSP FIR Complex ", DVP_KN_DSP_FIR_CPLX, 0}, + {"c64t DSP FIR HM Radix 4 ", DVP_KN_DSP_FIR_HM4x4, 0}, + {"c64t DSP FIR General", DVP_KN_DSP_FIR_GEN, 0}, + {"c64t DSP FIR HM17 Radix 8 ", DVP_KN_DSP_FIR_HM17_RA8x8, 0}, + {"c64t DSP FIR Adaptive LMS ", DVP_KN_DSP_FIR_LMS2, 0}, + {"c64t DSP FIR Radix 4 ", DVP_KN_DSP_FIR_R4, 0}, + {"c64t DSP FIR Radix 8", DVP_KN_DSP_FIR_R8, 0}, + {"c64t DSP FIR HM16 Radix 8 ", DVP_KN_DSP_FIR_HM16_RM8A8x8, 0}, + {"c64t DSP FIR Symmetric ", DVP_KN_DSP_FIR_SYM, 0}, + + {"c64t DSP IFFT 16x16 ", DVP_KN_DSP_IFFT_16x16, 0}, + {"c64t DSP IFFT 16x16 complex", DVP_KN_DSP_IFFT_16x16_IMRE, 0}, + {"c64t DSP IFFT 16x32 ", DVP_KN_DSP_IFFT_16x32, 0}, + {"c64t DSP IFFT 32x32 ", DVP_KN_DSP_IFFT_32x32, 0}, + + {"c64t DSP IIR ", DVP_KN_DSP_IIR, 0}, + {"c64t DSP IIR Lattice", DVP_KN_DSP_IIR_LAT, 0}, + {"c64t DSP IIR Single Point ", DVP_KN_DSP_IIR_SS, 0}, + + {"c64t DSP Lib MatrixMul ", DVP_KN_DSP_MUL, 0}, + {"c64t DSP Lib MatrixMul Complex", DVP_KN_DSP_MUL_CPLX, 0}, + {"c64t DSP Lib MatrixTranspose ", DVP_KN_DSP_MAT_TRANS, 0}, + {"c64t DSP Lib MaxIdx ", DVP_KN_DSP_MAXIDX, 0}, + {"c64t DSP Lib MaxVal ", DVP_KN_DSP_MAXVAL, 0}, + {"c64t DSP Lib MinVal ", DVP_KN_DSP_MINVAL, 0}, + {"c64t DSP Lib MInError ", DVP_KN_DSP_MINERROR, 0}, + {"c64t DSP Lib Mult32 ", DVP_KN_DSP_MUL32, 0}, + {"c64t DSP Lib Negate32 ", DVP_KN_DSP_NEG32, 0}, + {"c64t DSP Lib Reciprocal16 ", DVP_KN_DSP_RECIP16, 0}, + {"c64t DSP Lib SumofSquares ", DVP_KN_DSP_VECSUMSQ, 0}, + {"c64t DSP Lib WeightedVector ", DVP_KN_DSP_W_VEC, 0}, + + {"c64t DSP Lib FFT Twiddle16x16 ", DVP_KN_GEN_TWIDDLE_FFT_16X16, 0}, + {"c64t DSP Lib FFT Twiddle16x16 ", DVP_KN_GEN_TWIDDLE_FFT_16X16_IMRE, 0}, + {"c64t DSP Lib FFT Twiddle16x32 ", DVP_KN_GEN_TWIDDLE_FFT_16X32, 0}, + {"c64t DSP Lib FFT Twiddle 32x32 ", DVP_KN_GEN_TWIDDLE_FFT_32x32, 0}, + {"c64t DSP Lib IFFT Twiddle16x16 ", DVP_KN_GEN_TWIDDLE_IFFT_16X16, 0}, + {"c64t DSP Lib IFFT Twiddle16x16 ", DVP_KN_GEN_TWIDDLE_IFFT_16X16_IMRE, 0}, +#endif +#ifdef DVP_USE_TISMO + {"c64t TISMO", DVP_KN_TISMO_DISPARITY, 0}, +#endif +#ifdef DVP_USE_RVM + {"c64t RVM", DVP_KN_RVM, 0}, +#endif +#ifdef DVP_USE_ORB + {"c64t KN_ORB", DVP_KN_ORB, 0}, +#endif +#ifdef DVP_USE_DEI + {"c64t Deinterlacer", DVP_KN_DEI_DEINTERLACER, 0}, +#endif +#else //DVP_USE_IPC + {"c64t Echo", DVP_KN_ECHO, 0}, +#endif +}; +static DVP_U32 numRemoteKernels = dimof(remote_kernels); + +static DVP_Function_t remote_functions[] = { + {"DVP_SKEL_KernelGraphManagerInit", NULL, 0}, + {"DVP_SKEL_KernelGraphManagerDeinit", NULL, 0}, + {"DVP_SKEL_KernelGraphManager", NULL, 0}, +}; +static DVP_U32 numRemoteFunctions = dimof(remote_functions); + +DVP_U32 DVP_KernelGraphManagerCallback(DVP_U32 numArgs, DVP_U32 *args) +{ + numArgs = numArgs; // warnings + args = args; // warnings + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG": %u, %p\n", numArgs, args); + return 0; +} + +static DVP_Function_t local_functions[] = { + {"DVP_KernelGraphManagerCallback", DVP_KernelGraphManagerCallback, 0}, +}; +static DVP_U32 numLocalFunctions = dimof(local_functions); + +MODULE_EXPORT DVP_U32 DVP_GetSupportedKernels(DVP_CoreFunction_t **pFuncs) +{ + if (pFuncs != NULL) + *pFuncs = remote_kernels; + DVP_PRINT(DVP_ZONE_KGM, "Retreiving "KGM_TAG" Kernel Information!\n"); +#ifdef DVP_USE_IPC + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG" DVP_USE_IPC enabled!\n"); +#endif +#ifdef DVP_USE_VLIB + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG" DVP_USE_VLIB enabled!\n"); +#endif +#ifdef DVP_USE_RVM + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG" DVP_USE_RVM enabled!\n"); +#endif +#ifdef DVP_USE_TISMO + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG" DVP_USE_TISMO enabled!\n"); +#endif + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG" supports %u kernels\n", numRemoteKernels); + return numRemoteKernels; +} + +MODULE_EXPORT DVP_U32 DVP_GetSupportedRemoteCalls(DVP_Function_t **pRemote, DVP_U32 *pNum) +{ + *pRemote = remote_functions; + *pNum = numRemoteFunctions; + return 1; +} + +MODULE_EXPORT DVP_U32 DVP_GetSupportedLocalCalls(DVP_Function_t **pLocal, DVP_U32 *pNum) +{ + *pLocal = local_functions; + *pNum = numLocalFunctions; + return 1; +} + +MODULE_EXPORT DVP_Core_e DVP_GetSupportedRemoteCore() +{ + return DVP_CORE_DSP; +} + +MODULE_EXPORT DVP_U32 DVP_GetMaximumLoad(void) +{ +#if defined(TARGET_DVP_OMAP4) + return 466; // 466 Mhz +#else + return 0; +#endif +} + +static DVP_RPC_t *rpc; +//static DVP_RPC_Interface_t coreInterface; +static DVP_RPC_Core_t *core; +static thread_t worker; +static queue_t *workqueue; +static queue_t *retqueue; +static semaphore_t coreLock; +static DVP_Perf_t perf; +static DVP_RPC_Translation_t translations; + +static DVP_U32 DVP_KernelGraphManager_DSP(DVP_KernelNode_t *pNodes, DVP_U32 startNode, DVP_U32 numNodes) +{ + DVP_U32 processed = 0; + + // block multiple entry + semaphore_wait(&coreLock); + + if (pNodes) + { +#if defined(DVP_USE_OMAPRPC) + DVP_KernelNode_t *pTmp = pNodes; // temp var +#elif defined(DVP_USE_RCM) + DVP_KernelNode_t *pTmp = &pNodes[startNode]; // this will hold the translated address +#endif +#ifdef DVP_USE_IPC + DVP_U32 n = 0; + int status; + DVP_U32 size; + + DVP_PerformanceStart(&perf); + +#if defined(DVP_USE_RCM) + size = sizeof(DVP_KernelNode_t *); +#elif defined(DVP_USE_OMAPRPC) + size = (startNode+numNodes)*sizeof(DVP_KernelNode_t); +#endif + // @NOTE this implicitly sets the index variable to zero, which is correct in our situation. + memset(&translations, 0, sizeof(translations)); + + DVP_RPC_Parameter_t params[] = { + {DVP_RPC_READ_ONLY, size, (DVP_PTR)&pTmp, (DVP_PTR)dvp_rpc_get_handle(rpc, pTmp)}, +#if defined(DVP_USE_OMAPRPC) + {DVP_RPC_READ_ONLY, sizeof(DVP_U32), (DVP_PTR)&startNode, NULL}, +#endif + {DVP_RPC_READ_ONLY, sizeof(DVP_U32), (DVP_PTR)&numNodes, NULL}, + }; + + if (rpc == NULL || core == NULL) + { + DVP_PRINT(DVP_ZONE_ERROR, KGM_TAG": ERROR! Kernel Graph Manager for "KGM_TAG" is uninitialized!\n"); + goto leave; + } + + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG": Executing %u nodes on subgraph %p! Base %p start %u\n", numNodes, pTmp, pNodes, startNode); + + // for each node, translate all the pointers + for (n = startNode; n < (startNode + numNodes); n++) + { + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG": Translating Node[%u] Kernel %u\n", n, pNodes[n].header.kernel); + switch (pNodes[n].header.kernel) + { + case DVP_KN_NOOP: + { + break; + } +#ifdef DVP_USE_VLIB + case DVP_KN_XYXY_TO_Y800: // single planes + case DVP_KN_UYVY_TO_RGBp: // multiplane output + case DVP_KN_UYVY_TO_YUV420p: + case DVP_KN_UYVY_TO_YUV422p: + case DVP_KN_YUV422p_TO_UYVY: + case DVP_KN_NV12_TO_YUV444p: + case DVP_KN_INTEGRAL_IMAGE_8: + case DVP_KN_VLIB_XYXY_TO_Y800: + case DVP_KN_VLIB_UYVY_TO_RGBp: + case DVP_KN_VLIB_UYVY_TO_YUV420p: + case DVP_KN_VLIB_UYVY_TO_YUV422p: + case DVP_KN_VLIB_YUV422p_TO_UYVY: + case DVP_KN_VLIB_INTEGRAL_IMAGE_8: + case DVP_KN_VLIB_INTEGRAL_IMAGE_16: + case DVP_KN_VLIB_PACK_MASK_32: + case DVP_KN_VLIB_UNPACK_MASK_32: + case DVP_KN_VLIB_IMAGE_PYRAMID_8: + case DVP_KN_VLIB_IMAGE_PYRAMID_16: + case DVP_KN_VLIB_INIT_MEAN_LUMA_S16: + case DVP_KN_VLIB_INIT_MEAN_LUMA_S32: + case DVP_KN_VLIB_EXTRACT_BACK_8_16: + { + DVP_Transform_t *pIO = dvp_knode_to(&pNodes[n], DVP_Transform_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + DVP_PrintImage(DVP_ZONE_KGM, &pIO->input); + DVP_PrintImage(DVP_ZONE_KGM, &pIO->output); + break; + } + case DVP_KN_DILATE_CROSS: + case DVP_KN_DILATE_SQUARE: + case DVP_KN_DILATE_MASK: + case DVP_KN_ERODE_CROSS: + case DVP_KN_ERODE_MASK: + case DVP_KN_ERODE_SQUARE: + case DVP_KN_VLIB_DILATE_CROSS: + case DVP_KN_VLIB_DILATE_SQUARE: + case DVP_KN_VLIB_DILATE_MASK: + case DVP_KN_VLIB_ERODE_CROSS: + case DVP_KN_VLIB_ERODE_MASK: + case DVP_KN_VLIB_ERODE_SQUARE: + case DVP_KN_VLIB_ERODE_SINGLEPIXEL: + { + DVP_Morphology_t *pMorph = dvp_knode_to(&pNodes[n], DVP_Morphology_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pMorph->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pMorph->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + + DVP_PrintImage(DVP_ZONE_KGM, &pMorph->input); + DVP_PrintImage(DVP_ZONE_KGM, &pMorph->output); + + if (pNodes[n].header.kernel == DVP_KN_ERODE_MASK || + pNodes[n].header.kernel == DVP_KN_DILATE_MASK) + { + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pMorph->mask, DVP_TRUE, (DVP_PTR)pTmp, &translations); + DVP_PrintImage(DVP_ZONE_KGM, &pMorph->mask); + } + break; + } + case DVP_KN_IIR_HORZ: + case DVP_KN_IIR_VERT: + case DVP_KN_VLIB_IIR_HORZ: + case DVP_KN_VLIB_IIR_VERT: + case DVP_KN_VLIB_IIR_HORZ_16: + case DVP_KN_VLIB_IIR_VERT_16: + { + DVP_IIR_t *pIIR = dvp_knode_to(&pNodes[n], DVP_IIR_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIIR->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIIR->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIIR->scratch, DVP_FALSE, (DVP_PTR)pTmp, &translations); +#if !defined(__QNX__) /// @todo REMOVE: Temporary to avoid build error in QNX + if (pIIR->bounds[0].pData) + { +#if defined(DVP_USE_RCM) + DVP_COMPLAIN_IF_FALSE(dvp_rpc_flush(rpc, DVP_GetSupportedRemoteCore(), (DVP_PTR)pIIR->bounds[0].pData, pIIR->bounds[0].height*pIIR->bounds[0].width, DVP_MTYPE_MPUCACHED_VIRTUAL)); + pIIR->bounds[0].pData = dvp_rpc_mem_xlate_fwrd(rpc, DVP_GetSupportedRemoteCore(), pIIR->bounds[0].pData, pIIR->bounds[0].height*pIIR->bounds[0].width, DVP_MTYPE_MPUCACHED_VIRTUAL); +#else + translations.translations[translations.numTranslations].offset = (DVP_U32)&pIIR->bounds[0].pData - (DVP_U32)pTmp; + translations.translations[translations.numTranslations].base = (DVP_U32)pIIR->bounds[0].pData; + translations.translations[translations.numTranslations].cacheops = DVP_TRUE; + translations.translations[translations.numTranslations].reserved = (DVP_PTR)dvp_rpc_get_handle(rpc, pIIR->bounds[0].pData); + translations.numTranslations++; +#endif + } + if (pIIR->bounds[1].pData) + { +#if defined(DVP_USE_RCM) + DVP_COMPLAIN_IF_FALSE(dvp_rpc_flush(rpc, DVP_GetSupportedRemoteCore(), (DVP_PTR)pIIR->bounds[1].pData, pIIR->bounds[1].height*pIIR->bounds[1].width,DVP_MTYPE_MPUCACHED_VIRTUAL)); + pIIR->bounds[1].pData = dvp_rpc_mem_xlate_fwrd(rpc, DVP_GetSupportedRemoteCore(), pIIR->bounds[1].pData, pIIR->bounds[1].height*pIIR->bounds[1].width, DVP_MTYPE_MPUCACHED_VIRTUAL); +#else + translations.translations[translations.numTranslations].offset = (DVP_U32)&pIIR->bounds[1].pData - (DVP_U32)pTmp; + translations.translations[translations.numTranslations].base = (DVP_U32)pIIR->bounds[1].pData; + translations.translations[translations.numTranslations].cacheops = DVP_TRUE; + translations.translations[translations.numTranslations].reserved = (DVP_PTR)dvp_rpc_get_handle(rpc, pIIR->bounds[1].pData); + translations.numTranslations++; +#endif + } +#endif + DVP_PrintImage(DVP_ZONE_KGM, &pIIR->input); + DVP_PrintImage(DVP_ZONE_KGM, &pIIR->output); + DVP_PrintImage(DVP_ZONE_KGM, &pIIR->scratch); + break; + } + case DVP_KN_VLIB_CCL: + { + DVP_CCL_t *pCCL = dvp_knode_to(&pNodes[n], DVP_CCL_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pCCL->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pCCL->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + DVP_PrintImage(DVP_ZONE_KGM, &pCCL->input); + DVP_PrintImage(DVP_ZONE_KGM, &pCCL->output); + break; + } + case DVP_KN_CANNY_2D_GRADIENT: + case DVP_KN_VLIB_CANNY_2D_GRADIENT: + { + DVP_Canny2dGradient_t *pG = dvp_knode_to(&pNodes[n], DVP_Canny2dGradient_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pG->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pG->outGradX, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pG->outGradY, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pG->outMag, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_CANNY_NONMAX_SUPPRESSION: + case DVP_KN_VLIB_CANNY_NONMAX_SUPPRESSION: + { + DVP_CannyNonMaxSuppression_t *pCnonmax = dvp_knode_to(&pNodes[n], DVP_CannyNonMaxSuppression_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pCnonmax->inMag, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pCnonmax->inGradX, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pCnonmax->inGradY, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pCnonmax->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_GRADIENT_V5x5_PYRAMID_8: + case DVP_KN_VLIB_GRADIENT_H5x5_PYRAMID_8: + case DVP_KN_VLIB_GAUSSIAN_5x5_PYRAMID_8: + case DVP_KN_VLIB_GAUSSIAN_5x5_PYRAMID_16: + { + DVP_Gradient_t *pGrad = dvp_knode_to(&pNodes[n], DVP_Gradient_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pGrad->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pGrad->scratch, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pGrad->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_CANNY_HYST_THRESHHOLD: + case DVP_KN_VLIB_CANNY_HYST_THRESHHOLD: + case DVP_KN_VLIB_HYST_THRESHOLD: + { + DVP_CannyHystThresholding_t *pDth = dvp_knode_to(&pNodes[n], DVP_CannyHystThresholding_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->inMag, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->inEdgeMap, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_NONMAXSUPPRESS_3x3_S16: + case DVP_KN_NONMAXSUPPRESS_5x5_S16: + case DVP_KN_NONMAXSUPPRESS_7x7_S16: + case DVP_KN_VLIB_NONMAXSUPPRESS_3x3_S16: + case DVP_KN_VLIB_NONMAXSUPPRESS_5x5_S16: + case DVP_KN_VLIB_NONMAXSUPPRESS_7x7_S16: + { + DVP_Threshold_t *pNonmax = dvp_knode_to(&pNodes[n], DVP_Threshold_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pNonmax->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pNonmax->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + DVP_PrintImage(DVP_ZONE_KGM, &pNonmax->input); + DVP_PrintImage(DVP_ZONE_KGM, &pNonmax->output); + break; + } + case DVP_KN_VLIB_INIT_HISTOGRAM_8: + case DVP_KN_VLIB_INIT_HISTOGRAM_16: + { + DVP_Histogram_t *pH = dvp_knode_to(&pNodes[n], DVP_Histogram_t); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->edges, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->histArray, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_HISTOGRAM_8: + { + DVP_Histogram_t *pH = dvp_knode_to(&pNodes[n], DVP_Histogram_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pH->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->edges, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->histArray, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[0], DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[1], DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[2], DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->hOut, DVP_FALSE, (DVP_PTR)pTmp, &translations); + DVP_PrintImage(DVP_ZONE_KGM, &pH->input); + break; + } + case DVP_KN_VLIB_WEIGHTED_HISTOGRAM_8: + { + DVP_Histogram_t *pH = dvp_knode_to(&pNodes[n], DVP_Histogram_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pH->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->edges, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->histArray, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->binWeights, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[0], DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[1], DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[2], DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->hOut, DVP_FALSE, (DVP_PTR)pTmp, &translations); + DVP_PrintImage(DVP_ZONE_KGM, &pH->input); + break; + } + case DVP_KN_VLIB_HISTOGRAM_16: + { + DVP_Histogram_t *pH = dvp_knode_to(&pNodes[n], DVP_Histogram_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pH->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->edges, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->histArray, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[0], DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->hOut, DVP_FALSE, (DVP_PTR)pTmp, &translations); + DVP_PrintImage(DVP_ZONE_KGM, &pH->input); + break; + } + case DVP_KN_VLIB_WEIGHTED_HISTOGRAM_16: + { + DVP_Histogram_t *pH = dvp_knode_to(&pNodes[n], DVP_Histogram_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pH->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->edges, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->histArray, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->binWeights, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[0], DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->hOut, DVP_FALSE, (DVP_PTR)pTmp, &translations); + DVP_PrintImage(DVP_ZONE_KGM, &pH->input); + break; + } + case DVP_KN_VLIB_HISTOGRAM_ND_16: + { + DVP_Histogram_t *pH = dvp_knode_to(&pNodes[n], DVP_Histogram_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pH->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->numBinsArray, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[0], DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[1], DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[2], DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->hOut, DVP_FALSE, (DVP_PTR)pTmp, &translations); + DVP_PrintImage(DVP_ZONE_KGM, &pH->input); + break; + } + case DVP_KN_VLIB_BHATTACHAYA_DISTANCE: + case DVP_KN_VLIB_L1DISTANCE: + { + DVP_Distance_t *pDist = dvp_knode_to(&pNodes[n], DVP_Distance_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pDist->X, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pDist->Y, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_INIT_VAR_CONST_S16: + case DVP_KN_VLIB_INIT_VAR_CONST_S32: + { + DVP_ConstVar_t *pV = dvp_knode_to(&pNodes[n], DVP_ConstVar_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pV->var, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_DISPARITY_SAD8: + case DVP_KN_VLIB_DISPARITY_SAD16: + { + DVP_Disparity_t *pT = dvp_knode_to(&pNodes[n], DVP_Disparity_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pT->left, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pT->right, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pT->cost, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pT->mincost, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pT->disparity, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_SUB_BACK_S16: + case DVP_KN_VLIB_SUB_BACK_S32: + { + DVP_SubBackground_t *pSB = dvp_knode_to(&pNodes[n], DVP_SubBackground_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pSB->newestData, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pSB->currentMean, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pSB->currentVar, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pSB->output32packed, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_MOG_S16: + case DVP_KN_VLIB_MOG_S32: + { + DVP_Mog_t *pMOG = dvp_knode_to(&pNodes[n], DVP_Mog_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pMOG->image, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pMOG->wts, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pMOG->means, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pMOG->vars, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pMOG->compIndex, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pMOG->scratch, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pMOG->fgmask, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_NORMALFLOW_16: + { + DVP_NormalFlow_t *pNF = dvp_knode_to(&pNodes[n], DVP_NormalFlow_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pNF->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pNF->mag, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pNF->x, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pNF->y, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pNF->lut, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pNF->u, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pNF->v, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_NEDLER_MEAD_SIMPLEX_16: + case DVP_KN_VLIB_NEDLER_MEAD_SIMPLEX_3D: + { + DVP_Simplex_t *pS = dvp_knode_to(&pNodes[n], DVP_Simplex_t); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->start, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->step, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->stop, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->intBuf[0], DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->intBuf[1], DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->intBuf[2], DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->intBuf[3], DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->intBuf[4], DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->intBuf[5], DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_HARRIS_SCORE_7x7: + case DVP_KN_VLIB_HARRIS_SCORE_7x7_U32: + { + DVP_HarrisDSP_t *pHs = dvp_knode_to(&pNodes[n], DVP_HarrisDSP_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pHs->inGradX, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pHs->inGradY, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pHs->scratch, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pHs->harrisScore, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_TRACK_FEATURES_LUCAS_7x7: + { + DVP_TrackFeatures_t *pLk = dvp_knode_to(&pNodes[n], DVP_TrackFeatures_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pLk->im1, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pLk->im2, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pLk->gradx, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pLk->grady, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pLk->x, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pLk->y, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pLk->outx, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pLk->outy, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pLk->scratch, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_HOUGH_LINE_FROM_LIST: + { + DVP_HoughLine_t *pHl = dvp_knode_to(&pNodes[n], DVP_HoughLine_t); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pHl->pEdgeMapList, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pHl->pSIN, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pHl->pCOS, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pHl->ping, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pHl->pong, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pHl->pang, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pHl->peng, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pHl->pOutHoughSpace, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_EWR_MEAN_S16: + case DVP_KN_VLIB_EWR_MEAN_S32: + { + DVP_EMean_t *pEWR = dvp_knode_to(&pNodes[n], DVP_EMean_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pEWR->mean, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pEWR->data, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pEWR->mask, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_EWR_VAR_S16: + case DVP_KN_VLIB_EWR_VAR_S32: + { + DVP_EMean_t *pEWR = dvp_knode_to(&pNodes[n], DVP_EMean_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pEWR->var, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pEWR->mean, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pEWR->data, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pEWR->mask, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_UWR_MEAN_S16: + { + DVP_UMean_t *pUWR = dvp_knode_to(&pNodes[n], DVP_UMean_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->old_mean, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->new_data, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->old_data, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->new_mask, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->old_mask, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->new_mean, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_UWR_VAR_S16: + { + DVP_UMean_t *pUWR = dvp_knode_to(&pNodes[n], DVP_UMean_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->old_var, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->new_mean, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->old_mean, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->new_data, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->old_data, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->new_mask, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->old_mask, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->new_var, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_LEGENDRE_MOMENTS_INIT: + { + DVP_LegendreMoments_t *pLgm = dvp_knode_to(&pNodes[n], DVP_LegendreMoments_t); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pLgm->lPoly, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_LEGENDRE_MOMENTS: + { + DVP_LegendreMoments_t *pLgm = dvp_knode_to(&pNodes[n], DVP_LegendreMoments_t); + dvp_rpc_prepare_image(rpc, DVP_CORE_DSP, &pLgm->im, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pLgm->lPoly, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pLgm->lMoments, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_UYVY_TO_HSLp: // multiplane output + case DVP_KN_VLIB_UYVY_TO_HSLp: // multiplane output + { + DVP_Int2Pl_t *pLAB = dvp_knode_to(&pNodes[n], DVP_Int2Pl_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output1, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output2, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output3, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_UYVY_TO_LABp: + case DVP_KN_VLIB_UYVY_TO_LABp: + { + DVP_Int2Pl_t *pLAB = dvp_knode_to(&pNodes[n], DVP_Int2Pl_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output1, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output2, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output3, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pLAB->scratch, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_NONMAXSUPPRESS_U32: + { + DVP_Nonmax_NxN_t *pNonmax32 = dvp_knode_to(&pNodes[n], DVP_Nonmax_NxN_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pNonmax32->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pNonmax32->scratch, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pNonmax32->pixIndex, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } +#endif +#ifdef DVP_USE_TISMO + case DVP_KN_TISMO_DISPARITY: + { + DVP_Tismo_t *pT = dvp_knode_to(&pNodes[n], DVP_Tismo_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pT->left, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pT->right, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pT->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pT->invalid, DVP_FALSE, (DVP_PTR)pTmp, &translations); + DVP_PrintImage(DVP_ZONE_KGM, &pT->left); + DVP_PrintImage(DVP_ZONE_KGM, &pT->right); + DVP_PrintImage(DVP_ZONE_KGM, &pT->output); + DVP_PrintImage(DVP_ZONE_KGM, &pT->invalid); + break; + } +#endif +#ifdef DVP_USE_ORB + case DVP_KN_ORB: + { + DVP_Orb_t * pOrb = dvp_knode_to(&pNodes[n], DVP_Orb_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pOrb->inputImage, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pOrb->harrisImage, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pOrb->integralImage, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pOrb->orbPattern31, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pOrb->orbOutput.orbData, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pOrb->orbOutput.outImage, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } +#endif +#ifdef DVP_USE_DEI + case DVP_KN_DEI_DEINTERLACER: + { + DVP_Deinterlacer_t *pD = dvp_knode_to(&pNodes[n], DVP_Deinterlacer_t); + + if (pD->phy_virt_flag == 0) { + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pD->phy_fld_in_current, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pD->phy_fld_in_prev, DVP_TRUE, (DVP_PTR)pTmp, &translations); + } + + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pD->phy_luma_d0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pD->phy_luma_d1, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pD->phy_luma_d2, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } +#endif +#ifdef DVP_USE_RVM + case DVP_KN_RVM: + { + DVP_Rvm_t * pRvm = dvp_knode_to(&pNodes[n], DVP_Rvm_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pRvm->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pRvm->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pRvm->lut, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } +#endif +#ifdef DVP_USE_IMGLIB + case DVP_KN_IMG_BOUNDARY_8: + case DVP_KN_IMG_BOUNDARY_16s: + { + DVP_Boundary_t *pBoundary = dvp_knode_to(&pNodes[n], DVP_Boundary_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pBoundary->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pBoundary->outCoord, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pBoundary->outGray, DVP_FALSE, (DVP_PTR)pTmp, &translations); + DVP_PrintImage(DVP_ZONE_KGM, &pBoundary->input); + break; + } + case DVP_KN_YUV422p_TO_RGB565: + case DVP_KN_SOBEL_3x3_8: + case DVP_KN_IMG_YUV422p_TO_RGB565: + case DVP_KN_IMG_SOBEL_3x3_8: + case DVP_KN_IMG_SOBEL_3x3_16s: + case DVP_KN_IMG_SOBEL_5x5_16s: + case DVP_KN_IMG_SOBEL_7x7_16s: + case DVP_KN_IMG_PIX_SAT: + case DVP_KN_IMG_PIX_EXPAND: + case DVP_KN_IMG_PERIMETER_8: + case DVP_KN_IMG_PERIMETER_16: + case DVP_KN_IMG_MEDIAN_3x3_8: + case DVP_KN_IMG_MEDIAN_3x3_16s: + case DVP_KN_IMG_FDCT_8x8: + case DVP_KN_IMG_IDCT_8x8_12Q4: + { + DVP_Transform_t *pIO = dvp_knode_to(&pNodes[n], DVP_Transform_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + DVP_PrintImage(DVP_ZONE_KGM, &pIO->input); + DVP_PrintImage(DVP_ZONE_KGM, &pIO->output); + break; + } + case DVP_KN_IMG_CLIPPING_16: + { + DVP_CannyHystThresholding_t *pDth = dvp_knode_to(&pNodes[n], DVP_CannyHystThresholding_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->inMag, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->inEdgeMap, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_IMG_HISTOGRAM_8: + case DVP_KN_IMG_HISTOGRAM_16: + { + DVP_Histogram_t *pH = dvp_knode_to(&pNodes[n], DVP_Histogram_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pH->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->histArray, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->hOut, DVP_FALSE, (DVP_PTR)pTmp, &translations); + DVP_PrintImage(DVP_ZONE_KGM, &pH->input); + break; + } + case DVP_KN_CANNY_IMAGE_SMOOTHING: + case DVP_KN_CONV_3x3: + case DVP_KN_CONV_5x5: + case DVP_KN_CONV_7x7: + case DVP_KN_IMG_CONV_3x3: + case DVP_KN_IMG_CONV_5x5: + case DVP_KN_IMG_CONV_7x7: + case DVP_KN_IMG_CONV_11x11: + case DVP_KN_IMG_CONV_3x3_I16s_C16: + case DVP_KN_IMG_CONV_7x7_I16s_C16: + case DVP_KN_IMG_CONV_11x11_I16s_C16: + { + DVP_ImageConvolution_t *pImg = dvp_knode_to(&pNodes[n], DVP_ImageConvolution_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->mask, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_IMG_SAD_3x3: + case DVP_KN_IMG_SAD_5x5: + case DVP_KN_IMG_SAD_7x7: + case DVP_KN_IMG_SAD_8x8: + case DVP_KN_IMG_SAD_16x16: + case DVP_KN_IMG_MAD_8x8: + case DVP_KN_IMG_MAD_16x16: + { + DVP_SAD_t *pImg = dvp_knode_to(&pNodes[n], DVP_SAD_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->refImg, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_IMG_CONV_5x5_I8_C16: + case DVP_KN_IMG_CONV_5x5_I16s_C16: + case DVP_KN_IMG_CONV_7x7_I8_C16: + { + DVP_ImageConvolution_with_buffer_t *pImg_buff = dvp_knode_to(&pNodes[n], DVP_ImageConvolution_with_buffer_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg_buff->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg_buff->mask, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pImg_buff->scratch, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg_buff->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_THR_GT2MAX_8: + case DVP_KN_THR_GT2MAX_16: + case DVP_KN_THR_GT2THR_8: + case DVP_KN_THR_GT2THR_16: + case DVP_KN_THR_LE2MIN_8: + case DVP_KN_THR_LE2MIN_16: + case DVP_KN_THR_LE2THR_8: + case DVP_KN_THR_LE2THR_16: + case DVP_KN_IMG_THR_GT2MAX_8: + case DVP_KN_IMG_THR_GT2MAX_16: + case DVP_KN_IMG_THR_GT2THR_8: + case DVP_KN_IMG_THR_GT2THR_16: + case DVP_KN_IMG_THR_LE2MIN_8: + case DVP_KN_IMG_THR_LE2MIN_16: + case DVP_KN_IMG_THR_LE2THR_8: + case DVP_KN_IMG_THR_LE2THR_16: + case DVP_KN_IMG_ERRDIFF_BIN_8: + case DVP_KN_IMG_ERRDIFF_BIN_16: + { + DVP_Threshold_t *pImg = dvp_knode_to(&pNodes[n], DVP_Threshold_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_IMG_YC_DEMUX_BE16_8: + case DVP_KN_IMG_YC_DEMUX_LE16_8: + { + DVP_Int2Pl_t *pLAB = dvp_knode_to(&pNodes[n], DVP_Int2Pl_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output1, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output2, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output3, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_IMG_CORR_3x3: + case DVP_KN_IMG_CORR_3x3_I8_C16s: + case DVP_KN_IMG_CORR_3x3_I16s_C16s: + case DVP_KN_IMG_CORR_5x5_I16s_C16s: + case DVP_KN_IMG_CORR_11x11_I8_C16s: + case DVP_KN_IMG_CORR_11x11_I16s_C16s: + case DVP_KN_IMG_CORR_GEN_I16s_C16s: + case DVP_KN_IMG_CORR_GEN_IQ: + { + DVP_ImageCorrelation_t *pCOR = dvp_knode_to(&pNodes[n], DVP_ImageCorrelation_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pCOR->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pCOR->mask, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pCOR->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_IMG_QUANTIZE_16: + { + DVP_ImageQuantization_t *pQnt = dvp_knode_to(&pNodes[n], DVP_ImageQuantization_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pQnt->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pQnt->recip_tbl, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_IMG_WAVE_HORZ: + { + DVP_ImageWavelet_t *pWv = dvp_knode_to(&pNodes[n], DVP_ImageWavelet_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pWv->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pWv->qmf, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pWv->mqmf, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pWv->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VLIB_KALMAN_2x4: + case DVP_KN_VLIB_KALMAN_4x6: + { + DVP_KalmanFilter_t *pKf = dvp_knode_to(&pNodes[n], DVP_KalmanFilter_t); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->inMeasurements, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->transition, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->errorCov, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->predictedErrorCov, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->state, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->predictedState, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->measurement, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->processNoiseCov, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->measurementNoiseCov, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->kalmanGain, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->temp1, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->temp2, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->temp3, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } +#endif +#ifdef DVP_USE_DSPLIB + case DVP_KN_DSP_ADD16: + case DVP_KN_DSP_ADD32: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input1, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_AUTOCORR16: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_BITEXP32: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_BLKESWAP16: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_BLKESWAP32: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_BLKESWAP64: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_BLKMOVE: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_DOTPRODSQR: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input1, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_DOTPROD: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input1, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_FFT_16x16: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_FFT_16x16R: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_FFT_16x16_IMRE: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_FFT_16x32: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_FFT_32x32: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_FFT_32x32s: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + + case DVP_KN_DSP_FIR_CPLX: + case DVP_KN_DSP_FIR_HM4x4: + case DVP_KN_DSP_FIR_GEN: + case DVP_KN_DSP_FIR_HM17_RA8x8: + case DVP_KN_DSP_FIR_R4: + case DVP_KN_DSP_FIR_R8: + case DVP_KN_DSP_FIR_HM16_RM8A8x8: + case DVP_KN_DSP_FIR_SYM: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_FIR_LMS2: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + + case DVP_KN_DSP_IFFT_16x16: + case DVP_KN_DSP_IFFT_16x16_IMRE: + case DVP_KN_DSP_IFFT_16x32: + case DVP_KN_DSP_IFFT_32x32: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + + case DVP_KN_DSP_IIR: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input1, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output1, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + + case DVP_KN_DSP_IIR_LAT: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input1, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + + case DVP_KN_DSP_IIR_SS: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input1, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + + case DVP_KN_DSP_MUL: + case DVP_KN_DSP_MUL_CPLX: + { + DVP_DSP_MatMul *pBuf = dvp_knode_to(&pNodes[n], DVP_DSP_MatMul); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input1, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_MAT_TRANS: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_MAXIDX: + case DVP_KN_DSP_MAXVAL: + case DVP_KN_DSP_MINVAL: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_MINERROR: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input1, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_MUL32: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input1, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_NEG32: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_RECIP16: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_VECSUMSQ: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_DSP_W_VEC: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input1, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + + case DVP_KN_GEN_TWIDDLE_FFT_16X16: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + + case DVP_KN_GEN_TWIDDLE_FFT_16X16_IMRE: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + + case DVP_KN_GEN_TWIDDLE_FFT_16X32: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + + case DVP_KN_GEN_TWIDDLE_FFT_32x32: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + + case DVP_KN_GEN_TWIDDLE_IFFT_16X16: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + + case DVP_KN_GEN_TWIDDLE_IFFT_16X16_IMRE: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_prepare_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } +#endif + default: + return 0; // other kernels are not supported. + break; + } + } + + +#if defined(DVP_USE_RCM) + // flush all the node data back to memory + DVP_COMPLAIN_IF_FALSE(dvp_rpc_flush(rpc, DVP_GetSupportedRemoteCore(), (DVP_PTR)&pNodes[startNode], numNodes * sizeof(DVP_KernelNode_t), DVP_MTYPE_KERNELGRAPH)); + + // now pTmp will be the translated value of the Node pointer on the remote core. + pTmp = dvp_rpc_mem_xlate_fwrd(rpc, DVP_GetSupportedRemoteCore(), pNodes, numNodes*sizeof(DVP_KernelNode_t), DVP_MTYPE_KERNELGRAPH); + + // now increment to the node to be executed + pTmp = &pTmp[startNode]; +#endif + // execute the remote functions + RPC_COMPLAIN_IF_FAILED(status,dvp_rpc_remote_execute(rpc, core, DVP_KGM_REMOTE_EXEC, params, dimof(params), &translations)); + if (status >= 0) + processed = status; // get the number of nodes from the "status". + +#if defined(DVP_USE_RCM) + // need to invalidate the kernel nodes, they may have been modified by the remote core (local data) + DVP_COMPLAIN_IF_FALSE(dvp_rpc_invalidate(rpc, DVP_GetSupportedRemoteCore(), (DVP_PTR)&pNodes[startNode], numNodes * sizeof(DVP_KernelNode_t), DVP_MTYPE_KERNELGRAPH)); +#endif + + // for each node, translate the node data back to local VM. + for (n = startNode; n < (startNode + numNodes); n++) + { + switch (pNodes[n].header.kernel) + { + case DVP_KN_NOOP: + { + break; + } +#ifdef DVP_USE_VLIB + case DVP_KN_XYXY_TO_Y800: // single planes + case DVP_KN_UYVY_TO_RGBp: // multiplane output + case DVP_KN_UYVY_TO_YUV420p: + case DVP_KN_UYVY_TO_YUV422p: + case DVP_KN_YUV422p_TO_UYVY: + case DVP_KN_NV12_TO_YUV444p: + case DVP_KN_INTEGRAL_IMAGE_8: + case DVP_KN_VLIB_XYXY_TO_Y800: + case DVP_KN_VLIB_UYVY_TO_RGBp: + case DVP_KN_VLIB_UYVY_TO_YUV420p: + case DVP_KN_VLIB_UYVY_TO_YUV422p: + case DVP_KN_VLIB_YUV422p_TO_UYVY: + case DVP_KN_VLIB_INTEGRAL_IMAGE_8: + case DVP_KN_VLIB_INTEGRAL_IMAGE_16: + case DVP_KN_VLIB_PACK_MASK_32: + case DVP_KN_VLIB_UNPACK_MASK_32: + case DVP_KN_VLIB_IMAGE_PYRAMID_8: + case DVP_KN_VLIB_IMAGE_PYRAMID_16: + case DVP_KN_VLIB_INIT_MEAN_LUMA_S16: + case DVP_KN_VLIB_INIT_MEAN_LUMA_S32: + case DVP_KN_VLIB_EXTRACT_BACK_8_16: + { + DVP_Transform_t *pIO = dvp_knode_to(&pNodes[n], DVP_Transform_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->output, DVP_TRUE); + break; + } + case DVP_KN_DILATE_CROSS: + case DVP_KN_DILATE_SQUARE: + case DVP_KN_DILATE_MASK: + case DVP_KN_ERODE_CROSS: + case DVP_KN_ERODE_MASK: + case DVP_KN_ERODE_SQUARE: + case DVP_KN_VLIB_DILATE_CROSS: + case DVP_KN_VLIB_DILATE_SQUARE: + case DVP_KN_VLIB_DILATE_MASK: + case DVP_KN_VLIB_ERODE_CROSS: + case DVP_KN_VLIB_ERODE_MASK: + case DVP_KN_VLIB_ERODE_SQUARE: + case DVP_KN_VLIB_ERODE_SINGLEPIXEL: + { + DVP_Morphology_t *pMorph = dvp_knode_to(&pNodes[n], DVP_Morphology_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pMorph->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pMorph->output, DVP_TRUE); + if (pNodes[n].header.kernel == DVP_KN_ERODE_MASK || + pNodes[n].header.kernel == DVP_KN_DILATE_MASK) + { + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pMorph->mask, DVP_FALSE); + } + break; + } + case DVP_KN_IIR_HORZ: + case DVP_KN_IIR_VERT: + case DVP_KN_VLIB_IIR_HORZ: + case DVP_KN_VLIB_IIR_VERT: + case DVP_KN_VLIB_IIR_HORZ_16: + case DVP_KN_VLIB_IIR_VERT_16: + { + DVP_IIR_t *pIIR = dvp_knode_to(&pNodes[n], DVP_IIR_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIIR->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIIR->output, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIIR->scratch, DVP_FALSE); + if (pIIR->bounds[0].pData) + pIIR->bounds[0].pData = dvp_rpc_mem_xlate_back(rpc, DVP_GetSupportedRemoteCore(), pIIR->bounds[0].pData, DVP_MTYPE_MPUCACHED_VIRTUAL); + if (pIIR->bounds[1].pData) + pIIR->bounds[1].pData = dvp_rpc_mem_xlate_back(rpc, DVP_GetSupportedRemoteCore(), pIIR->bounds[1].pData, DVP_MTYPE_MPUCACHED_VIRTUAL); + break; + } + case DVP_KN_VLIB_CCL: + { + DVP_CCL_t *pCCL = dvp_knode_to(&pNodes[n], DVP_CCL_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pCCL->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pCCL->output, DVP_TRUE); + break; + } + case DVP_KN_CANNY_2D_GRADIENT: + case DVP_KN_VLIB_CANNY_2D_GRADIENT: + { + DVP_Canny2dGradient_t *pG = dvp_knode_to(&pNodes[n], DVP_Canny2dGradient_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pG->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pG->outGradX, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pG->outGradY, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pG->outMag, DVP_TRUE); + break; + } + case DVP_KN_CANNY_NONMAX_SUPPRESSION: + case DVP_KN_VLIB_CANNY_NONMAX_SUPPRESSION: + { + DVP_CannyNonMaxSuppression_t *pCnonmax = dvp_knode_to(&pNodes[n], DVP_CannyNonMaxSuppression_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pCnonmax->inMag, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pCnonmax->inGradX, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pCnonmax->inGradY, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pCnonmax->output, DVP_TRUE); + break; + } + case DVP_KN_VLIB_GRADIENT_V5x5_PYRAMID_8: + case DVP_KN_VLIB_GRADIENT_H5x5_PYRAMID_8: + case DVP_KN_VLIB_GAUSSIAN_5x5_PYRAMID_8: + case DVP_KN_VLIB_GAUSSIAN_5x5_PYRAMID_16: + { + DVP_Gradient_t *pGrad = dvp_knode_to(&pNodes[n], DVP_Gradient_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pGrad->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pGrad->scratch, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pGrad->output, DVP_TRUE); + break; + } + case DVP_KN_CANNY_HYST_THRESHHOLD: + case DVP_KN_VLIB_CANNY_HYST_THRESHHOLD: + case DVP_KN_VLIB_HYST_THRESHOLD: + { + DVP_CannyHystThresholding_t *pDth = dvp_knode_to(&pNodes[n], DVP_CannyHystThresholding_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->inMag, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->inEdgeMap, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->output, DVP_TRUE); + break; + } + case DVP_KN_NONMAXSUPPRESS_3x3_S16: + case DVP_KN_NONMAXSUPPRESS_5x5_S16: + case DVP_KN_NONMAXSUPPRESS_7x7_S16: + case DVP_KN_VLIB_NONMAXSUPPRESS_3x3_S16: + case DVP_KN_VLIB_NONMAXSUPPRESS_5x5_S16: + case DVP_KN_VLIB_NONMAXSUPPRESS_7x7_S16: + { + DVP_Threshold_t *pNonmax = dvp_knode_to(&pNodes[n], DVP_Threshold_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pNonmax->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pNonmax->output, DVP_TRUE); + break; + } + case DVP_KN_VLIB_INIT_HISTOGRAM_8: + case DVP_KN_VLIB_INIT_HISTOGRAM_16: + { + DVP_Histogram_t *pH = dvp_knode_to(&pNodes[n], DVP_Histogram_t); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->edges, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->histArray, DVP_TRUE); + break; + } + case DVP_KN_VLIB_HISTOGRAM_8: + { + DVP_Histogram_t *pH = dvp_knode_to(&pNodes[n], DVP_Histogram_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pH->input, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->edges, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->histArray, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[0], DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[1], DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[2], DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->hOut, DVP_TRUE); + break; + } + case DVP_KN_VLIB_WEIGHTED_HISTOGRAM_8: + { + DVP_Histogram_t *pH = dvp_knode_to(&pNodes[n], DVP_Histogram_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pH->input, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->edges, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->histArray, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->binWeights, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[0], DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[1], DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[2], DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->hOut, DVP_TRUE); + break; + } + case DVP_KN_VLIB_HISTOGRAM_16: + { + DVP_Histogram_t *pH = dvp_knode_to(&pNodes[n], DVP_Histogram_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pH->input, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->edges, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->histArray, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[0], DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->hOut, DVP_TRUE); + break; + } + case DVP_KN_VLIB_WEIGHTED_HISTOGRAM_16: + { + DVP_Histogram_t *pH = dvp_knode_to(&pNodes[n], DVP_Histogram_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pH->input, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->edges, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->histArray, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->binWeights, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[0], DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->hOut, DVP_TRUE); + break; + } + case DVP_KN_VLIB_HISTOGRAM_ND_16: + { + DVP_Histogram_t *pH = dvp_knode_to(&pNodes[n], DVP_Histogram_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pH->input, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->numBinsArray, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[0], DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[1], DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->h[2], DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->hOut, DVP_TRUE); + DVP_PrintImage(DVP_ZONE_KGM, &pH->input); + break; + } + case DVP_KN_VLIB_BHATTACHAYA_DISTANCE: + { + DVP_Distance_t *pDist = dvp_knode_to(&pNodes[n], DVP_Distance_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pDist->X, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pDist->Y, DVP_FALSE); + break; + } + case DVP_KN_VLIB_L1DISTANCE: + { + DVP_Distance_t *pDist = dvp_knode_to(&pNodes[n], DVP_Distance_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pDist->X, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pDist->Y, DVP_FALSE); + break; + } + case DVP_KN_VLIB_INIT_VAR_CONST_S16: + case DVP_KN_VLIB_INIT_VAR_CONST_S32: + { + DVP_ConstVar_t *pV = dvp_knode_to(&pNodes[n], DVP_ConstVar_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pV->var, DVP_FALSE); + break; + } + case DVP_KN_VLIB_DISPARITY_SAD8: + case DVP_KN_VLIB_DISPARITY_SAD16: + { + DVP_Disparity_t *pT = dvp_knode_to(&pNodes[n], DVP_Disparity_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pT->left, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pT->right, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pT->cost, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pT->mincost, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pT->disparity, DVP_TRUE); + break; + } + case DVP_KN_VLIB_SUB_BACK_S16: + case DVP_KN_VLIB_SUB_BACK_S32: + { + DVP_SubBackground_t *pSB = dvp_knode_to(&pNodes[n], DVP_SubBackground_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pSB->newestData, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pSB->currentMean, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pSB->currentVar, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pSB->output32packed, DVP_TRUE); + break; + } + case DVP_KN_VLIB_MOG_S16: + case DVP_KN_VLIB_MOG_S32: + { + DVP_Mog_t *pMOG = dvp_knode_to(&pNodes[n], DVP_Mog_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pMOG->image, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pMOG->wts, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pMOG->means, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pMOG->vars, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pMOG->compIndex, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pMOG->scratch, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pMOG->fgmask, DVP_TRUE); + break; + } + case DVP_KN_VLIB_NORMALFLOW_16: + { + DVP_NormalFlow_t *pNF = dvp_knode_to(&pNodes[n], DVP_NormalFlow_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pNF->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pNF->mag, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pNF->x, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pNF->y, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pNF->lut, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pNF->u, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pNF->v, DVP_TRUE); + break; + } + case DVP_KN_VLIB_NEDLER_MEAD_SIMPLEX_16: + case DVP_KN_VLIB_NEDLER_MEAD_SIMPLEX_3D: + { + DVP_Simplex_t *pS = dvp_knode_to(&pNodes[n], DVP_Simplex_t); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->start, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->step, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->stop, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->intBuf[0], DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->intBuf[1], DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->intBuf[2], DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->intBuf[3], DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->intBuf[4], DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pS->intBuf[5], DVP_TRUE); + break; + } + case DVP_KN_VLIB_HARRIS_SCORE_7x7: + case DVP_KN_VLIB_HARRIS_SCORE_7x7_U32: + { + DVP_HarrisDSP_t *pHs = dvp_knode_to(&pNodes[n], DVP_HarrisDSP_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pHs->inGradX, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pHs->inGradY, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pHs->scratch, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pHs->harrisScore, DVP_TRUE); + break; + } + case DVP_KN_VLIB_TRACK_FEATURES_LUCAS_7x7: + { + DVP_TrackFeatures_t *pLk = dvp_knode_to(&pNodes[n], DVP_TrackFeatures_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pLk->im1, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pLk->im2, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pLk->gradx, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pLk->grady, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pLk->x, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pLk->y, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pLk->outx, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pLk->outy, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pLk->scratch, DVP_TRUE); + break; + } + case DVP_KN_VLIB_HOUGH_LINE_FROM_LIST: + { + DVP_HoughLine_t *pHl = dvp_knode_to(&pNodes[n], DVP_HoughLine_t); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pHl->pEdgeMapList, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pHl->pSIN, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pHl->pCOS, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pHl->ping, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pHl->pong, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pHl->pang, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pHl->peng, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pHl->pOutHoughSpace, DVP_TRUE); + break; + } + case DVP_KN_VLIB_EWR_MEAN_S16: + case DVP_KN_VLIB_EWR_MEAN_S32: + { + DVP_EMean_t *pEWR = dvp_knode_to(&pNodes[n], DVP_EMean_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pEWR->mean, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pEWR->data, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pEWR->mask, DVP_TRUE); + break; + } + case DVP_KN_VLIB_EWR_VAR_S16: + case DVP_KN_VLIB_EWR_VAR_S32: + { + DVP_EMean_t *pEWR = dvp_knode_to(&pNodes[n], DVP_EMean_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pEWR->var, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pEWR->mean, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pEWR->data, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pEWR->mask, DVP_TRUE); + break; + } + case DVP_KN_VLIB_UWR_MEAN_S16: + { + DVP_UMean_t *pUWR = dvp_knode_to(&pNodes[n], DVP_UMean_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->old_mean, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->new_data, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->old_data, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->new_mask, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->old_mask, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->new_mean, DVP_TRUE); + break; + } + case DVP_KN_VLIB_UWR_VAR_S16: + { + DVP_UMean_t *pUWR = dvp_knode_to(&pNodes[n], DVP_UMean_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->old_var, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->new_mean, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->old_mean, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->new_data, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->old_data, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->new_mask, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->old_mask, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pUWR->new_var, DVP_TRUE); + break; + } + case DVP_KN_VLIB_LEGENDRE_MOMENTS_INIT: + { + DVP_LegendreMoments_t *pLgm = dvp_knode_to(&pNodes[n], DVP_LegendreMoments_t); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pLgm->lPoly, DVP_FALSE); + break; + } + case DVP_KN_VLIB_LEGENDRE_MOMENTS: + { + DVP_LegendreMoments_t *pLgm = dvp_knode_to(&pNodes[n], DVP_LegendreMoments_t); + dvp_rpc_return_image(rpc, DVP_CORE_DSP, &pLgm->im, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pLgm->lPoly, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pLgm->lMoments, DVP_TRUE); + break; + } + case DVP_KN_UYVY_TO_HSLp: // multiplane output + case DVP_KN_VLIB_UYVY_TO_HSLp: + { + DVP_Int2Pl_t *pLAB = dvp_knode_to(&pNodes[n], DVP_Int2Pl_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output1, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output2, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output3, DVP_TRUE); + break; + } + case DVP_KN_UYVY_TO_LABp: + case DVP_KN_VLIB_UYVY_TO_LABp: + { + DVP_Int2Pl_t *pLAB = dvp_knode_to(&pNodes[n], DVP_Int2Pl_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output1, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output2, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output3, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pLAB->scratch, DVP_TRUE); + break; + } + case DVP_KN_VLIB_NONMAXSUPPRESS_U32: + { + DVP_Nonmax_NxN_t *pNonmax32 = dvp_knode_to(&pNodes[n], DVP_Nonmax_NxN_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pNonmax32->input, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pNonmax32->scratch, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pNonmax32->pixIndex, DVP_TRUE); + break; + } + +#endif +#ifdef DVP_USE_TISMO + case DVP_KN_TISMO_DISPARITY: + { + DVP_Tismo_t *pT = dvp_knode_to(&pNodes[n], DVP_Tismo_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pT->left, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pT->right, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pT->output, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pT->invalid, DVP_TRUE); + break; + } +#endif +#ifdef DVP_USE_ORB + case DVP_KN_ORB: + { + DVP_Orb_t * pOrb = dvp_knode_to(&pNodes[n], DVP_Orb_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pOrb->inputImage, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pOrb->harrisImage, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pOrb->integralImage, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pOrb->orbPattern31, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pOrb->orbOutput.orbData, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pOrb->orbOutput.outImage, DVP_TRUE); + break; + } +#endif +#ifdef DVP_USE_DEI + case DVP_KN_DEI_DEINTERLACER: + { + DVP_Deinterlacer_t *pD = dvp_knode_to(&pNodes[n], DVP_Deinterlacer_t); + + if (pD->phy_virt_flag == 0) { + dvp_rpc_return_image (rpc, DVP_GetSupportedRemoteCore(), &pD->phy_fld_in_current, DVP_TRUE); + dvp_rpc_return_image (rpc, DVP_GetSupportedRemoteCore(), &pD->phy_fld_in_prev, DVP_TRUE); + } + + dvp_rpc_return_buffer (rpc, DVP_GetSupportedRemoteCore(), &pD->phy_luma_d0, DVP_TRUE); + dvp_rpc_return_buffer (rpc, DVP_GetSupportedRemoteCore(), &pD->phy_luma_d1, DVP_TRUE); + dvp_rpc_return_buffer (rpc, DVP_GetSupportedRemoteCore(), &pD->phy_luma_d2, DVP_TRUE); + break; + } +#endif +#ifdef DVP_USE_RVM + case DVP_KN_RVM: + { + DVP_Rvm_t * pRvm = dvp_knode_to(&pNodes[n], DVP_Rvm_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pRvm->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pRvm->output, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pRvm->lut, DVP_FALSE); + break; + } +#endif +#ifdef DVP_USE_IMGLIB + case DVP_KN_IMG_BOUNDARY_8: + case DVP_KN_IMG_BOUNDARY_16s: + { + DVP_Boundary_t *pBoundary = dvp_knode_to(&pNodes[n], DVP_Boundary_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pBoundary->input, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pBoundary->outCoord, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pBoundary->outGray, DVP_TRUE); + break; + } + case DVP_KN_YUV422p_TO_RGB565: + case DVP_KN_SOBEL_3x3_8: + case DVP_KN_IMG_YUV422p_TO_RGB565: + case DVP_KN_IMG_SOBEL_3x3_8: + case DVP_KN_IMG_SOBEL_3x3_16s: + case DVP_KN_IMG_SOBEL_5x5_16s: + case DVP_KN_IMG_SOBEL_7x7_16s: + case DVP_KN_IMG_PIX_SAT: + case DVP_KN_IMG_PIX_EXPAND: + case DVP_KN_IMG_PERIMETER_8: + case DVP_KN_IMG_PERIMETER_16: + case DVP_KN_IMG_MEDIAN_3x3_8: + case DVP_KN_IMG_MEDIAN_3x3_16s: + case DVP_KN_IMG_FDCT_8x8: + case DVP_KN_IMG_IDCT_8x8_12Q4: + { + DVP_Transform_t *pIO = dvp_knode_to(&pNodes[n], DVP_Transform_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->output, DVP_TRUE); + break; + } + case DVP_KN_IMG_CLIPPING_16: + { + DVP_CannyHystThresholding_t *pDth = dvp_knode_to(&pNodes[n], DVP_CannyHystThresholding_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->inMag, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->inEdgeMap, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->output, DVP_TRUE); + break; + } + case DVP_KN_IMG_HISTOGRAM_8: + case DVP_KN_IMG_HISTOGRAM_16: + { + DVP_Histogram_t *pH = dvp_knode_to(&pNodes[n], DVP_Histogram_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pH->input, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->histArray, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pH->hOut, DVP_TRUE); + break; + } + case DVP_KN_CANNY_IMAGE_SMOOTHING: + case DVP_KN_CONV_3x3: + case DVP_KN_CONV_5x5: + case DVP_KN_CONV_7x7: + case DVP_KN_IMG_CONV_3x3: + case DVP_KN_IMG_CONV_5x5: + case DVP_KN_IMG_CONV_7x7: + case DVP_KN_IMG_CONV_11x11: + case DVP_KN_IMG_CONV_3x3_I16s_C16: + case DVP_KN_IMG_CONV_7x7_I16s_C16: + case DVP_KN_IMG_CONV_11x11_I16s_C16: + { + DVP_ImageConvolution_t *pImg = dvp_knode_to(&pNodes[n], DVP_ImageConvolution_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->output, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->mask, DVP_FALSE); + break; + } + case DVP_KN_IMG_SAD_3x3: + case DVP_KN_IMG_SAD_5x5: + case DVP_KN_IMG_SAD_7x7: + case DVP_KN_IMG_SAD_8x8: + case DVP_KN_IMG_SAD_16x16: + case DVP_KN_IMG_MAD_8x8: + case DVP_KN_IMG_MAD_16x16: + { + DVP_SAD_t *pImg = dvp_knode_to(&pNodes[n], DVP_SAD_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->output, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->refImg, DVP_FALSE); + break; + } + case DVP_KN_IMG_CONV_5x5_I8_C16: + case DVP_KN_IMG_CONV_5x5_I16s_C16: + case DVP_KN_IMG_CONV_7x7_I8_C16: + { + DVP_ImageConvolution_with_buffer_t *pImg_buff = dvp_knode_to(&pNodes[n], DVP_ImageConvolution_with_buffer_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg_buff->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg_buff->mask, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pImg_buff->scratch, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg_buff->output, DVP_TRUE); + break; + } + case DVP_KN_THR_GT2MAX_8: + case DVP_KN_THR_GT2MAX_16: + case DVP_KN_THR_GT2THR_8: + case DVP_KN_THR_GT2THR_16: + case DVP_KN_THR_LE2MIN_8: + case DVP_KN_THR_LE2MIN_16: + case DVP_KN_THR_LE2THR_8: + case DVP_KN_THR_LE2THR_16: + case DVP_KN_IMG_THR_GT2MAX_8: + case DVP_KN_IMG_THR_GT2MAX_16: + case DVP_KN_IMG_THR_GT2THR_8: + case DVP_KN_IMG_THR_GT2THR_16: + case DVP_KN_IMG_THR_LE2MIN_8: + case DVP_KN_IMG_THR_LE2MIN_16: + case DVP_KN_IMG_THR_LE2THR_8: + case DVP_KN_IMG_THR_LE2THR_16: + case DVP_KN_IMG_ERRDIFF_BIN_8: + case DVP_KN_IMG_ERRDIFF_BIN_16: + { + DVP_Threshold_t *pImg = dvp_knode_to(&pNodes[n], DVP_Threshold_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->output, DVP_TRUE); + break; + } + case DVP_KN_IMG_YC_DEMUX_BE16_8: + case DVP_KN_IMG_YC_DEMUX_LE16_8: + { + DVP_Int2Pl_t *pLAB = dvp_knode_to(&pNodes[n], DVP_Int2Pl_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output1, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output2, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pLAB->output3, DVP_TRUE); + break; + } + case DVP_KN_IMG_CORR_3x3: + case DVP_KN_IMG_CORR_3x3_I8_C16s: + case DVP_KN_IMG_CORR_3x3_I16s_C16s: + case DVP_KN_IMG_CORR_5x5_I16s_C16s: + case DVP_KN_IMG_CORR_11x11_I8_C16s: + case DVP_KN_IMG_CORR_11x11_I16s_C16s: + case DVP_KN_IMG_CORR_GEN_I16s_C16s: + case DVP_KN_IMG_CORR_GEN_IQ: + { + DVP_ImageCorrelation_t *pCOR = dvp_knode_to(&pNodes[n], DVP_ImageCorrelation_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pCOR->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pCOR->mask, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pCOR->output, DVP_TRUE); + break; + } + case DVP_KN_IMG_QUANTIZE_16: + { + DVP_ImageQuantization_t *pQnt = dvp_knode_to(&pNodes[n], DVP_ImageQuantization_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pQnt->input, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pQnt->recip_tbl, DVP_FALSE); + break; + } + case DVP_KN_IMG_WAVE_HORZ: + { + DVP_ImageWavelet_t *pWv = dvp_knode_to(&pNodes[n], DVP_ImageWavelet_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pWv->input, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pWv->qmf, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pWv->mqmf, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pWv->output, DVP_TRUE); + break; + } + case DVP_KN_VLIB_KALMAN_2x4: + case DVP_KN_VLIB_KALMAN_4x6: + { + DVP_KalmanFilter_t *pKf = dvp_knode_to(&pNodes[n], DVP_KalmanFilter_t); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->inMeasurements, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->transition, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->errorCov, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->predictedErrorCov, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->state, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->predictedState, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->measurement, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->processNoiseCov, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->measurementNoiseCov, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->kalmanGain, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->temp1, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->temp2, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pKf->temp3, DVP_TRUE); + break; + } +#endif + +#ifdef DVP_USE_DSPLIB + case DVP_KN_DSP_ADD16: + case DVP_KN_DSP_ADD32: + { + DVP_DSPFunc * pDSPData = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPData->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPData->input1, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPData->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_AUTOCORR16: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_BITEXP32: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_FALSE); + break; + } + case DVP_KN_DSP_BLKESWAP16: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_BLKESWAP32: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_BLKESWAP64: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_BLKMOVE: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_DOTPRODSQR: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->input1, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_DOTPROD: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->input1, DVP_FALSE); + break; + } + case DVP_KN_DSP_FFT_16x16: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_FFT_16x16R: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_FFT_16x16_IMRE: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_FFT_16x32: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_FFT_32x32: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_FFT_32x32s: + { + DVP_DSPFunc *pBuf = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->twoway, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pBuf->output0, DVP_TRUE); + break; + } + + case DVP_KN_DSP_MUL: + case DVP_KN_DSP_MUL_CPLX: + { + DVP_DSP_MatMul* pDSPMult = dvp_knode_to(&pNodes[n], DVP_DSP_MatMul); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPMult->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPMult->input1, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPMult->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_FIR_CPLX: + case DVP_KN_DSP_FIR_HM4x4: + case DVP_KN_DSP_FIR_GEN: + case DVP_KN_DSP_FIR_HM17_RA8x8: + case DVP_KN_DSP_FIR_R4: + case DVP_KN_DSP_FIR_R8: + case DVP_KN_DSP_FIR_HM16_RM8A8x8: + case DVP_KN_DSP_FIR_SYM: + { + DVP_DSPFunc* pDSPFIR = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPFIR->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPFIR->twoway, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPFIR->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_FIR_LMS2: + { + DVP_DSPFunc* pDSPFIR_LMS2 = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPFIR_LMS2->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPFIR_LMS2->twoway, DVP_FALSE); + break; + } + case DVP_KN_DSP_IFFT_16x16: + case DVP_KN_DSP_IFFT_16x16_IMRE: + case DVP_KN_DSP_IFFT_16x32: + case DVP_KN_DSP_IFFT_32x32: + { + DVP_DSPFunc* pDSPIIR = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPIIR->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPIIR->twoway, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPIIR->output0, DVP_TRUE); + break; + } + + case DVP_KN_DSP_IIR: + { + DVP_DSPFunc* pDSPIIR = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pDSPIIR->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pDSPIIR->input1, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pDSPIIR->twoway, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pDSPIIR->output0, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_CORE_DSP, &pDSPIIR->output1, DVP_TRUE); + break; + } + + case DVP_KN_DSP_IIR_LAT: + { + DVP_DSPFunc* pDSPIIR_LAT = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPIIR_LAT->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPIIR_LAT->input1, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPIIR_LAT->twoway, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPIIR_LAT->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_IIR_SS: + { + DVP_DSPFunc* pDSPIIR_SS = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPIIR_SS->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPIIR_SS->input1, DVP_FALSE); + break; + } + case DVP_KN_DSP_MAT_TRANS: + { + DVP_DSPFunc* pDSPMatTrans = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPMatTrans->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPMatTrans->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_MAXIDX: + case DVP_KN_DSP_MAXVAL: + case DVP_KN_DSP_MINVAL: + { + DVP_DSPFunc* pDSPMaxIdx = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPMaxIdx->input0, DVP_FALSE); + break; + } + case DVP_KN_DSP_MINERROR: + { + DVP_DSPFunc* pDSPMinError = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPMinError->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPMinError->input1, DVP_FALSE); + break; + } + case DVP_KN_DSP_MUL32: + { + DVP_DSPFunc* pDSPMult32 = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPMult32->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPMult32->input1, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPMult32->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_NEG32: + { + DVP_DSPFunc* pDSPNeg32 = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPNeg32->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPNeg32->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_RECIP16: + { + DVP_DSPFunc* pDSPRecip16 = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPRecip16->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPRecip16->twoway, DVP_TRUE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPRecip16->output0, DVP_TRUE); + break; + } + case DVP_KN_DSP_VECSUMSQ: + { + DVP_DSPFunc* pDSPVecSum = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPVecSum->input0, DVP_FALSE); + break; + } + case DVP_KN_DSP_W_VEC: + { + DVP_DSPFunc* pDSPW_Vec = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPW_Vec->input0, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPW_Vec->input1, DVP_FALSE); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPW_Vec->output0, DVP_TRUE); + break; + } + case DVP_KN_GEN_TWIDDLE_FFT_16X16: + { + DVP_DSPFunc* pDSPFFT16x16Twd = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPFFT16x16Twd->input0, DVP_FALSE); + break; + } + case DVP_KN_GEN_TWIDDLE_FFT_16X16_IMRE: + { + DVP_DSPFunc* pDSPFFT16x16Twd = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPFFT16x16Twd->input0, DVP_FALSE); + break; + } + case DVP_KN_GEN_TWIDDLE_FFT_16X32: + { + DVP_DSPFunc* pDSPFFT16x32Twd = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPFFT16x32Twd->input0, DVP_FALSE); + break; + } + case DVP_KN_GEN_TWIDDLE_FFT_32x32: + { + DVP_DSPFunc* pDSPFFT32x32Twd = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPFFT32x32Twd->input0, DVP_FALSE); + break; + } + case DVP_KN_GEN_TWIDDLE_IFFT_16X16: + { + DVP_DSPFunc* pDSPIFFT16x16Twd = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPIFFT16x16Twd->input0, DVP_FALSE); + break; + } + case DVP_KN_GEN_TWIDDLE_IFFT_16X16_IMRE: + { + DVP_DSPFunc* pDSPIFFT16x16Twd = dvp_knode_to(&pNodes[n], DVP_DSPFunc); + dvp_rpc_return_buffer(rpc, DVP_GetSupportedRemoteCore(), &pDSPIFFT16x16Twd->input0, DVP_FALSE); + break; + } +#endif + default: + goto leave; + } + } + + DVP_PerformanceStop(&perf); + +#endif // DVP_USE_IPC + + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG": Processed %u nodes!\n", processed); + } +leave: + semaphore_post(&coreLock); // allow other threads to enter + return processed; +} + +static thread_ret_t DVP_KernelGraphManagerThread_DSP(void *arg __attribute__((unused))) +{ + DVP_KGM_Thread_t kgmt; + + thread_nextaffinity(); + while (queue_read(workqueue, true_e, &kgmt) == true_e) + { + DVP_KernelNode_t *pSubNodes = kgmt.pSubNodes; + DVP_U32 startNode = kgmt.startNode; + DVP_U32 numNodes = kgmt.numNodes; + DVP_U32 processed = 0; + + processed = DVP_KernelGraphManager_DSP(pSubNodes, startNode, numNodes); + + kgmt.numNodesExecuted = processed; + queue_write(retqueue, true_e, &kgmt); + } + thread_exit(0); +} + +MODULE_EXPORT DVP_BOOL DVP_KernelGraphManagerDeinit(void) +{ + queue_pop(workqueue); + queue_pop(retqueue); + thread_join(worker); + queue_destroy(workqueue); + queue_destroy(retqueue); + semaphore_delete(&coreLock); + DVP_PerformancePrint(&perf, KGM_TAG); + +#ifdef DVP_USE_IPC + int status = 0; + DVP_PRINT(DVP_ZONE_KGM, "Destroying "KGM_TAG"\n"); + RPC_COMPLAIN_IF_FAILED(status,dvp_rpc_remote_execute(rpc, core, DVP_KGM_REMOTE_DEINIT, NULL, 0, NULL)); + core = NULL; + rpc = NULL; + if (status < 0) + return DVP_FALSE; + else + return DVP_TRUE; +#else + rpc = NULL; + core = NULL; + return DVP_TRUE; +#endif +} + +MODULE_EXPORT void DVP_KernelGraphManagerRestart(void *arg __attribute__((unused))) +{ + int status = 0; + DVP_U32 version = DVP_VERSION; + DVP_U16 width = 320; + DVP_U16 height = 240; + DVP_RPC_Parameter_t params[] = { + {DVP_RPC_READ_ONLY, sizeof(DVP_U16), &width, NULL}, + {DVP_RPC_READ_ONLY, sizeof(DVP_U16), &height, NULL}, + {DVP_RPC_READ_ONLY, sizeof(DVP_U32), &version, NULL}, + }; + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG" re-issuing init command to remote core.\n"); +#ifdef DVP_USE_IPC + RPC_COMPLAIN_IF_FAILED(status,dvp_rpc_remote_execute(rpc, core, DVP_KGM_REMOTE_INIT, params, dimof(params), NULL)); +#endif +} + +MODULE_EXPORT DVP_U32 DVP_KernelGraphManagerInit(DVP_RPC_t *pRPC, DVP_RPC_Core_t *pCore) +{ + if (rpc == NULL && core == NULL && pRPC != NULL && pCore != NULL) + { + int status; + DVP_U32 version = DVP_VERSION; + DVP_U16 width = 320; + DVP_U16 height = 240; + DVP_RPC_Parameter_t params[] = { + {DVP_RPC_READ_ONLY, sizeof(DVP_U16), &width, NULL}, + {DVP_RPC_READ_ONLY, sizeof(DVP_U16), &height, NULL}, + {DVP_RPC_READ_ONLY, sizeof(DVP_U32), &version, NULL}, + }; + rpc = pRPC; + core = pCore; +#ifdef DVP_USE_IPC + RPC_COMPLAIN_IF_FAILED(status,dvp_rpc_remote_execute(rpc, core, DVP_KGM_REMOTE_INIT, params, dimof(params), NULL)); + if (status < 0) + return DVP_FALSE; + else +#endif + { + DVP_Perf_Clear(&perf); + semaphore_create(&coreLock, 1, false_e); + workqueue = queue_create(10, sizeof(DVP_KGM_Thread_t)); + retqueue = queue_create(10, sizeof(DVP_KGM_Thread_t)); + worker = thread_create(DVP_KernelGraphManagerThread_DSP, NULL); + return DVP_TRUE; + } + } + else + return DVP_FALSE; +} + +MODULE_EXPORT DVP_U32 DVP_KernelGraphManager(DVP_KernelNode_t *pSubNodes, DVP_U32 startNode, DVP_U32 numNodes, DVP_BOOL sync) +{ + DVP_PRINT(DVP_ZONE_KGM, "Entered "KGM_TAG" Kernel Manager! (%s)\n",(sync?"SYNC":"QUEUED")); + if (sync == DVP_FALSE) + { + DVP_KGM_Thread_t kgmt = {pSubNodes, startNode, numNodes, 0}; + if (queue_write(workqueue, true_e, &kgmt) == true_e) // this is internally a copy + { + do { + DVP_KGM_Thread_t kgmr; + + if (queue_read(retqueue, true_e, &kgmr) == true_e) + { + if (kgmt.pSubNodes == kgmr.pSubNodes && + kgmt.startNode == kgmr.startNode && + kgmt.numNodes == kgmr.numNodes) // this is ours, return. + { + DVP_PRINT(DVP_ZONE_KGM, "Work Thread returned %u nodes!\n", kgmr.numNodesExecuted); + return kgmr.numNodesExecuted; + } + else // it's not ours, put it back in the queue + queue_write(retqueue, true_e, &kgmr); + } + else + break; + } while (1); + } + return 0; + } + else + { + return DVP_KernelGraphManager_DSP(pSubNodes, startNode, numNodes); + } +} + +#if defined(SYSBIOS_SL) +static static_function_t dvp_kgm_functions[] = { + {"DVP_KernelGraphManagerInit", (function_f)DVP_KernelGraphManagerInit}, + {"DVP_KernelGraphManager", (function_f)DVP_KernelGraphManager}, + {"DVP_GetSupportedKernels", (function_f)DVP_GetSupportedKernels}, + {"DVP_GetSupportedLocalCalls", (function_f)DVP_GetSupportedLocalCalls}, + {"DVP_GetSupportedRemoteCalls", (function_f)DVP_GetSupportedRemoteCalls}, + {"DVP_GetSupportedRemoteCore", (function_f)DVP_GetSupportedRemoteCore}, + {"DVP_GetMaximumLoad", (function_f)DVP_GetMaximumLoad}, + {"DVP_KernelGraphManagerDenit", (function_f)DVP_KernelGraphManagerDeinit}, +}; + +static_module_table_t dvp_kgm_dsp_table = { + "dvp_kgm_dsp", + dimof(dvp_kgm_functions), + dvp_kgm_functions +}; +#endif diff --git a/source/dvp/dvp_kgm_ocl/concerto.mak b/source/dvp/dvp_kgm_ocl/concerto.mak new file mode 100644 index 0000000..379bfc1 --- /dev/null +++ b/source/dvp/dvp_kgm_ocl/concerto.mak @@ -0,0 +1,35 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(CL_AVAILABLE),true) + +include $(PRELUDE) +TARGET=dvp_kgm_ocl +TARGETTYPE=dsmo +CSOURCES=$(call all-c-files) +DEFS += $(DVP_FEATURES) +IDIRS += $(DVP_INC) +STATIC_LIBS += ocl +SHARED_LIBS += dvp +ifeq ($(TARGET_OS),DARWIN) + LDFLAGS += -framework OpenCL +else ifeq ($(TARGET_PLATFORM),PANDA) + SYS_SHARED_LIBS += PVROCL +else + SYS_SHARED_LIBS += OpenCL +endif +include $(FINALE) + +endif + diff --git a/source/dvp/dvp_kgm_ocl/dvp_kgm_ocl.c b/source/dvp/dvp_kgm_ocl/dvp_kgm_ocl.c new file mode 100644 index 0000000..1f79dc2 --- /dev/null +++ b/source/dvp/dvp_kgm_ocl/dvp_kgm_ocl.c @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#include +#include + +#define KGM_TAG "DVP KGM OCL" + +static DVP_CoreFunction_t local_kernels[] = { + {"OCL SOBEL 8", DVP_KN_SOBEL_8, 0}, + {"OCL SCHARR 8", DVP_KN_SCHARR_8, 0}, + {"OCL PREWITT 8", DVP_KN_PREWITT_8, 0}, + {"OCL KROON 8", DVP_KN_KROON_8, 0}, + + {"OCL SOBEL 8", DVP_KN_OCL_SOBEL, 0}, + {"OCL SCHARR 8", DVP_KN_OCL_SCHARR, 0}, + {"OCL PREWITT 8", DVP_KN_OCL_PREWITT, 0}, + {"OCL KROON 8", DVP_KN_OCL_KROON, 0}, +}; +static DVP_U32 numLocalKernels = dimof(local_kernels); + +MODULE_EXPORT DVP_U32 DVP_GetSupportedKernels(DVP_CoreFunction_t **pFuncs) +{ + if (pFuncs != NULL) + *pFuncs = local_kernels; + DVP_PRINT(DVP_ZONE_KGM, "Retreiving "KGM_TAG" Kernel Information!\n"); + return numLocalKernels; +} + +MODULE_EXPORT DVP_U32 DVP_GetSupportedRemoteCalls(DVP_Function_t **pRemote, DVP_U32 *pNum) +{ + *pRemote = 0; + *pNum = 0; + return 0; +} + +MODULE_EXPORT DVP_U32 DVP_GetSupportedLocalCalls(DVP_Function_t **pLocal, DVP_U32 *pNum) +{ + *pLocal = 0; + *pNum = 0; + return 0; +} + +MODULE_EXPORT DVP_Core_e DVP_GetSupportedRemoteCore() +{ + return DVP_CORE_GPU; +} + +MODULE_EXPORT DVP_U32 DVP_GetMaximumLoad(void) +{ + return TARGET_NUM_CORES * 1000; +} + +static ocl_t *ocl = NULL; + +MODULE_EXPORT void DVP_KernelGraphManagerRestart(void *arg) +{ + // do nothing +} + +MODULE_EXPORT DVP_BOOL DVP_KernelGraphManagerDeinit(void) +{ + ocl_fini(ocl); + return DVP_TRUE; +} + +MODULE_EXPORT DVP_BOOL DVP_KernelGraphManagerInit(DVP_RPC_t *pRPC __attribute__ ((unused)), + DVP_RPC_Core_t *pCore __attribute__ ((unused))) +{ + ocl = ocl_init(); + return DVP_TRUE; +} + +MODULE_EXPORT DVP_U32 DVP_KernelGraphManager(DVP_KernelNode_t *pSubNodes, DVP_U32 startNode, DVP_U32 numNodes) +{ + DVP_U32 n,i = 0; + DVP_S32 processed = 0; + DVP_Perf_t *pPerf = NULL; + DVP_U32 kernel = 0; + DVP_Error_e err = DVP_SUCCESS; + + if (pSubNodes) + { + for (n = startNode; n < (startNode + numNodes); n++) + { +#ifdef DVP_DEBUG + for (i = 0; i < dimof(local_kernels); i++) + { + if (local_kernels[i].kernel == pSubNodes[n].header.kernel) { + DVP_PRINT(DVP_ZONE_KGM, "Executing Kernel %s\n",local_kernels[i].name); + } + } +#endif + // initialize the perf pointer and clock rate + pPerf = &pSubNodes[n].header.perf; + pPerf->rate = rtimer_freq(); // fill in the clock rate used to capture data. + DVP_PerformanceStart(pPerf); + + switch (pSubNodes[n].header.kernel) + { + case DVP_KN_SOBEL_8: + case DVP_KN_OCL_SOBEL: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + err = ocl_Sobel8(ocl, &pT->input, &pT->output); + break; + } + case DVP_KN_SCHARR_8: + case DVP_KN_OCL_SCHARR: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + err = ocl_Scharr8(ocl, &pT->input, &pT->output); + break; + } + case DVP_KN_PREWITT_8: + case DVP_KN_OCL_PREWITT: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + err = ocl_Prewitt8(ocl, &pT->input, &pT->output); + break; + } + case DVP_KN_KROON_8: + case DVP_KN_OCL_KROON: + { + DVP_Transform_t *pT = dvp_knode_to(&pSubNodes[n], DVP_Transform_t); + err = ocl_Kroon8(ocl, &pT->input, &pT->output); + break; + } + default: + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: "KGM_TAG" Unknown Kernel %u\n",kernel); + processed--; + break; + } + } + processed++; + DVP_PerformanceStop(pPerf); + } + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG": Processed %u nodes!\n", processed); + } + return processed; +} + + +#if defined(SYSBIOS_SL) +static static_function_t dvp_kgm_functions[] = { + {"DVP_KernelGraphManagerInit", (function_f)DVP_KernelGraphManagerInit}, + {"DVP_KernelGraphManager", (function_f)DVP_KernelGraphManager}, + {"DVP_GetSupportedKernels", (function_f)DVP_GetSupportedKernels}, + {"DVP_GetSupportedLocalCalls", (function_f)DVP_GetSupportedLocalCalls}, + {"DVP_GetSupportedRemoteCalls", (function_f)DVP_GetSupportedRemoteCalls}, + {"DVP_GetSupportedRemoteCore", (function_f)DVP_GetSupportedRemoteCore}, + {"DVP_GetMaximumLoad", (function_f)DVP_GetMaximumLoad}, + {"DVP_KernelGraphManagerDenit", (function_f)DVP_KernelGraphManagerDeinit}, +}; + +static_module_table_t dvp_kgm_ocl_table = { + "dvp_kgm_ocl", + dimof(dvp_kgm_functions), + dvp_kgm_functions +}; +#endif diff --git a/source/dvp/dvp_kgm_simcop/Android.mk b/source/dvp/dvp_kgm_simcop/Android.mk new file mode 100644 index 0000000..f482ba0 --- /dev/null +++ b/source/dvp/dvp_kgm_simcop/Android.mk @@ -0,0 +1,26 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH:=$(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(DVP_DEBUGGING) $(DVP_CFLAGS) $(DVP_FEATURES) +LOCAL_SRC_FILES := dvp_kgm_simcop.c +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_MODULE := libdvp_kgm_simcop +LOCAL_SHARED_LIBRARIES := libdvp $(DVP_SYSLIBS) libcutils +include $(BUILD_SHARED_LIBRARY) + diff --git a/source/dvp/dvp_kgm_simcop/concerto.mak b/source/dvp/dvp_kgm_simcop/concerto.mak new file mode 100644 index 0000000..81bc556 --- /dev/null +++ b/source/dvp/dvp_kgm_simcop/concerto.mak @@ -0,0 +1,29 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_CPU),ARM) + +include $(PRELUDE) +TARGET=dvp_kgm_simcop +TARGETTYPE=dsmo +CSOURCES=dvp_kgm_simcop.c +DEFFILE=dvp_kgm.def +DEFS+=$(DVP_FEATURES) +IDIRS+=$(DVP_INC) $(IPC_INC) $(MEM_INCS) $(DVP_INT_INC) +SHARED_LIBS+=dvp +SYS_SHARED_LIBS+=$(IPC_LIBS) $(MEM_LIBS) +include $(FINALE) + +endif + diff --git a/source/dvp/dvp_kgm_simcop/dvp_kgm.def b/source/dvp/dvp_kgm_simcop/dvp_kgm.def new file mode 100644 index 0000000..2fb4db1 --- /dev/null +++ b/source/dvp/dvp_kgm_simcop/dvp_kgm.def @@ -0,0 +1,11 @@ +LIBRARY "dvp_kgm_simcop.dll" +EXPORTS + DVP_KernelGraphManagerInit + DVP_GetSupportedKernels + DVP_GetSupportedLocalCalls + DVP_GetSupportedRemoteCalls + DVP_GetSupportedRemoteCore + DVP_KernelGraphManager + DVP_KernelGraphManagerDeinit + DVP_GetMaximumLoad + diff --git a/source/dvp/dvp_kgm_simcop/dvp_kgm_simcop.c b/source/dvp/dvp_kgm_simcop/dvp_kgm_simcop.c new file mode 100644 index 0000000..366a4af --- /dev/null +++ b/source/dvp/dvp_kgm_simcop/dvp_kgm_simcop.c @@ -0,0 +1,959 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#if defined(DVP_USE_VRUN) +#include +#endif + +#if defined(DVP_USE_DEI) +#include +#endif + +#define KGM_TAG "DVP KGM SIMCOP" + +static DVP_CoreFunction_t remote_kernels[] = { +#ifdef DVP_USE_IPC + {"SIMCOP No operation", DVP_KN_NOOP, 0}, +#ifdef DVP_USE_VRUN + // name kernel load + {"SIMCOP Dilate Cross", DVP_KN_DILATE_CROSS, 0}, + {"SIMCOP Dilate Mask", DVP_KN_DILATE_MASK, 0}, + {"SIMCOP Dilate Square", DVP_KN_DILATE_SQUARE, 0}, + {"SIMCOP Erode Cross", DVP_KN_ERODE_CROSS, 0}, + {"SIMCOP Erode Mask", DVP_KN_ERODE_MASK, 0}, + {"SIMCOP Erode Cross", DVP_KN_ERODE_SQUARE, 0}, + + {"SIMCOP Dilate Cross", DVP_KN_VRUN_DILATE_CROSS, 0}, + {"SIMCOP Dilate Mask", DVP_KN_VRUN_DILATE_MASK, 0}, + {"SIMCOP Dilate Square", DVP_KN_VRUN_DILATE_SQUARE, 0}, + {"SIMCOP Erode Cross", DVP_KN_VRUN_ERODE_CROSS, 0}, + {"SIMCOP Erode Mask", DVP_KN_VRUN_ERODE_MASK, 0}, + {"SIMCOP Erode Cross", DVP_KN_VRUN_ERODE_SQUARE, 0}, + + {"SIMCOP IIR Horz", DVP_KN_IIR_HORZ, 0}, + {"SIMCOP IIR Vert", DVP_KN_IIR_VERT, 0}, + + {"SIMCOP IIR Horz", DVP_KN_VRUN_IIR_HORZ, 0}, + {"SIMCOP IIR Vert", DVP_KN_VRUN_IIR_VERT, 0}, + + {"SIMCOP NonMax Sup 3x3", DVP_KN_NONMAXSUPPRESS_3x3_S16, 0}, + {"SIMCOP NonMax Sup 5x5", DVP_KN_NONMAXSUPPRESS_5x5_S16, 0}, + {"SIMCOP NonMax Sup 7x7", DVP_KN_NONMAXSUPPRESS_7x7_S16, 0}, + + {"SIMCOP NonMax Sup 3x3", DVP_KN_VRUN_NONMAXSUPPRESS_3x3_S16, 0}, + {"SIMCOP NonMax Sup 5x5", DVP_KN_VRUN_NONMAXSUPPRESS_5x5_S16, 0}, + {"SIMCOP NonMax Sup 7x7", DVP_KN_VRUN_NONMAXSUPPRESS_7x7_S16, 0}, + + {"SIMCOP Img Conv 3x3", DVP_KN_CONV_3x3, 0}, + {"SIMCOP Img Conv 5x5", DVP_KN_CONV_5x5, 0}, + {"SIMCOP Img Conv 7x7", DVP_KN_CONV_7x7, 0}, + + {"SIMCOP Img Conv 3x3", DVP_KN_VRUN_CONV_3x3, 0}, + {"SIMCOP Img Conv 5x5", DVP_KN_VRUN_CONV_5x5, 0}, + {"SIMCOP Img Conv 7x7", DVP_KN_VRUN_CONV_7x7, 0}, + {"SIMCOP Img Conv MxN", DVP_KN_VRUN_CONV_MxN, 0}, + + {"SIMCOP Img Thr gt2max8", DVP_KN_THR_GT2MAX_8, 0}, + {"SIMCOP Img Thr gt2max16", DVP_KN_THR_GT2MAX_16, 0}, + {"SIMCOP Img Thr gt2thr8", DVP_KN_THR_GT2THR_8, 0}, + {"SIMCOP Img Thr gt2thr16", DVP_KN_THR_GT2THR_16, 0}, + {"SIMCOP Img Thr le2min8", DVP_KN_THR_LE2MIN_8, 0}, + {"SIMCOP Img Thr le2min16", DVP_KN_THR_LE2MIN_16, 0}, + {"SIMCOP Img Thr le2thr8", DVP_KN_THR_LE2THR_8, 0}, + {"SIMCOP Img Thr le2thr16", DVP_KN_THR_LE2THR_16, 0}, + + {"SIMCOP Img Thr gt2max8", DVP_KN_VRUN_THR_GT2MAX_8, 0}, + {"SIMCOP Img Thr gt2max16", DVP_KN_VRUN_THR_GT2MAX_16, 0}, + {"SIMCOP Img Thr gt2thr8", DVP_KN_VRUN_THR_GT2THR_8, 0}, + {"SIMCOP Img Thr gt2thr16", DVP_KN_VRUN_THR_GT2THR_16, 0}, + {"SIMCOP Img Thr le2min8", DVP_KN_VRUN_THR_LE2MIN_8, 0}, + {"SIMCOP Img Thr le2min16", DVP_KN_VRUN_THR_LE2MIN_16, 0}, + {"SIMCOP Img Thr le2thr8", DVP_KN_VRUN_THR_LE2THR_8, 0}, + {"SIMCOP Img Thr le2thr16", DVP_KN_VRUN_THR_LE2THR_16, 0}, + + {"SIMCOP Img Sobel 3x3 8s", DVP_KN_SOBEL_3x3_8s, 0}, + {"SIMCOP Img Sobel 3x3 8", DVP_KN_SOBEL_3x3_8, 0}, + {"SIMCOP Img Sobel 3x3 16s", DVP_KN_SOBEL_3x3_16s, 0}, + {"SIMCOP Img Sobel 3x3 16", DVP_KN_SOBEL_3x3_16, 0}, + {"SIMCOP Img Sobel 5x5 8s", DVP_KN_SOBEL_5x5_8s, 0}, + {"SIMCOP Img Sobel 5x5 8", DVP_KN_SOBEL_5x5_8, 0}, + {"SIMCOP Img Sobel 5x5 16s", DVP_KN_SOBEL_5x5_16s, 0}, + {"SIMCOP Img Sobel 5x5 16", DVP_KN_SOBEL_5x5_16, 0}, + {"SIMCOP Img Sobel 7x7 8s", DVP_KN_SOBEL_7x7_8s, 0}, + {"SIMCOP Img Sobel 7x7 8", DVP_KN_SOBEL_7x7_8, 0}, + {"SIMCOP Img Sobel 7x7 16s", DVP_KN_SOBEL_7x7_16s, 0}, + {"SIMCOP Img Sobel 7x7 16", DVP_KN_SOBEL_7x7_16, 0}, + + {"SIMCOP Img Sobel 3x3 8s", DVP_KN_VRUN_SOBEL_3x3_8s, 0}, + {"SIMCOP Img Sobel 3x3 8", DVP_KN_VRUN_SOBEL_3x3_8, 0}, + {"SIMCOP Img Sobel 3x3 16s", DVP_KN_VRUN_SOBEL_3x3_16s, 0}, + {"SIMCOP Img Sobel 3x3 16", DVP_KN_VRUN_SOBEL_3x3_16, 0}, + {"SIMCOP Img Sobel 5x5 8s", DVP_KN_VRUN_SOBEL_5x5_8s, 0}, + {"SIMCOP Img Sobel 5x5 8", DVP_KN_VRUN_SOBEL_5x5_8, 0}, + {"SIMCOP Img Sobel 5x5 16s", DVP_KN_VRUN_SOBEL_5x5_16s, 0}, + {"SIMCOP Img Sobel 5x5 16", DVP_KN_VRUN_SOBEL_5x5_16, 0}, + {"SIMCOP Img Sobel 7x7 8s", DVP_KN_VRUN_SOBEL_7x7_8s, 0}, + {"SIMCOP Img Sobel 7x7 8", DVP_KN_VRUN_SOBEL_7x7_8, 0}, + {"SIMCOP Img Sobel 7x7 16s", DVP_KN_VRUN_SOBEL_7x7_16s, 0}, + {"SIMCOP Img Sobel 7x7 16", DVP_KN_VRUN_SOBEL_7x7_16, 0}, + + {"SIMCOP Img Harris Corners",DVP_KN_VRUN_HARRIS_CORNERS, 0}, + {"SIMCOP Img Harris Score", DVP_KN_VRUN_HARRIS_SCORE_7x7, 0}, + {"SIMCOP Img Block Maxima", DVP_KN_VRUN_BLOCK_MAXIMA, 0}, + {"SIMCOP Img NMS Step1", DVP_KN_VRUN_NMS_STEP1, 0}, + + {"SIMCOP Canny Img", DVP_KN_CANNY_IMAGE_SMOOTHING, 0}, + {"SIMCOP Canny 2D Grad", DVP_KN_CANNY_2D_GRADIENT, 0}, + {"SIMCOP Canny NonMax", DVP_KN_CANNY_NONMAX_SUPPRESSION, 0}, + {"SIMCOP Canny Hyst Th", DVP_KN_CANNY_HYST_THRESHHOLD, 0}, + + {"SIMCOP Canny Img", DVP_KN_VRUN_CANNY_IMAGE_SMOOTHING, 0}, + {"SIMCOP Canny 2D Grad", DVP_KN_VRUN_CANNY_2D_GRADIENT, 0}, + {"SIMCOP Canny NonMax", DVP_KN_VRUN_CANNY_NONMAX_SUPPRESSION, 0}, + {"SIMCOP Canny Hyst Th", DVP_KN_VRUN_CANNY_HYST_THRESHHOLD, 0}, + + {"SIMCOP UYVY to YUV444p", DVP_KN_UYVY_TO_YUV444p, 0}, + {"SIMCOP UYVY to RGBp", DVP_KN_UYVY_TO_RGBp, 0}, + {"SIMCOP UYVY to IYUV", DVP_KN_UYVY_TO_YUV420p, 0}, + {"SIMCOP xYxY to LUMA", DVP_KN_XYXY_TO_Y800, 0}, + {"SIMCOP NV12 to YUV444p", DVP_KN_NV12_TO_YUV444p, 0}, + {"SIMCOP YUV444p to RGBp", DVP_KN_YUV444p_TO_RGBp, 0}, + + {"SIMCOP UYVY to YUV444p", DVP_KN_VRUN_UYVY_TO_YUV444p, 0}, + {"SIMCOP UYVY to RGBp", DVP_KN_VRUN_UYVY_TO_RGBp, 0}, + {"SIMCOP UYVY to IYUV", DVP_KN_VRUN_UYVY_TO_YUV420p, 0}, + {"SIMCOP xYxY to LUMA", DVP_KN_VRUN_XYXY_TO_Y800, 0}, + {"SIMCOP NV12 to YUV444p", DVP_KN_VRUN_NV12_TO_YUV444p, 0}, + {"SIMCOP YUV444p to RGBp", DVP_KN_VRUN_YUV444p_TO_RGBp, 0}, + + {"SIMCOP Integral 8", DVP_KN_INTEGRAL_IMAGE_8, 0}, + + {"SIMCOP Integral 8", DVP_KN_VRUN_INTEGRAL_IMAGE_8, 0}, + + {"LDC Affine Transfm", DVP_KN_LDC_AFFINE_TRANSFORM, 0}, + {"SIMCOP SAD 8x8", DVP_KN_VRUN_SAD_8x8, 0}, + {"SIMCOP SAD 16x16", DVP_KN_VRUN_SAD_16x16, 0}, + {"SIMCOP SAD 3x3", DVP_KN_VRUN_SAD_3x3, 0}, + {"SIMCOP SAD 5x5", DVP_KN_VRUN_SAD_5x5, 0}, + {"SIMCOP SAD 7x7", DVP_KN_VRUN_SAD_7x7, 0}, +#endif +#ifdef DVP_USE_DEI + {"SIMCOP DEI INIT", DVP_KN_DEI_DEINTERLACER_INIT, 0}, + {"SIMCOP DEI DEINIT", DVP_KN_DEI_DEINTERLACER_DEINIT, 0}, +#endif +#else + {"SIMCOP Echo", DVP_KN_ECHO, 0}, +#endif +}; +static DVP_U32 numRemoteKernels = dimof(remote_kernels); + +static DVP_Function_t remote_functions[] = { + {"DVP_SKEL_KernelGraphManagerInit", NULL, 0}, + {"DVP_SKEL_KernelGraphManagerDeinit", NULL, 0}, + {"DVP_SKEL_KernelGraphManager", NULL, 0}, +}; +static DVP_U32 numRemoteFunctions = dimof(remote_functions); + +DVP_U32 DVP_KernelGraphManagerCallback(DVP_U32 numArgs, DVP_U32 *args) +{ + numArgs = numArgs; // warnings + args = args; // warnings + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG": %u, %p\n", numArgs, args); + return 0; +} + +static DVP_Function_t local_functions[] = { + {"DVP_KernelGraphManagerCallback", DVP_KernelGraphManagerCallback, 0}, +}; +static DVP_U32 numLocalFunctions = dimof(local_functions); + +MODULE_EXPORT DVP_U32 DVP_GetSupportedKernels(DVP_CoreFunction_t **pFuncs) +{ + if (pFuncs != NULL) + *pFuncs = remote_kernels; + DVP_PRINT(DVP_ZONE_KGM, "Retreiving "KGM_TAG" Kernel Information!\n"); +#ifdef DVP_USE_IPC + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG" DVP_USE_IPC enabled!\n"); +#endif +#ifdef DVP_USE_VRUN + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG" DVP_USE_VRUN enabled!\n"); +#endif + return numRemoteKernels; +} + +MODULE_EXPORT DVP_U32 DVP_GetSupportedRemoteCalls(DVP_Function_t **pRemote, DVP_U32 *pNum) +{ + *pRemote = remote_functions; + *pNum = numRemoteFunctions; + return 1; +} + +MODULE_EXPORT DVP_U32 DVP_GetSupportedLocalCalls(DVP_Function_t **pLocal, DVP_U32 *pNum) +{ + *pLocal = local_functions; + *pNum = numLocalFunctions; + return 1; +} + +MODULE_EXPORT DVP_Core_e DVP_GetSupportedRemoteCore() +{ + return DVP_CORE_SIMCOP; +} + +MODULE_EXPORT DVP_U32 DVP_GetMaximumLoad(void) +{ +#if defined(TARGET_DVP_OMAP4) && defined(BLAZE_TABLET) + return 400; // 400 Mhz +#elif defined(TARGET_DVP_OMAP4) + return 200; // 200 Mhz +#else + return 0; +#endif +} + +static DVP_RPC_t *rpc; +//static DVP_RPC_Interface_t coreInterface; +static DVP_RPC_Core_t *core; +static thread_t worker; +static queue_t *workqueue; +static queue_t *retqueue; +static semaphore_t coreLock; +static DVP_Perf_t perf; +static DVP_RPC_Translation_t translations; + +static DVP_U32 DVP_KernelGraphManager_SIMCOP(DVP_KernelNode_t *pNodes, DVP_U32 startNode, DVP_U32 numNodes) +{ + DVP_U32 processed = 0; + + // block multiple entry + semaphore_wait(&coreLock); + + if (pNodes) + { +#if defined(DVP_USE_OMAPRPC) + DVP_KernelNode_t *pTmp = pNodes; // temp var +#elif defined(DVP_USE_RCM) + DVP_KernelNode_t *pTmp = &pNodes[startNode]; // this will hold the translated address +#endif + +#ifdef DVP_USE_IPC + DVP_U32 n = 0; + int status; + DVP_U32 size; + + DVP_PerformanceStart(&perf); + +#if defined(DVP_USE_RCM) + size = sizeof(DVP_KernelNode_t *); +#elif defined(DVP_USE_OMAPRPC) + size = (startNode+numNodes)*sizeof(DVP_KernelNode_t); +#endif + // @NOTE this implicitly sets the index variable to zero, which is correct in our situation. + memset(&translations, 0, sizeof(translations)); + + DVP_RPC_Parameter_t params[] = { + {DVP_RPC_READ_ONLY, size, (DVP_PTR)&pTmp, (DVP_PTR)dvp_rpc_get_handle(rpc, pTmp)}, +#if defined(DVP_USE_OMAPRPC) + {DVP_RPC_READ_ONLY, sizeof(DVP_U32), (DVP_PTR)&startNode, NULL}, +#endif + {DVP_RPC_READ_ONLY, sizeof(DVP_U32), (DVP_PTR)&numNodes, NULL}, + }; + + if (rpc == NULL || core == NULL) + { + DVP_PRINT(DVP_ZONE_ERROR, KGM_TAG": ERROR! Kernel Graph Manager for SIMCOP is uninitialized!\n"); + goto leave; + } + + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG": Executing %u nodes on subgraph %p! Base %p start %u\n", numNodes, pTmp, pNodes, startNode); + + // for each node, translate all the pointers + for (n = startNode; n < (startNode + numNodes); n++) + { + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG": Translating Node[%u] Kernel %u\n", n, pNodes[n].header.kernel); + switch (pNodes[n].header.kernel) + { + case DVP_KN_NOOP: +#ifdef DVP_USE_DEI + case DVP_KN_DEI_DEINTERLACER_INIT: + case DVP_KN_DEI_DEINTERLACER_DEINIT: +#endif + { + break; + } +#ifdef DVP_USE_VRUN + case DVP_KN_DILATE_CROSS: + case DVP_KN_DILATE_SQUARE: + case DVP_KN_DILATE_MASK: + case DVP_KN_ERODE_CROSS: + case DVP_KN_ERODE_MASK: + case DVP_KN_ERODE_SQUARE: + case DVP_KN_VRUN_DILATE_CROSS: + case DVP_KN_VRUN_DILATE_SQUARE: + case DVP_KN_VRUN_DILATE_MASK: + case DVP_KN_VRUN_ERODE_CROSS: + case DVP_KN_VRUN_ERODE_MASK: + case DVP_KN_VRUN_ERODE_SQUARE: + { + DVP_Morphology_t *pMorph = dvp_knode_to(&pNodes[n], DVP_Morphology_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pMorph->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pMorph->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + + DVP_PrintImage(DVP_ZONE_KGM, &pMorph->input); + DVP_PrintImage(DVP_ZONE_KGM, &pMorph->output); + + if (pNodes[n].header.kernel == DVP_KN_ERODE_MASK || + pNodes[n].header.kernel == DVP_KN_DILATE_MASK || + pNodes[n].header.kernel == DVP_KN_VRUN_ERODE_MASK || + pNodes[n].header.kernel == DVP_KN_VRUN_DILATE_MASK) + { + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pMorph->mask, DVP_TRUE, (DVP_PTR)pTmp, &translations); + DVP_PrintImage(DVP_ZONE_KGM, &pMorph->mask); + } + break; + } + case DVP_KN_IIR_HORZ: + case DVP_KN_IIR_VERT: + case DVP_KN_VRUN_IIR_HORZ: + case DVP_KN_VRUN_IIR_VERT: + { + DVP_IIR_t *pIIR = dvp_knode_to(&pNodes[n], DVP_IIR_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIIR->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIIR->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIIR->scratch, DVP_FALSE, (DVP_PTR)pTmp, &translations); +#if !defined(__QNX__) /// @todo REMOVE: Temporary to avoid build error in QNX + if (pIIR->bounds[0].pData) + { +#if defined(DVP_USE_RCM) + DVP_COMPLAIN_IF_FALSE(dvp_rpc_flush(rpc, DVP_GetSupportedRemoteCore(), (DVP_PTR)pIIR->bounds[0].pData, pIIR->bounds[0].height*pIIR->bounds[0].width,DVP_MTYPE_MPUCACHED_VIRTUAL)); + pIIR->bounds[0].pData = dvp_rpc_mem_xlate_fwrd(rpc, DVP_GetSupportedRemoteCore(), pIIR->bounds[0].pData, pIIR->bounds[0].height*pIIR->bounds[0].width, DVP_MTYPE_MPUCACHED_VIRTUAL); +#else + translations.translations[translations.numTranslations].offset = (DVP_U32)&pIIR->bounds[0].pData - (DVP_U32)pTmp; + translations.translations[translations.numTranslations].base = (DVP_U32)pIIR->bounds[0].pData; + translations.translations[translations.numTranslations].cacheops = DVP_TRUE; + translations.translations[translations.numTranslations].reserved = (DVP_PTR)dvp_rpc_get_handle(rpc, pIIR->bounds[0].pData); + translations.numTranslations++; +#endif + } + if (pIIR->bounds[1].pData) + { +#if defined(DVP_USE_RCM) + DVP_COMPLAIN_IF_FALSE(dvp_rpc_flush(rpc, DVP_GetSupportedRemoteCore(), (DVP_PTR)pIIR->bounds[1].pData, pIIR->bounds[1].height*pIIR->bounds[1].width,DVP_MTYPE_MPUCACHED_VIRTUAL)); + pIIR->bounds[1].pData = dvp_rpc_mem_xlate_fwrd(rpc, DVP_GetSupportedRemoteCore(), pIIR->bounds[1].pData, pIIR->bounds[1].height*pIIR->bounds[1].width, DVP_MTYPE_MPUCACHED_VIRTUAL); +#else + translations.translations[translations.numTranslations].offset = (DVP_U32)&pIIR->bounds[1].pData - (DVP_U32)pTmp; + translations.translations[translations.numTranslations].base = (DVP_U32)pIIR->bounds[1].pData; + translations.translations[translations.numTranslations].cacheops = DVP_TRUE; + translations.translations[translations.numTranslations].reserved = (DVP_PTR)dvp_rpc_get_handle(rpc, pIIR->bounds[1].pData); + translations.numTranslations++; +#endif + } +#endif + DVP_PrintImage(DVP_ZONE_KGM, &pIIR->input); + DVP_PrintImage(DVP_ZONE_KGM, &pIIR->output); + DVP_PrintImage(DVP_ZONE_KGM, &pIIR->scratch); + break; + } + case DVP_KN_NONMAXSUPPRESS_3x3_S16: + case DVP_KN_NONMAXSUPPRESS_5x5_S16: + case DVP_KN_NONMAXSUPPRESS_7x7_S16: + case DVP_KN_THR_GT2MAX_8: + case DVP_KN_THR_GT2MAX_16: + case DVP_KN_THR_GT2THR_8: + case DVP_KN_THR_GT2THR_16: + case DVP_KN_THR_LE2MIN_8: + case DVP_KN_THR_LE2MIN_16: + case DVP_KN_THR_LE2THR_8: + case DVP_KN_THR_LE2THR_16: + case DVP_KN_VRUN_NONMAXSUPPRESS_3x3_S16: + case DVP_KN_VRUN_NONMAXSUPPRESS_5x5_S16: + case DVP_KN_VRUN_NONMAXSUPPRESS_7x7_S16: + case DVP_KN_VRUN_THR_GT2MAX_8: + case DVP_KN_VRUN_THR_GT2MAX_16: + case DVP_KN_VRUN_THR_GT2THR_8: + case DVP_KN_VRUN_THR_GT2THR_16: + case DVP_KN_VRUN_THR_LE2MIN_8: + case DVP_KN_VRUN_THR_LE2MIN_16: + case DVP_KN_VRUN_THR_LE2THR_8: + case DVP_KN_VRUN_THR_LE2THR_16: + { + DVP_Threshold_t *pThresh = dvp_knode_to(&pNodes[n], DVP_Threshold_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pThresh->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pThresh->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_CANNY_IMAGE_SMOOTHING: + case DVP_KN_CONV_3x3: + case DVP_KN_CONV_5x5: + case DVP_KN_CONV_7x7: + case DVP_KN_VRUN_CANNY_IMAGE_SMOOTHING: + case DVP_KN_VRUN_CONV_3x3: + case DVP_KN_VRUN_CONV_5x5: + case DVP_KN_VRUN_CONV_7x7: + case DVP_KN_VRUN_CONV_MxN: + { + DVP_ImageConvolution_t *pImg = dvp_knode_to(&pNodes[n], DVP_ImageConvolution_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->mask, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VRUN_SAD_8x8: + case DVP_KN_VRUN_SAD_16x16: + case DVP_KN_VRUN_SAD_3x3: + case DVP_KN_VRUN_SAD_5x5: + case DVP_KN_VRUN_SAD_7x7: + { + DVP_SAD_t *pImg = dvp_knode_to(&pNodes[n], DVP_SAD_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->refImg, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_CANNY_2D_GRADIENT: + case DVP_KN_VRUN_CANNY_2D_GRADIENT: + { + DVP_Canny2dGradient_t *pGrad = dvp_knode_to(&pNodes[n], DVP_Canny2dGradient_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pGrad->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pGrad->outGradX, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pGrad->outGradY, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pGrad->outMag, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_CANNY_NONMAX_SUPPRESSION: + case DVP_KN_VRUN_CANNY_NONMAX_SUPPRESSION: + { + DVP_CannyNonMaxSuppression_t *pCnonmax = dvp_knode_to(&pNodes[n], DVP_CannyNonMaxSuppression_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pCnonmax->inMag, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pCnonmax->inGradX, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pCnonmax->inGradY, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pCnonmax->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_CANNY_HYST_THRESHHOLD: + case DVP_KN_VRUN_CANNY_HYST_THRESHHOLD: + { + DVP_CannyHystThresholding_t *pDth = dvp_knode_to(&pNodes[n], DVP_CannyHystThresholding_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->inMag, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->inEdgeMap, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_XYXY_TO_Y800: // single planes + case DVP_KN_UYVY_TO_YUV444p: // multiplane output + case DVP_KN_UYVY_TO_RGBp: // multiplane output + case DVP_KN_UYVY_TO_YUV420p: // multiplane output + case DVP_KN_INTEGRAL_IMAGE_8: + case DVP_KN_NV12_TO_YUV444p: + case DVP_KN_YUV444p_TO_RGBp: + case DVP_KN_SOBEL_3x3_8s: + case DVP_KN_SOBEL_3x3_8: + case DVP_KN_SOBEL_3x3_16s: + case DVP_KN_SOBEL_3x3_16: + case DVP_KN_SOBEL_5x5_8s: + case DVP_KN_SOBEL_5x5_8: + case DVP_KN_SOBEL_5x5_16s: + case DVP_KN_SOBEL_5x5_16: + case DVP_KN_SOBEL_7x7_8s: + case DVP_KN_SOBEL_7x7_8: + case DVP_KN_SOBEL_7x7_16s: + case DVP_KN_SOBEL_7x7_16: + case DVP_KN_VRUN_XYXY_TO_Y800: // single planes + case DVP_KN_VRUN_UYVY_TO_YUV444p: // multiplane output + case DVP_KN_VRUN_UYVY_TO_RGBp: // multiplane output + case DVP_KN_VRUN_UYVY_TO_YUV420p: // multiplane output + case DVP_KN_VRUN_INTEGRAL_IMAGE_8: + case DVP_KN_VRUN_NV12_TO_YUV444p: + case DVP_KN_VRUN_YUV444p_TO_RGBp: + case DVP_KN_VRUN_SOBEL_3x3_8s: + case DVP_KN_VRUN_SOBEL_3x3_8: + case DVP_KN_VRUN_SOBEL_3x3_16s: + case DVP_KN_VRUN_SOBEL_3x3_16: + case DVP_KN_VRUN_SOBEL_5x5_8s: + case DVP_KN_VRUN_SOBEL_5x5_8: + case DVP_KN_VRUN_SOBEL_5x5_16s: + case DVP_KN_VRUN_SOBEL_5x5_16: + case DVP_KN_VRUN_SOBEL_7x7_8s: + case DVP_KN_VRUN_SOBEL_7x7_8: + case DVP_KN_VRUN_SOBEL_7x7_16s: + case DVP_KN_VRUN_SOBEL_7x7_16: + case DVP_KN_LDC_AFFINE_TRANSFORM: + { + DVP_Transform_t *pIO = dvp_knode_to(&pNodes[n], DVP_Transform_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + DVP_PrintImage(DVP_ZONE_KGM, &pIO->input); + DVP_PrintImage(DVP_ZONE_KGM, &pIO->output); + break; + } + case DVP_KN_VRUN_HARRIS_CORNERS: + { + DVP_HarrisCorners_t *pIO = dvp_knode_to(&pNodes[n], DVP_HarrisCorners_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->tempBuf1, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->tempBuf2, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->tempBuf3, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->tempBuf4, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->output, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VRUN_HARRIS_SCORE_7x7: + { + + DVP_Harris_t *pIO = dvp_knode_to(&pNodes[n], DVP_Harris_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->input, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->harrisScore, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VRUN_BLOCK_MAXIMA: + { + DVP_BlockMaxima_t *pIO = dvp_knode_to(&pNodes[n], DVP_BlockMaxima_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->input, DVP_FALSE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->blockMaximaX, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->blockMaximaY, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->blockMaximaMAX, DVP_TRUE, (DVP_PTR)pTmp, &translations); + break; + } + case DVP_KN_VRUN_NMS_STEP1: + { + DVP_NMSStep1_t *pIO = dvp_knode_to(&pNodes[n], DVP_NMSStep1_t); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->nmsStep1X, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->nmsStep1Y, DVP_TRUE, (DVP_PTR)pTmp, &translations); + dvp_rpc_prepare_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->nmsStep1Dst, DVP_FALSE, (DVP_PTR)pTmp, &translations); + break; + } +#endif + default: + return 0; // other kernels are not supported. + break; + } + } + +#if defined(DVP_USE_RCM) + // flush all the node data back to memory + DVP_COMPLAIN_IF_FALSE(dvp_rpc_flush(rpc, DVP_GetSupportedRemoteCore(), (DVP_PTR)&pNodes[startNode], numNodes * sizeof(DVP_KernelNode_t), DVP_MTYPE_KERNELGRAPH)); + + // now pTmp will be the translated value of the Node pointer on the remote core. + pTmp = dvp_rpc_mem_xlate_fwrd(rpc, DVP_GetSupportedRemoteCore(), pNodes, numNodes*sizeof(DVP_KernelNode_t), DVP_MTYPE_KERNELGRAPH); + + // now increment to the node to be executed + pTmp = &pTmp[startNode]; +#endif + // execute the remote functions + RPC_COMPLAIN_IF_FAILED(status,dvp_rpc_remote_execute(rpc, core, DVP_KGM_REMOTE_EXEC, params, dimof(params), &translations)); + if (status >= 0) + processed = status; // get the number of nodes from the "status". + +#if defined(DVP_USE_RCM) + // need to invalidate the kernel nodes, they may have been modified by the remote core (local data) + DVP_COMPLAIN_IF_FALSE(dvp_rpc_invalidate(rpc, DVP_GetSupportedRemoteCore(), (DVP_PTR)&pNodes[startNode], numNodes * sizeof(DVP_KernelNode_t), DVP_MTYPE_KERNELGRAPH)); +#endif + + // for each node, translate the node data back to local VM. + for (n = startNode; n < (startNode + numNodes); n++) + { + switch (pNodes[n].header.kernel) + { + case DVP_KN_NOOP: +#ifdef DVP_USE_DEI + case DVP_KN_DEI_DEINTERLACER_INIT: + case DVP_KN_DEI_DEINTERLACER_DEINIT: +#endif + { + break; + } +#ifdef DVP_USE_VRUN + case DVP_KN_DILATE_CROSS: + case DVP_KN_DILATE_SQUARE: + case DVP_KN_DILATE_MASK: + case DVP_KN_ERODE_CROSS: + case DVP_KN_ERODE_MASK: + case DVP_KN_ERODE_SQUARE: + case DVP_KN_VRUN_DILATE_CROSS: + case DVP_KN_VRUN_DILATE_SQUARE: + case DVP_KN_VRUN_DILATE_MASK: + case DVP_KN_VRUN_ERODE_CROSS: + case DVP_KN_VRUN_ERODE_MASK: + case DVP_KN_VRUN_ERODE_SQUARE: + { + DVP_Morphology_t *pMorph = dvp_knode_to(&pNodes[n], DVP_Morphology_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pMorph->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pMorph->output, DVP_TRUE); + if (pNodes[n].header.kernel == DVP_KN_ERODE_MASK || + pNodes[n].header.kernel == DVP_KN_DILATE_MASK || + pNodes[n].header.kernel == DVP_KN_VRUN_ERODE_MASK || + pNodes[n].header.kernel == DVP_KN_VRUN_DILATE_MASK) + { + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pMorph->mask, DVP_FALSE); + } + break; + } + case DVP_KN_IIR_HORZ: + case DVP_KN_IIR_VERT: + case DVP_KN_VRUN_IIR_HORZ: + case DVP_KN_VRUN_IIR_VERT: + { + DVP_IIR_t *pIIR = dvp_knode_to(&pNodes[n], DVP_IIR_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIIR->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIIR->output, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIIR->scratch, DVP_FALSE); + if (pIIR->bounds[0].pData) + pIIR->bounds[0].pData = dvp_rpc_mem_xlate_back(rpc, DVP_GetSupportedRemoteCore(), pIIR->bounds[0].pData, DVP_MTYPE_MPUCACHED_VIRTUAL); + if (pIIR->bounds[1].pData) + pIIR->bounds[1].pData = dvp_rpc_mem_xlate_back(rpc, DVP_GetSupportedRemoteCore(), pIIR->bounds[1].pData, DVP_MTYPE_MPUCACHED_VIRTUAL); + break; + } + case DVP_KN_NONMAXSUPPRESS_3x3_S16: + case DVP_KN_NONMAXSUPPRESS_5x5_S16: + case DVP_KN_NONMAXSUPPRESS_7x7_S16: + case DVP_KN_THR_GT2MAX_8: + case DVP_KN_THR_GT2MAX_16: + case DVP_KN_THR_GT2THR_8: + case DVP_KN_THR_GT2THR_16: + case DVP_KN_THR_LE2MIN_8: + case DVP_KN_THR_LE2MIN_16: + case DVP_KN_THR_LE2THR_8: + case DVP_KN_THR_LE2THR_16: + case DVP_KN_VRUN_NONMAXSUPPRESS_3x3_S16: + case DVP_KN_VRUN_NONMAXSUPPRESS_5x5_S16: + case DVP_KN_VRUN_NONMAXSUPPRESS_7x7_S16: + case DVP_KN_VRUN_THR_GT2MAX_8: + case DVP_KN_VRUN_THR_GT2MAX_16: + case DVP_KN_VRUN_THR_GT2THR_8: + case DVP_KN_VRUN_THR_GT2THR_16: + case DVP_KN_VRUN_THR_LE2MIN_8: + case DVP_KN_VRUN_THR_LE2MIN_16: + case DVP_KN_VRUN_THR_LE2THR_8: + case DVP_KN_VRUN_THR_LE2THR_16: + { + DVP_Threshold_t *pThresh = dvp_knode_to(&pNodes[n], DVP_Threshold_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pThresh->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pThresh->output, DVP_TRUE); + break; + } + case DVP_KN_CANNY_IMAGE_SMOOTHING: + case DVP_KN_CONV_3x3: + case DVP_KN_CONV_5x5: + case DVP_KN_CONV_7x7: + case DVP_KN_VRUN_CANNY_IMAGE_SMOOTHING: + case DVP_KN_VRUN_CONV_3x3: + case DVP_KN_VRUN_CONV_5x5: + case DVP_KN_VRUN_CONV_7x7: + case DVP_KN_VRUN_CONV_MxN: + { + DVP_ImageConvolution_t *pImg = dvp_knode_to(&pNodes[n], DVP_ImageConvolution_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->output, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->mask, DVP_FALSE); + break; + } + case DVP_KN_VRUN_SAD_8x8: + case DVP_KN_VRUN_SAD_16x16: + case DVP_KN_VRUN_SAD_3x3: + case DVP_KN_VRUN_SAD_5x5: + case DVP_KN_VRUN_SAD_7x7: + { + DVP_SAD_t *pImg = dvp_knode_to(&pNodes[n], DVP_SAD_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->output, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pImg->refImg, DVP_FALSE); + break; + } + case DVP_KN_CANNY_2D_GRADIENT: + case DVP_KN_VRUN_CANNY_2D_GRADIENT: + { + DVP_Canny2dGradient_t *pGrad = dvp_knode_to(&pNodes[n], DVP_Canny2dGradient_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pGrad->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pGrad->outGradX, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pGrad->outGradY, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pGrad->outMag, DVP_TRUE); + break; + } + case DVP_KN_CANNY_NONMAX_SUPPRESSION: + case DVP_KN_VRUN_CANNY_NONMAX_SUPPRESSION: + { + DVP_CannyNonMaxSuppression_t *pCnonmax = dvp_knode_to(&pNodes[n], DVP_CannyNonMaxSuppression_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pCnonmax->inMag, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pCnonmax->inGradX, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pCnonmax->inGradY, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pCnonmax->output, DVP_TRUE); + break; + } + case DVP_KN_CANNY_HYST_THRESHHOLD: + case DVP_KN_VRUN_CANNY_HYST_THRESHHOLD: + { + DVP_CannyHystThresholding_t *pDth = dvp_knode_to(&pNodes[n], DVP_CannyHystThresholding_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->inMag, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->inEdgeMap, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pDth->output, DVP_TRUE); + break; + } + case DVP_KN_XYXY_TO_Y800: // single planes + case DVP_KN_UYVY_TO_YUV444p: // multiplane output + case DVP_KN_UYVY_TO_RGBp: // multiplane output + case DVP_KN_UYVY_TO_YUV420p: + case DVP_KN_INTEGRAL_IMAGE_8: + case DVP_KN_NV12_TO_YUV444p: + case DVP_KN_YUV444p_TO_RGBp: + case DVP_KN_SOBEL_3x3_8s: + case DVP_KN_SOBEL_3x3_8: + case DVP_KN_SOBEL_3x3_16s: + case DVP_KN_SOBEL_3x3_16: + case DVP_KN_SOBEL_5x5_8s: + case DVP_KN_SOBEL_5x5_8: + case DVP_KN_SOBEL_5x5_16s: + case DVP_KN_SOBEL_5x5_16: + case DVP_KN_SOBEL_7x7_8s: + case DVP_KN_SOBEL_7x7_8: + case DVP_KN_SOBEL_7x7_16s: + case DVP_KN_SOBEL_7x7_16: + case DVP_KN_VRUN_XYXY_TO_Y800: // single planes + case DVP_KN_VRUN_UYVY_TO_YUV444p: // multiplane output + case DVP_KN_VRUN_UYVY_TO_RGBp: // multiplane output + case DVP_KN_VRUN_UYVY_TO_YUV420p: + case DVP_KN_VRUN_INTEGRAL_IMAGE_8: + case DVP_KN_VRUN_NV12_TO_YUV444p: + case DVP_KN_VRUN_YUV444p_TO_RGBp: + case DVP_KN_VRUN_SOBEL_3x3_8s: + case DVP_KN_VRUN_SOBEL_3x3_8: + case DVP_KN_VRUN_SOBEL_3x3_16s: + case DVP_KN_VRUN_SOBEL_3x3_16: + case DVP_KN_VRUN_SOBEL_5x5_8s: + case DVP_KN_VRUN_SOBEL_5x5_8: + case DVP_KN_VRUN_SOBEL_5x5_16s: + case DVP_KN_VRUN_SOBEL_5x5_16: + case DVP_KN_VRUN_SOBEL_7x7_8s: + case DVP_KN_VRUN_SOBEL_7x7_8: + case DVP_KN_VRUN_SOBEL_7x7_16s: + case DVP_KN_VRUN_SOBEL_7x7_16: + case DVP_KN_LDC_AFFINE_TRANSFORM: + { + DVP_Transform_t *pIO = dvp_knode_to(&pNodes[n], DVP_Transform_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->output, DVP_TRUE); + break; + } + case DVP_KN_VRUN_HARRIS_CORNERS: + { + + DVP_HarrisCorners_t *pIO = dvp_knode_to(&pNodes[n], DVP_HarrisCorners_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->tempBuf1, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->tempBuf2, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->tempBuf3, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->tempBuf4, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->output, DVP_TRUE); + break; + } + case DVP_KN_VRUN_HARRIS_SCORE_7x7: + { + DVP_Harris_t *pIO = dvp_knode_to(&pNodes[n], DVP_Harris_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->harrisScore, DVP_TRUE); + break; + } + case DVP_KN_VRUN_BLOCK_MAXIMA: + { + DVP_BlockMaxima_t *pIO = dvp_knode_to(&pNodes[n], DVP_BlockMaxima_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->input, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->blockMaximaX, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->blockMaximaY, DVP_TRUE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->blockMaximaMAX, DVP_TRUE); + break; + } + case DVP_KN_VRUN_NMS_STEP1: + { + DVP_NMSStep1_t *pIO = dvp_knode_to(&pNodes[n], DVP_NMSStep1_t); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->nmsStep1X, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->nmsStep1Y, DVP_FALSE); + dvp_rpc_return_image(rpc, DVP_GetSupportedRemoteCore(), &pIO->nmsStep1Dst, DVP_TRUE); + break; + } +#endif + default: + goto leave; + } + } + + DVP_PerformanceStop(&perf); + +#endif // DVP_USE_IPC + + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG": Processed %u nodes!\n", processed); + } +leave: + semaphore_post(&coreLock); // allow other threads to enter + return processed; +} + +static thread_ret_t DVP_KernelGraphManagerThread_SIMCOP(void *arg __attribute__((unused))) +{ + DVP_KGM_Thread_t kgmt; + + thread_nextaffinity(); + while (queue_read(workqueue, true_e, &kgmt) == true_e) + { + DVP_KernelNode_t *pSubNodes = kgmt.pSubNodes; + DVP_U32 startNode = kgmt.startNode; + DVP_U32 numNodes = kgmt.numNodes; + DVP_U32 processed = 0; + + processed = DVP_KernelGraphManager_SIMCOP(pSubNodes, startNode, numNodes); + + kgmt.numNodesExecuted = processed; + queue_write(retqueue, true_e, &kgmt); + } + thread_exit(0); +} + +MODULE_EXPORT void DVP_KernelGraphManagerRestart(void *arg __attribute__((unused))) +{ + int status = 0; + DVP_U32 version = DVP_VERSION; + DVP_U16 width = 320; + DVP_U16 height = 240; + DVP_RPC_Parameter_t params[] = { + {DVP_RPC_READ_ONLY, sizeof(DVP_U16), &width, NULL}, + {DVP_RPC_READ_ONLY, sizeof(DVP_U16), &height, NULL}, + {DVP_RPC_READ_ONLY, sizeof(DVP_U32), &version, NULL}, + }; + DVP_PRINT(DVP_ZONE_KGM, KGM_TAG" re-issuing init command to remote core.\n"); +#ifdef DVP_USE_IPC + RPC_COMPLAIN_IF_FAILED(status,dvp_rpc_remote_execute(rpc, core, DVP_KGM_REMOTE_INIT, params, dimof(params), NULL)); +#endif +} + +MODULE_EXPORT DVP_BOOL DVP_KernelGraphManagerDeinit(void) +{ + queue_pop(workqueue); + queue_pop(retqueue); + thread_join(worker); + queue_destroy(workqueue); + queue_destroy(retqueue); + semaphore_delete(&coreLock); + DVP_PerformancePrint(&perf, KGM_TAG); + +#ifdef DVP_USE_IPC + int status = 0; + DVP_PRINT(DVP_ZONE_KGM, "Destroying "KGM_TAG"\n"); + RPC_COMPLAIN_IF_FAILED(status,dvp_rpc_remote_execute(rpc, core, DVP_KGM_REMOTE_DEINIT, NULL, 0, NULL)); + core = NULL; + rpc = NULL; + if (status < 0) + return DVP_FALSE; + else + return DVP_TRUE; +#else + rpc = NULL; + core = NULL; + return DVP_TRUE; +#endif +} + +MODULE_EXPORT DVP_U32 DVP_KernelGraphManagerInit(DVP_RPC_t *pRPC, DVP_RPC_Core_t *pCore) +{ + if (rpc == NULL && core == NULL && pRPC != NULL && pCore != NULL) + { + int status; + //DVP_U32 version = DVP_VERSION; + DVP_U32 width = 320; + DVP_U32 height = 240; + DVP_RPC_Parameter_t params[] = { + {DVP_RPC_READ_ONLY, sizeof(DVP_U32), &width, NULL}, + {DVP_RPC_READ_ONLY, sizeof(DVP_U32), &height, NULL}, + //{DVP_RPC_READ_ONLY, sizeof(DVP_U32), &version, NULL}, // optional? + }; + rpc = pRPC; + core = pCore; +#ifdef DVP_USE_IPC + RPC_COMPLAIN_IF_FAILED(status,dvp_rpc_remote_execute(rpc, core, DVP_KGM_REMOTE_INIT, params, dimof(params), NULL)); + if (status < 0) + return DVP_FALSE; + else +#endif + { + DVP_Perf_Clear(&perf); + semaphore_create(&coreLock, 1, false_e); + workqueue = queue_create(10, sizeof(DVP_KGM_Thread_t)); + retqueue = queue_create(10, sizeof(DVP_KGM_Thread_t)); + worker = thread_create(DVP_KernelGraphManagerThread_SIMCOP, NULL); + return DVP_TRUE; + } + } + else + return DVP_FALSE; +} + +MODULE_EXPORT DVP_U32 DVP_KernelGraphManager(DVP_KernelNode_t *pSubNodes, DVP_U32 startNode, DVP_U32 numNodes, DVP_BOOL sync) +{ + DVP_PRINT(DVP_ZONE_KGM, "Entered "KGM_TAG" Kernel Manager! (%s)\n",(sync?"SYNC":"QUEUED")); + if (sync == DVP_FALSE) + { + DVP_KGM_Thread_t kgmt = {pSubNodes, startNode, numNodes, 0}; + if (queue_write(workqueue, true_e, &kgmt) == true_e) // this is internally a copy + { + do { + DVP_KGM_Thread_t kgmr; + + if (queue_read(retqueue, true_e, &kgmr) == true_e) + { + if (kgmt.pSubNodes == kgmr.pSubNodes && + kgmt.startNode == kgmr.startNode && + kgmt.numNodes == kgmr.numNodes) // this is ours, return. + { + DVP_PRINT(DVP_ZONE_KGM, "Work Thread returned %u nodes!\n", kgmr.numNodesExecuted); + return kgmr.numNodesExecuted; + } + else // it's not ours, put it back in the queue + queue_write(retqueue, true_e, &kgmr); + } + else + break; + } while (1); + } + return 0; + } + else + { + return DVP_KernelGraphManager_SIMCOP(pSubNodes, startNode, numNodes); + } +} + + +#if defined(SYSBIOS_SL) +static static_function_t dvp_kgm_functions[] = { + {"DVP_KernelGraphManagerInit", (function_f)DVP_KernelGraphManagerInit}, + {"DVP_KernelGraphManager", (function_f)DVP_KernelGraphManager}, + {"DVP_GetSupportedKernels", (function_f)DVP_GetSupportedKernels}, + {"DVP_GetSupportedLocalCalls", (function_f)DVP_GetSupportedLocalCalls}, + {"DVP_GetSupportedRemoteCalls", (function_f)DVP_GetSupportedRemoteCalls}, + {"DVP_GetSupportedRemoteCore", (function_f)DVP_GetSupportedRemoteCore}, + {"DVP_GetMaximumLoad", (function_f)DVP_GetMaximumLoad}, + {"DVP_KernelGraphManagerDenit", (function_f)DVP_KernelGraphManagerDeinit}, +}; + +static_module_table_t dvp_kgm_simcop_table = { + "dvp_kgm_simcop", + dimof(dvp_kgm_functions), + dvp_kgm_functions +}; +#endif diff --git a/source/dvp/dvp_kgraph/Android.mk b/source/dvp/dvp_kgraph/Android.mk new file mode 100644 index 0000000..60f34af --- /dev/null +++ b/source/dvp/dvp_kgraph/Android.mk @@ -0,0 +1,51 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := -DDVP_KGAPI_THREADED $(DVP_DEBUGGING) $(DVP_CFLAGS) $(DVP_FEATURES) +ifeq ($(TARGET_ANDROID_VERSION),GINGERBREAD) +LOCAL_CFLAGS += -DV4L2_SUPPORT +else ifeq ($(PLAT_MAJOR),4) # ICS/JB +LOCAL_CFLAGS += -DSURFACE_FLINGER -DDVP_CONTINUE_ON_ERRORS +endif +LOCAL_SRC_FILES := \ + dvp_kgb.c \ + dvp_kmdl.c \ + dvp_kgraph.c \ + dvp_mem.c \ + dvp_mem_int.c \ + dvp_display.c +ifeq ($(PLAT_MAJOR),4) +LOCAL_SRC_FILES += dvp_rpc_omaprpc.c +else +LOCAL_SRC_FILES += dvp_rpc_rcm.c +endif + +LOCAL_C_INCLUDES := $(DVP_INCLUDES) +LOCAL_WHOLE_STATIC_LIBRARIES := libv4l2 libsosal libsosal_shm +LOCAL_SHARED_LIBRARIES := libdl $(DVP_SYSLIBS) libutils libcutils libbinder +ifeq ($(PLAT_MAJOR),4) # ICS/JB +LOCAL_WHOLE_STATIC_LIBRARIES += libgfxdisp libsf +LOCAL_SHARED_LIBRARIES += libhardware libion libgui libui +LOCAL_LDLIBS += -lhwcomposer.omap4 +endif +ifeq ($(IPC_TYPE),rpmsg) +LOCAL_WHOLE_STATIC_LIBRARIES += libomaprpc +endif +LOCAL_MODULE := libdvp +include $(BUILD_SHARED_LIBRARY) diff --git a/source/dvp/dvp_kgraph/concerto.mak b/source/dvp/dvp_kgraph/concerto.mak new file mode 100644 index 0000000..f21be34 --- /dev/null +++ b/source/dvp/dvp_kgraph/concerto.mak @@ -0,0 +1,41 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(PRELUDE) +TARGET=dvp +TARGETTYPE=dsmo +CSOURCES=$(all-c-files) +DEFFILE=dvp.def +DEFS+=DVP_KGAPI_THREADED $(DVP_FEATURES) +IDIRS += $(IPC_INCS) $(MEM_INCS) +SYS_SHARED_LIBS += $(MEM_LIBS) +ifeq ($(TARGET_OS),LINUX) + ifneq ($(GTK_PATH),) + IDIRS+=$(GTK_INC) + LDIRS+=$(GTK_LDIRS) + STATIC_LIBS+=gtkwindow + SYS_SHARED_LIBS+=$(GTK_LIBS) + endif + SHARED_LIBS += $(IPC_LIBS) +else ifeq ($(TARGET_OS),Windows_NT) + SYS_SHARED_LIBS += $(IPC_LIBS) $(PLATFORM_LIBS) +else ifeq ($(TARGET_OS),__QNX__) + STATIC_LIBS += qnxscreen + SYS_SHARED_LIBS += $(IPC_LIBS) $(PLATFORM_LIBS) +else + # in non-linux systems, are aren't using OMAPRPC + SYS_SHARED_LIBS += $(IPC_LIBS) $(PLATFORM_LIBS) +endif +STATIC_LIBS+=sosal +include $(FINALE) diff --git a/source/dvp/dvp_kgraph/dvp.def b/source/dvp/dvp_kgraph/dvp.def new file mode 100644 index 0000000..73da6b7 --- /dev/null +++ b/source/dvp/dvp_kgraph/dvp.def @@ -0,0 +1,39 @@ +LIBRARY "dvp.dll" +EXPORTS + DVP_KernelGraph_Init + DVP_KernelGraph_Deinit + DVP_KernelGraph_Process + DVP_KernelNode_Alloc + DVP_KernelNode_Free + DVP_KernelGraph_Alloc + DVP_KernelGraph_Free + DVP_KernelGraphSection_Init + DVP_PerformanceClear + DVP_PerformanceStart + DVP_PerformanceStop + DVP_PrintPerformanceCSV + DVP_PrintPerformanceGraph + DVP_PrintImage + DVP_Image_Init + DVP_Image_Deinit + DVP_Image_Alloc + DVP_Image_Free + DVP_Image_Size + DVP_Image_Serialize + DVP_Image_Unserialize + DVP_Image_Copy + DVP_Image_Fill + DVP_Buffer_Alloc + DVP_Buffer_Free + DVP_Buffer_Init + DVP_Buffer_Deinit + DVP_Display_Alloc + DVP_Display_Free + DVP_Display_Create + DVP_Display_Destroy + DVP_Display_Render + DVP_Perf_Clear + DVP_SetCoreCapacity + DVP_GetCoreCapacity + DVP_QuerySystem + DVP_QueryKernel diff --git a/source/dvp/dvp_kgraph/dvp_display.c b/source/dvp/dvp_kgraph/dvp_display.c new file mode 100644 index 0000000..e2d8c33 --- /dev/null +++ b/source/dvp/dvp_kgraph/dvp_display.c @@ -0,0 +1,1168 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +// On ANDROID GB or FROYO and on Linux (like Ubuntu) +#if defined(V4L2_SUPPORT) +#include + +typedef struct _dvp_display_t { + v4l2_api_t *m_v4l2; + uint32_t width; + uint32_t height; + thread_t m_renderer; + DVP_BOOL m_running; + DVP_Perf_t m_perf; + event_t m_gate; +} dvp_display_t; + +#define _DVP_DISPLAY_T +#include +#include + +#if defined(BLAZE) || defined(SDP) +#define INITIAL_OFFSET_X (0) +#define INITIAL_OFFSET_Y (0) +#else +#define INITIAL_OFFSET_X (480) +#define INITIAL_OFFSET_Y (77) // put it below the systray and title bar on some phones +#endif + +DVP_BOOL DVP_Display_Alloc(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + if (dvpd && pImage) + { + void *buffer = NULL; + uint32_t index = 0; + uint32_t length = 0; + buffer = v4l2_acquire(dvpd->m_v4l2, &index); + if (buffer) + { + length = v4l2_length(dvpd->m_v4l2, index); + pImage->pBuffer[0] = buffer; + pImage->pData[0] = buffer; + if (pImage->planes == 1) + pImage->y_stride = length / pImage->bufHeight; + else if (pImage->color == FOURCC_NV12) + { + pImage->y_stride = length / (pImage->bufHeight + pImage->bufHeight/2); + pImage->pBuffer[1] = &pImage->pBuffer[0][(pImage->y_stride*pImage->bufHeight)]; + pImage->pData[1] = pImage->pBuffer[1]; + } + // it is important to set this to the length returned from V4L2, not a calculated value. + pImage->numBytes = length; + +#if (defined(ANDROID) || defined(LINUX)) && defined(DVP_USE_TILER) + // on Android and Linux, V4L2 display buffers are allocated out of the tiler. + pImage->memType = DVP_MTYPE_DISPLAY_2DTILED; + pImage->skipCacheOpFlush = DVP_TRUE; // uncached + pImage->skipCacheOpInval = DVP_TRUE; // uncached +#endif + DVP_PrintImage(DVP_ZONE_VIDEO, pImage); + return DVP_TRUE; + } + else + return DVP_FALSE; + } + else + return DVP_FALSE; +} + +DVP_BOOL DVP_Display_Free(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + if (dvpd && pImage) + { + void *buffer = pImage->pBuffer[0]; + uint32_t index = v4l2_search_buffer(dvpd->m_v4l2, buffer); + if (v4l2_release(dvpd->m_v4l2, buffer, index) == false_e) + return DVP_FALSE; + else + { + memset(pImage, 0, sizeof(DVP_Image_t)); + pImage->memType = DVP_MTYPE_DEFAULT; + return DVP_TRUE; + } + } + return DVP_FALSE; +} + +void sysfs_put(const char *key, const char *value) +{ + size_t len = strlen(value); + int fd = open(key, O_RDWR); + if (fd) + { + DVP_PRINT(DVP_ZONE_VIDEO, "%s => %s\n", value, key); + write(fd, value, len); + close(fd); + } +} + +void sysfs_get(const char *key, char *value, size_t len) +{ + int fd = open(key, O_RDWR); + if (fd) + { + read(fd, value, len); + close(fd); + DVP_PRINT(DVP_ZONE_VIDEO, "%s => \"%s\"\n", key, value); + } +} + +void set_rgb_color(uint8_t r, uint8_t g, uint8_t b) +{ + char rv[4]; + char gv[4]; + char bv[4]; + snprintf(rv, sizeof(rv), "%03u", r); + snprintf(gv, sizeof(gv), "%03u", g); + snprintf(bv, sizeof(bv), "%03u", b); +#if defined(BLAZE) + sysfs_put("/sys/class/leds/blue/brightness", rv); + sysfs_put("/sys/class/leds/red/brightness", gv); + sysfs_put("/sys/class/leds/green/brightness", bv); +#endif +} + +void enable_secondary_display() +{ +#if defined(ANDROID) && (defined(BLAZE) || defined(SDP)) + char value[20]; + memset(value, 0, sizeof(value)); +#if defined(FROYO) + sysfs_put("/sys/devices/platform/omapdss/overlay2/manager", "2lcd"); + sysfs_put("/sys/devices/platform/omapdss/overlay2/zorder", "3"); + sysfs_put("/sys/devices/platform/omapdss/overlay1/zorder", "2"); + sysfs_get("/sys/devices/platform/omapdss/overlay2/zorder", value, sizeof(value)); +#elif defined(GINGERBREAD) + sysfs_put("/sys/devices/platform/omapdss/display1/enabled", "1"); + sysfs_put("/sys/devices/platform/omapdss/overlay2/manager", "2lcd"); + sysfs_put("/sys/devices/platform/omapdss/overlay2/zorder", "3"); + sysfs_put("/sys/devices/platform/omapdss/overlay1/zorder", "2"); + sysfs_put("/sys/devices/platform/omapdss/overlay0/zorder", "3"); +#endif +#endif +} + +void disable_secondary_display() +{ +#if defined(ANDROID) && (defined(BLAZE) || defined(SDP)) + char value[20]; + memset(value, 0, sizeof(value)); +#if defined(FROYO) + sysfs_put("/sys/devices/platform/omapdss/overlay2/manager", "lcd"); + sysfs_put("/sys/devices/platform/omapdss/overlay2/zorder", "0"); + sysfs_put("/sys/devices/platform/omapdss/overlay1/zorder", "2"); + sysfs_put("/sys/devices/platform/omapdss/overlay0/zorder", "3"); + sysfs_get("/sys/devices/platform/omapdss/overlay2/zorder", value, sizeof(value)); +#elif defined(GINGERBREAD) + sysfs_put("/sys/devices/platform/omapdss/display1/enabled", "0"); + sysfs_put("/sys/devices/platform/omapdss/overlay2/manager", "lcd"); + sysfs_put("/sys/devices/platform/omapdss/overlay2/zorder", "1"); + sysfs_put("/sys/devices/platform/omapdss/overlay1/zorder", "2"); + sysfs_put("/sys/devices/platform/omapdss/overlay0/zorder", "3"); +#endif +#endif +} + +void enable_primary_display() +{ +#if !(defined(BLAZE) || defined(SDP)) && defined(ANDROID) + sysfs_put("/sys/devices/platform/omapdss/overlay2/manager", "2lcd"); + sysfs_put("/sys/devices/platform/omapdss/overlay2/rotation", "0"); + sysfs_put("/sys/devices/platform/omapdss/overlay0/zorder", "2"); + sysfs_put("/sys/devices/platform/omapdss/overlay1/zorder", "1"); + sysfs_put("/sys/devices/platform/omapdss/overlay2/zorder", "3"); + sysfs_put("/sys/devices/platform/omapdss/overlay2/global_alpha", "100"); + sysfs_put("/sys/devices/platform/omapdss/overlay2/enabled", "1"); + sysfs_put("/sys/devices/platform/omapdss/manager2/trans_key_enable", "0"); + sysfs_put("/sys/devices/platform/omapdss/manager2/alpha_blending_enabled", "1"); + sysfs_put("/sys/devices/platform/omapdss/manager2/trans_key_value", "0"); + sysfs_put("/sys/devices/platform/omapdss/manager2/trans_key_type", "video-source"); +#endif +} + +void disable_primary_display() +{ +#if !(defined(BLAZE) || defined(SDP)) && defined(ANDROID) + sysfs_put("/sys/devices/platform/omapdss/overlay2/manager", "2lcd"); + sysfs_put("/sys/devices/platform/omapdss/overlay2/rotation", "0"); + sysfs_put("/sys/devices/platform/omapdss/overlay0/zorder", "3"); + sysfs_put("/sys/devices/platform/omapdss/overlay1/zorder", "1"); + sysfs_put("/sys/devices/platform/omapdss/overlay2/zorder", "1"); + sysfs_put("/sys/devices/platform/omapdss/overlay2/global_alpha", "255"); + sysfs_put("/sys/devices/platform/omapdss/overlay2/enabled", "0"); + sysfs_put("/sys/devices/platform/omapdss/manager2/trans_key_enable", "0"); + sysfs_put("/sys/devices/platform/omapdss/manager2/alpha_blending_enabled", "0"); + sysfs_put("/sys/devices/platform/omapdss/manager2/trans_key_value", "0"); + sysfs_put("/sys/devices/platform/omapdss/manager2/trans_key_type", "gfx-destination"); +#endif +} + +void DVP_Display_Render(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + if (dvpd) + { + uint32_t index = 0; + + DVP_PerformanceStart(&dvpd->m_perf); + + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2 Rendering DVP_Image_t *%p Buffer %p\n", pImage, pImage->pBuffer[0]); + // get the index of the buffer + index = v4l2_search_buffer(dvpd->m_v4l2, pImage->pBuffer[0]); + if (index != V4L2_INVALID_INDEX) + { + //The crop is breaking the Tismo graph since the display is bigger than the image + //It is only necessary when the x_start and y_start becomes non-zero (no cases yet) + //v4l2_crop(dvpd->m_v4l2, pImage->x_start, pImage->y_start, pImage->width, pImage->height); + v4l2_queue(dvpd->m_v4l2, index, V4L2_BUF_TYPE_VIDEO_OUTPUT); + v4l2_start(dvpd->m_v4l2, V4L2_BUF_TYPE_VIDEO_OUTPUT); + event_set(&dvpd->m_gate); // unblock the dequeue thread + + DVP_PerformanceStop(&dvpd->m_perf); + DVP_PerformancePrint(&dvpd->m_perf, "V4L2"); + } + else + { + DVP_PRINT(DVP_ZONE_VIDEO, "ERROR: V4L2 Image is not allocated from display!\n"); + } + } +} + +thread_ret_t DVP_Display_Thread(void *arg) +{ + dvp_display_t *dvpd = (dvp_display_t *)arg; + thread_ret_t ret = 0; + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2 Dequeue Thread Launched! (Waiting)\n"); + event_wait(&dvpd->m_gate, EVENT_FOREVER); + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2 Dequeue Thread Running!\n"); + while (dvpd->m_running == DVP_TRUE) + { + void *buffer; + uint32_t index; + bool_e dequeued = true_e; + do { + if (v4l2_wait(dvpd->m_v4l2) > 0) + { + dequeued = v4l2_dequeue(dvpd->m_v4l2, &index, V4L2_BUF_TYPE_VIDEO_OUTPUT); + if (dequeued) + { + // the actual buffer dequeued + buffer = v4l2_search_index(dvpd->m_v4l2, index); + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2 Dequeued Buffer %p [%u]\n", buffer, index); + break; + } + else + { + //DVP_PRINT(DVP_ZONE_VIDEO, "V4L2 Dequeue did not work!\n"); + // there's just nothing to dequeue yet, sleep a while until + // there is something to remove... + // this should really be propotional to some frame rate parameter + thread_msleep(33); + } + } + else + { + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2 Wait failure!\n"); + dequeued = false_e; + } + } while (dequeued == false_e && dvpd->m_running == DVP_TRUE); + } + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2 Display Thread Exitting\n"); + thread_exit(ret); +} + +void DVP_Display_Destroy(dvp_display_t **dvpd) +{ + if (dvpd && *dvpd) + { + dvp_display_t *tmp = *dvpd; // convienence pointer + + tmp->m_running = DVP_FALSE; + event_set(&tmp->m_gate); + v4l2_stop(tmp->m_v4l2, V4L2_BUF_TYPE_VIDEO_OUTPUT); // this dequeues everything implicitly + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2 Closing Renderer Thread\n"); + thread_join(tmp->m_renderer); // wait for the thread to finish + DVP_PRINT(DVP_ZONE_VIDEO, "V4L2 Renderer Closed!\n"); + v4l2_free(tmp->m_v4l2); // unmap the memory + v4l2_close(&tmp->m_v4l2); // close the driver + event_deinit(&tmp->m_gate); + free(tmp); // free the data structre + *dvpd = NULL; // set the user's pointer to null. + + disable_secondary_display(); + disable_primary_display(); + } +} + +dvp_display_t *DVP_Display_Create(uint32_t image_width, uint32_t image_height, + uint32_t buffer_width, uint32_t buffer_height, + uint32_t display_width, uint32_t display_height, + uint32_t scaled_width, uint32_t scaled_height, + uint32_t crop_top, uint32_t crop_left, + fourcc_t color, + int32_t rotation, + uint32_t numBuffers) +{ + DVP_BOOL unwind = DVP_FALSE; + dvp_display_t *dvpd = (dvp_display_t *)calloc(1,sizeof(dvp_display_t)); + if (dvpd) + { + DVP_PRINT(DVP_ZONE_VIDEO, "Image: %ux%u Display: %ux%u Scaled:%ux%u\n", + image_width, image_height, + display_width, display_height, + scaled_width, scaled_height); + enable_secondary_display(); + enable_primary_display(); + set_rgb_color(0,0,0); // turn off the LED so that we don't get the light in the camera + + event_init(&dvpd->m_gate, false_e); // a one-shot event. + dvpd->m_v4l2 = v4l2_open(V4L2_DISPLAY_DEVICE, V4L2_CAP_STREAMING, true_e); + dvpd->width = image_width; + dvpd->height = image_height; + dvpd->m_perf.minTime = 0xFFFFFFFF; + if (v4l2_allocate(dvpd->m_v4l2, buffer_width, buffer_height, numBuffers, color, V4L2_BUF_TYPE_VIDEO_OUTPUT) == false_e) + unwind = DVP_TRUE; + else + { + uint32_t overlay_width = 0; + uint32_t overlay_height = 0; + uint32_t offset_x = INITIAL_OFFSET_X; + uint32_t offset_y = INITIAL_OFFSET_Y; + + // retrieve the information about the overlay + v4l2_metrics(dvpd->m_v4l2, &overlay_width, &overlay_height); + + DVP_PRINT(DVP_ZONE_VIDEO, "OVERLAY: %ux%u %ux%u\n", overlay_width, overlay_height, display_width, display_height); + + if (offset_x > (display_width-scaled_width)) + offset_x = (display_width-scaled_width); + if (offset_y > (display_height-scaled_height)) + offset_y = (display_height-scaled_height); + +#if (defined(BLAZE) || defined(SDP)) && defined(ANDROID) + v4l2_mirror(dvpd->m_v4l2, true_e); + v4l2_crop(dvpd->m_v4l2, crop_left, crop_top, image_width, image_height); + v4l2_position(dvpd->m_v4l2, offset_x, offset_y, scaled_width, scaled_height); +#endif + +#if !(defined(BLAZE) || defined(SDP)) && defined(ANDROID) + // no mirror, it's not supported. + v4l2_position(dvpd->m_v4l2, offset_x, offset_y, scaled_width, scaled_height); + //if (color == FOURCC_NV12) + // v4l2_crop(dvpd->m_v4l2, 0, 32, image_width, image_height); + v4l2_crop(dvpd->m_v4l2, crop_left, crop_top, image_width, image_height); + if (color != FOURCC_NV12) + v4l2_transparency(dvpd->m_v4l2, V4L2_FBUF_FLAG_CHROMAKEY, 0); +#endif + // set the rotation of the overlay. + v4l2_rotate(dvpd->m_v4l2, rotation); + + // create the renderer + dvpd->m_running = DVP_TRUE; + dvpd->m_renderer = thread_create(DVP_Display_Thread, (void *)dvpd); + + // insert a green/gray screen at the start + { + DVP_Image_t tmp; + uint32_t y, i; + + DVP_Image_Init(&tmp, buffer_width, buffer_height, color); + tmp.width = image_width; + tmp.height = image_height; + DVP_Display_Alloc(dvpd, &tmp); + if (color == FOURCC_UYVY) { + for (y = 0; y < tmp.height; y++) { + i = (y * tmp.y_stride); + memset(&tmp.pData[0][i], 0x80, tmp.width*tmp.x_stride); + } + } + else if (color == FOURCC_NV12) + { + for (y = 0; y < tmp.height; y++) { + i = (y * tmp.y_stride); + memset(&tmp.pData[0][i], 0x80, tmp.width*tmp.x_stride); + } + for (y = 0; y < tmp.height; y++) { + i = (y/2 * tmp.y_stride); + memset(&tmp.pData[1][i], 0x10, tmp.width/2*tmp.x_stride*2); + } + } + else if (color == FOURCC_RGB || color == FOURCC_BGR) + { + for (y = 0; y < tmp.height; y++) { + i = (y * tmp.y_stride); + memset(&tmp.pData[0][i], 0x80, tmp.width*tmp.x_stride); + } + } + DVP_Display_Render(dvpd, &tmp); // this will do a memcpy + DVP_Display_Free(dvpd, &tmp); + } +#if !(defined(BLAZE) || defined(SDP)) + // send the alpha value again! + sysfs_put("/sys/devices/platform/omapdss/overlay2/global_alpha", "100"); +#endif + } + } + if (unwind) + DVP_Display_Destroy(&dvpd); + return dvpd; +} + +DVP_BOOL DVP_Display_Drop(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + if (dvpd && pImage) + return DVP_TRUE; + else + return DVP_FALSE; +} + +#elif defined(__QNX__) + +#include + +typedef struct _dvp_display_t { + struct qnxscreen_api *m_qnxscreen; + uint32_t width; + uint32_t height; + DVP_BOOL m_running; + DVP_Perf_t m_perf; +} dvp_display_t; + +#define _DVP_DISPLAY_T +#include +#include +#include + +#define INITIAL_OFFSET_X (0) +#define INITIAL_OFFSET_Y (0) + +DVP_BOOL DVP_Display_Alloc(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + void *buffer = NULL; + uint32_t index = 0; + uint32_t length = 0; + + if (!dvpd || !pImage) + return DVP_FALSE; + + buffer = qnxscreen_acquire(dvpd->m_qnxscreen, &index); + if (!buffer) + return DVP_FALSE; + + length = qnxscreen_length(dvpd->m_qnxscreen, index); + pImage->pBuffer[0] = buffer; + pImage->pData[0] = buffer; + switch (pImage->color) { + case FOURCC_NV12: + pImage->y_stride = length / (pImage->bufHeight + pImage->bufHeight/2); + pImage->pBuffer[1] = &pImage->pBuffer[0][(pImage->y_stride * pImage->bufHeight)]; + pImage->pData[1] = pImage->pBuffer[1]; + break; + case FOURCC_UYVY: + default: + pImage->y_stride = length / pImage->bufHeight; // we know it's strided. + break; + } + pImage->memType = DVP_MTYPE_DISPLAY_2DTILED; + pImage->numBytes = length; + + DVP_PrintImage(DVP_ZONE_VIDEO, pImage); + return DVP_TRUE; +} + +DVP_BOOL DVP_Display_Free(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + void *buffer; + uint32_t index; + + if (!dvpd || !pImage) + return DVP_FALSE; + + buffer = pImage->pBuffer[0]; + index = qnxscreen_search_buffer(dvpd->m_qnxscreen, buffer); + if (qnxscreen_release(dvpd->m_qnxscreen, buffer, index) == false_e) + return DVP_FALSE; + + memset(pImage, 0, sizeof(DVP_Image_t)); + pImage->memType = DVP_MTYPE_DEFAULT; + return DVP_TRUE; +} + +void DVP_Display_Render(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + uint32_t index = 0; + + if (!dvpd || !pImage) + return; + + DVP_PerformanceStart(&dvpd->m_perf); + DVP_PRINT(DVP_ZONE_VIDEO, "QNX Screen Rendering DVP_Image_t *%p Buffer %p\n", pImage, pImage->pBuffer[0]); + // get the index of the buffer + index = qnxscreen_search_buffer(dvpd->m_qnxscreen, pImage->pBuffer[0]); + if (index == QNXSCREEN_INVALID_INDEX) { + DVP_PRINT(DVP_ZONE_VIDEO, "ERROR: V4L2 Image is not allocated from display!\n"); + return; + } + qnxscreen_post(dvpd->m_qnxscreen, index); + DVP_PerformanceStop(&dvpd->m_perf); + DVP_PerformancePrint(&dvpd->m_perf, "QNXSCREEN"); +} + +void DVP_Display_Destroy(dvp_display_t **dvpd) +{ + if (!dvpd || !(*dvpd)) + return; + + qnxscreen_free((*dvpd)->m_qnxscreen); // unmap the memory + qnxscreen_close(&(*dvpd)->m_qnxscreen); // close the driver + free(*dvpd); // free the data structre + *dvpd = NULL; // set the user's pointer to null. +} + +dvp_display_t *DVP_Display_Create(uint32_t image_width, uint32_t image_height, + uint32_t buffer_width, uint32_t buffer_height, + uint32_t display_width, uint32_t display_height, + uint32_t scaled_width, uint32_t scaled_height, + uint32_t crop_top, uint32_t crop_left, + fourcc_t color, int32_t rotation, uint32_t numBuffers) +{ + dvp_display_t *dvpd = (dvp_display_t *)calloc(1,sizeof(dvp_display_t)); + uint32_t overlay_width = 0; + uint32_t overlay_height = 0; + // @TODO: figure out a better way to handle this for rotation + uint32_t offset_x = 15; + uint32_t offset_y = 600-(image_height+15); + + if (!dvpd) + return NULL; + + DVP_PRINT(DVP_ZONE_VIDEO, "Image: %ux%u Display: %ux%u Scaled:%ux%u\n", + image_width, image_height, + display_width, display_height, + scaled_width, scaled_height); + + dvpd->m_qnxscreen = qnxscreen_open(); + dvpd->width = image_width; + dvpd->height = image_height; + DVP_Perf_Clear(&dvpd->m_perf); + + if (qnxscreen_allocate(dvpd->m_qnxscreen, buffer_width, buffer_height, numBuffers, color) == false_e) + goto unwind; + + // retrieve the information about the overlay + qnxscreen_metrics(dvpd->m_qnxscreen, &overlay_width, &overlay_height); + + DVP_PRINT(DVP_ZONE_VIDEO, "OVERLAY: %ux%u %ux%u\n", overlay_width, overlay_height, display_width, display_height); + + if (offset_x > (display_width-scaled_width)) + offset_x = (display_width-scaled_width); + if (offset_y > (display_height-scaled_height)) + offset_y = (display_height-scaled_height); + + qnxscreen_mirror(dvpd->m_qnxscreen, true_e); + qnxscreen_transparency(dvpd->m_qnxscreen, 100); + qnxscreen_position(dvpd->m_qnxscreen, offset_x, offset_y, scaled_width, scaled_height); + + // set the rotation of the overlay. + qnxscreen_rotate(dvpd->m_qnxscreen, rotation); + + // insert a green/gray screen at the start + { + DVP_Image_t tmp; + uint32_t y, i; + + DVP_Image_Init(&tmp, buffer_width, buffer_width, color); + tmp.width = image_width; + tmp.height = image_height; + DVP_Display_Alloc(dvpd, &tmp); + if (color == FOURCC_UYVY) { + for (y = 0; y < tmp.height; y++) { + i = (y * tmp.y_stride); + memset(&tmp.pData[0][i], 0x80, tmp.width * 2); + } + } else if (color == FOURCC_NV12) { + for (y = 0; y < tmp.height; y++) { + i = (y * tmp.y_stride); + memset(&tmp.pData[0][i], 0x80, + tmp.width * tmp.x_stride); + } + for (y = 0; y < tmp.height; y++) { + i = (y/2 * tmp.y_stride); + memset(&tmp.pData[1][i], 0x10, + tmp.width / 2 * tmp.x_stride * 2); + } + } + DVP_Display_Render(dvpd, &tmp); // this will do a memcpy + DVP_Display_Free(dvpd, &tmp); + } + + return dvpd; +unwind: + DVP_Display_Destroy(&dvpd); + return NULL; +} + +DVP_BOOL DVP_Display_Drop(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + if (dvpd && pImage) + return DVP_TRUE; + else + return DVP_FALSE; +} + +#elif defined(GTK_SUPPORT) + +#include +#include + +typedef struct _dvp_diplay_t { + GtkWindow_t *w; + uint32_t width; + uint32_t height; + thread_t m_renderer; + bool_e m_running; +} dvp_display_t; + +DVP_BOOL DVP_Display_Alloc(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + if (dvpd) + { + uint32_t index; + void *buffer = gtkwindow_acquire(dvpd->w, &index); + if (buffer) + { + uint32_t length = gtkwindow_length(dvpd->w, index); + pImage->pBuffer[0] = buffer; + pImage->pData[0] = buffer; + if (pImage->planes == 1) + pImage->y_stride = length / pImage->bufHeight; + else if (pImage->color == FOURCC_NV12) + { + pImage->y_stride = length / (pImage->bufHeight + pImage->bufHeight/2); + pImage->pBuffer[1] = &pImage->pBuffer[0][(pImage->y_stride*pImage->bufHeight)]; + pImage->pData[1] = pImage->pBuffer[1]; + } + // it is important to set this to the length returned from V4L2, not a calculated value. + pImage->numBytes = length; + +#if defined(LINUX) && defined(DVP_USE_TILER) + // on Android and Linux, V4L2 display buffers are allocated out of the tiler. + pImage->memType = DVP_MTYPE_DISPLAY_2DTILED; +#endif + DVP_PrintImage(DVP_ZONE_VIDEO, pImage); + return DVP_TRUE; + } + } + return DVP_FALSE; +} + +DVP_BOOL DVP_Display_Free(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + if (dvpd) + { + void *buffer = pImage->pBuffer[0]; + uint32_t index = gtkwindow_search_index(dvpd->w, buffer); + if (gtkwindow_release(dvpd->w, buffer, index) == false_e) + return DVP_FALSE; + else + { + memset(pImage, 0, sizeof(DVP_Image_t)); + pImage->memType = DVP_MTYPE_DEFAULT; + return DVP_TRUE; + } + } + return DVP_FALSE; +} + + +thread_ret_t DVP_Display_Thread(void *arg) +{ + dvp_display_t *dvpd = (dvp_display_t *)arg; + while (dvpd->m_running) + { + uint32_t index; + gtkwindow_dequeue(dvpd->w, &index); + } + thread_exit(0); +} + + +void DVP_Display_Render(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + if (dvpd) + { + uint32_t index = gtkwindow_search_index(dvpd->w, pImage->pData[0]); + gtkwindow_queue(dvpd->w, index); + } +} + +void DVP_Display_Destroy(dvp_display_t **pdvpd) +{ + if (pdvpd) + { + dvp_display_t *dvpd = *pdvpd; + if (dvpd) + { + dvpd->m_running = false_e; + gtkwindow_free(dvpd->w); + gtkwindow_close(dvpd->w); + thread_join(dvpd->m_renderer); + free(dvpd); + } + *pdvpd = NULL; + } +} + +dvp_display_t *DVP_Display_Create(uint32_t image_width, uint32_t image_height, + uint32_t buffer_width, uint32_t buffer_height, + uint32_t display_width, uint32_t display_height, + uint32_t scaled_width, uint32_t scaled_height, + uint32_t crop_top, uint32_t crop_left, + fourcc_t color, int32_t rotation, uint32_t numBuffers) +{ + DVP_BOOL unwind = DVP_FALSE; + dvp_display_t *dvpd = (dvp_display_t *)calloc(1,sizeof(dvp_display_t)); + if (dvpd) + { + DVP_PRINT(DVP_ZONE_VIDEO, "DISPLAY: Requesting Color Space %08x\n", color); + dvpd->width = buffer_width; + dvpd->height = buffer_height; + dvpd->w = gtkwindow_open("DVP Display"); + if (dvpd->w && gtkwindow_allocate(dvpd->w, buffer_width, buffer_height, numBuffers, color)) + { + DVP_PRINT(DVP_ZONE_VIDEO, "DISPLAY: Allocated %u images\n", numBuffers); + dvpd->m_running = true_e; + dvpd->m_renderer = thread_create(DVP_Display_Thread, dvpd); + } + else + { + gtkwindow_close(dvpd->w); + free(dvpd); + dvpd = NULL; + } + } + return dvpd; +} + +DVP_BOOL DVP_Display_Drop(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + if (dvpd && pImage) + return DVP_TRUE; + else + return DVP_FALSE; +} + +#elif defined(ICS) || defined(JELLYBEAN) + +#if defined(SURFACE_FLINGER) + +#include + +typedef struct _dvp_display_t { + surfaceflinger_t *sfd; +} dvp_display_t; + +#define _DVP_DISPLAY_T +#include +#include +#include +#if defined(ANDROID) +#include +#endif + +#define INITIAL_OFFSET_X (100) +#define INITIAL_OFFSET_Y (100) + +void DVP_Display_Destroy(dvp_display_t **dvpd) +{ + if (dvpd && *dvpd) + { + if ((*dvpd)->sfd) + { + surfaceflinger_free((*dvpd)->sfd); + surfaceflinger_destroy(&(*dvpd)->sfd); + } + free((*dvpd)); + dvpd = NULL; + } +} + +dvp_display_t *DVP_Display_Create(uint32_t image_width, + uint32_t image_height, + uint32_t buffer_width, + uint32_t buffer_height, + uint32_t display_width __attribute__((unused)), + uint32_t display_height __attribute__((unused)), + uint32_t scaled_width __attribute__((unused)), + uint32_t scaled_height __attribute__((unused)), + uint32_t crop_top __attribute__((unused)), + uint32_t crop_left __attribute__((unused)), + fourcc_t color, + int32_t rotation __attribute__((unused)), + uint32_t numBuffers) +{ + DVP_PRINT(DVP_ZONE_VIDEO, "Creating surfaceflinger Display!\n"); + if (color == FOURCC_NV12) + { + dvp_display_t *dvpd = (dvp_display_t *)calloc(1, sizeof(dvp_display_t)); + if (dvpd) + { + dvpd->sfd = surfaceflinger_create(buffer_width, buffer_height); + if ( surfaceflinger_allocate(dvpd->sfd, buffer_width, buffer_height, numBuffers, color) ) + { + DVP_PRINT(DVP_ZONE_VIDEO, "Allocated %u buffers\n", numBuffers); + } + + surfaceflinger_set_crop(dvpd->sfd, 0, 0, image_width, image_height); + + uint32_t offset_x = INITIAL_OFFSET_X; + uint32_t offset_y = INITIAL_OFFSET_Y; + + surfaceflinger_set_position(dvpd->sfd, offset_x, offset_y); + } + return dvpd; + } + else + return NULL; +} + +void DVP_Display_Render(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + if (dvpd && dvpd->sfd) + { + if (pImage->reserved) + { + void *ptr; + surfaceflinger_enqueue(dvpd->sfd, pImage->reserved); + surfaceflinger_dequeue(dvpd->sfd, &ptr); + // @TODO did pImage->reserved and ptr ==? + } + } +} + +DVP_BOOL DVP_Display_Alloc(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + DVP_BOOL allocated = DVP_FALSE; + bool_e result = false_e; + if (dvpd && dvpd->sfd) + { + int32_t stride; + uint8_t *ptrs[3] = {NULL, NULL, NULL}; + result = surfaceflinger_acquire(dvpd->sfd, &(pImage->reserved), ptrs, &stride); + if (result) + { + switch (pImage->color) + { + case FOURCC_NV12: + pImage->memType = DVP_MTYPE_DISPLAY_2DTILED; + pImage->y_stride = stride; + pImage->pBuffer[0] = ptrs[0]; + pImage->pBuffer[1] = ptrs[1]; + pImage->pData[0] = pImage->pBuffer[0]; + pImage->pData[1] = pImage->pBuffer[1]; + break; + } + DVP_PRINT(DVP_ZONE_VIDEO,"Display buffer stride is %u\n", pImage->y_stride); + allocated = DVP_TRUE; + } + } + return allocated; +} + +DVP_BOOL DVP_Display_Free(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + if (dvpd && dvpd->sfd) + { + if (pImage->reserved) + { + surfaceflinger_release(dvpd->sfd, pImage->reserved); + } + } + return DVP_TRUE; +} + +DVP_BOOL DVP_Display_Drop(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + if (dvpd && pImage) + return DVP_TRUE; + else + return DVP_FALSE; +} + +#else + +#include + +typedef struct _dvp_display_t { + gfx_display_t *gfxd; +} dvp_display_t; + +#define _DVP_DISPLAY_T +#include +#include +#include +#if defined(ANDROID) +#include +#endif + +void DVP_Display_Destroy(dvp_display_t **dvpd) +{ + if (dvpd && *dvpd) + { + if ((*dvpd)->gfxd) + { + gfx_display_free((*dvpd)->gfxd); + gfx_display_destroy(&(*dvpd)->gfxd); + } + free((*dvpd)); + dvpd = NULL; + } +} + +dvp_display_t *DVP_Display_Create(uint32_t image_width __attribute__((unused)), + uint32_t image_height __attribute__((unused)), + uint32_t buffer_width, + uint32_t buffer_height, + uint32_t display_width __attribute__((unused)), + uint32_t display_height __attribute__((unused)), + uint32_t scaled_width __attribute__((unused)), + uint32_t scaled_height __attribute__((unused)), + uint32_t crop_top __attribute__((unused)), + uint32_t crop_left __attribute__((unused)), + fourcc_t color, + int32_t rotation __attribute__((unused)), + uint32_t numBuffers) +{ + DVP_PRINT(DVP_ZONE_VIDEO, "Creating GFX Display!\n"); + if (color == FOURCC_NV12) + { + dvp_display_t *dvpd = (dvp_display_t *)calloc(1, sizeof(dvp_display_t)); + if (dvpd) + { + char filename[MAX_PATH]; + PYUV_GetFilename(filename, "/sdcard/", "display", buffer_width, buffer_height, 30, color); + dvpd->gfxd = gfx_display_create(filename); + if (gfx_display_allocate(dvpd->gfxd, numBuffers, buffer_width, buffer_height, color) == true_e) + { + DVP_PRINT(DVP_ZONE_VIDEO, "Allocated %u buffers\n", numBuffers); + } + } + return dvpd; + } + else + return NULL; +} + +void DVP_Display_Render(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + if (dvpd && dvpd->gfxd) + { + if (pImage->reserved) + { + void *ptr; + gfx_display_queue(dvpd->gfxd, pImage->reserved); + gfx_display_dequeue(dvpd->gfxd, &ptr); + // @TODO did pImage->reserved and ptr ==? + } + } +} + +DVP_BOOL DVP_Display_Alloc(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + DVP_BOOL allocated = DVP_FALSE; + if (dvpd && dvpd->gfxd) + { + image_t *img = gfx_display_acquire(dvpd->gfxd, &(pImage->reserved)); + if (img) + { + switch (pImage->color) + { + case FOURCC_NV12: + pImage->memType = DVP_MTYPE_DISPLAY_2DTILED; + pImage->y_stride = img->plane[0].ystride; + pImage->pBuffer[0] = img->plane[0].ptr; + pImage->pBuffer[1] = img->plane[1].ptr; + pImage->pData[0] = pImage->pBuffer[0]; + pImage->pData[1] = pImage->pBuffer[1]; + break; + } + DVP_PRINT(DVP_ZONE_VIDEO,"Display buffer stride is %u\n", pImage->y_stride); + allocated = DVP_TRUE; + } + } + return allocated; +} + +DVP_BOOL DVP_Display_Free(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + if (dvpd && dvpd->gfxd) + { + if (pImage->reserved) + { + gfx_display_release(dvpd->gfxd, NULL, pImage->reserved); + } + } + return DVP_TRUE; +} + +DVP_BOOL DVP_Display_Drop(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + if (dvpd && pImage) + return DVP_TRUE; + else + return DVP_FALSE; +} +#endif + +#else + +#if !defined(WIN32) +#warning "Building DVP Display in FILE output mode!" +#else +#pragma message("***** Building DVP Display in FILE output mode!") +#endif + +typedef struct _dvp_display_t { + FILE *out; +} dvp_display_t; + +#define _DVP_DISPLAY_T +#include +#include +#include + + +dvp_display_t *DVP_Display_Create(uint32_t image_width, uint32_t image_height, + uint32_t buffer_width, uint32_t buffer_height, + uint32_t display_width, uint32_t display_height, + uint32_t scaled_width, uint32_t scaled_height, + uint32_t crop_top, uint32_t crop_left, + fourcc_t color, int32_t rotation, uint32_t numBuffers) +{ + DVP_PRINT(DVP_ZONE_VIDEO, "Creating File Based DVP Display!\n"); + if (color == FOURCC_UYVY || color == FOURCC_NV12 || color == FOURCC_YUY2) + { + dvp_display_t *dvpd = (dvp_display_t *)calloc(1, sizeof(dvp_display_t)); + if (dvpd) + { + char display_name[255]; + PYUV_GetFilename(display_name, "", "display", image_width, image_height, 30, color); + //sprintf(display_name, "display_%ux%u_%s.yuv", image_width, image_height, (color==FOURCC_UYVY?"UYVY":"NV12")); + dvpd->out = fopen(display_name, "wb+"); + DVP_PRINT(DVP_ZONE_VIDEO, "Opened file %s\n", display_name); + } + return dvpd; + } + else + return NULL; +} + +void DVP_Display_Destroy(dvp_display_t **dvpd) +{ + if (dvpd && *dvpd) + { + if ((*dvpd)->out) + fclose((*dvpd)->out); + free((*dvpd)); + *dvpd = NULL; + } +} + +void DVP_Display_Render(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + uint32_t y, j, n = 0, len = 0; + if (dvpd == NULL || dvpd->out == NULL) + return; + if (pImage->color == FOURCC_UYVY || pImage->color == FOURCC_YUY2) + { + for (y = 0; y < pImage->height; y++) // loop for each line + { + len = (pImage->x_stride * pImage->width); + j = (y * pImage->y_stride); + n += (uint32_t)fwrite(&pImage->pData[0][j], 1, len, dvpd->out); + } + fflush(dvpd->out); + } + else if (pImage->color == FOURCC_NV12) + { + for (y = 0; y < pImage->height ; y++) + { + len = (pImage->x_stride * pImage->width); + j = (y * pImage->y_stride); + n+= (DVP_U32)fwrite(&pImage->pData[0][j], 1, len, dvpd->out); + } + for (y = 0; y < pImage->height/2; y++) + { + len = (pImage->x_stride * pImage->width); // half-width but double pixels + j = (y * pImage->y_stride); + n+= (DVP_U32)fwrite(&pImage->pData[1][j], 1, len, dvpd->out); + } + fflush(dvpd->out); + } +} + +DVP_BOOL DVP_Display_Alloc(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + uint32_t p = 0; + if (pImage->color == FOURCC_UYVY || pImage->color == FOURCC_YUY2) + { + uint32_t planeSize = pImage->bufWidth * pImage->bufHeight * pImage->x_stride; + pImage->pBuffer[0] = calloc(1, planeSize); + pImage->pData[0] = pImage->pBuffer[0]; + pImage->numBytes = planeSize; + } + else if (pImage->color == FOURCC_NV12) + { + uint32_t numBytes = (pImage->bufWidth * pImage->bufHeight * 3)/2; + pImage->pBuffer[0] = calloc(1, numBytes); + pImage->pBuffer[1] = &pImage->pBuffer[0][pImage->height * pImage->width]; + pImage->pData[0] = pImage->pBuffer[0]; + pImage->pData[1] = pImage->pBuffer[1]; + } + pImage->y_stride = pImage->width * pImage->x_stride; + pImage->memType = DVP_MTYPE_MPUCACHED_VIRTUAL; + if (pImage->pBuffer[0]) + return DVP_TRUE; + else + return DVP_FALSE; +} + +DVP_BOOL DVP_Display_Free(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + free(pImage->pBuffer[0]); + pImage->pBuffer[0] = NULL; + pImage->pBuffer[1] = NULL; + pImage->pData[0] = NULL; + pImage->pData[1] = NULL; + pImage->numBytes = 0; + pImage->y_stride = 0; + pImage->memType = DVP_MTYPE_DEFAULT; + return DVP_TRUE; +} + +DVP_BOOL DVP_Display_Drop(dvp_display_t *dvpd, DVP_Image_t *pImage) +{ + if (dvpd && pImage) + return DVP_TRUE; + else + return DVP_FALSE; +} + +#endif + diff --git a/source/dvp/dvp_kgraph/dvp_kgb.c b/source/dvp/dvp_kgraph/dvp_kgb.c new file mode 100644 index 0000000..f5cacfb --- /dev/null +++ b/source/dvp/dvp_kgraph/dvp_kgb.c @@ -0,0 +1,826 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#if defined(ANDROID) || defined(LINUX) || defined(__QNX__) || defined(CYGWIN) || defined(DARWIN) +#if !defined(__QNX__) && !defined(DARWIN) +#include +#else +#define __EXT_UNIX_MISC //Needed by QNX version of dirent.h to include scandir() +#endif +#include +#include +#include +#endif + +#include +#include + +#include +#include +#include + +#define DVP_OPTIMIZED_GRAPHS +#if defined(ANDROID) || defined(__QNX__) || defined(LINUX) +#define DVP_USE_LOAD_TABLE +#endif + +#if defined(ANDROID) +#define DVP_PROPERTY_KEY "log.ti.dvp.load_table_users" +#define DVP_PROPERTY_VAL_FMT "count=%d" +#define DVP_PROPERTY_VAL_DFT "count=0" +#include +#endif + +#if defined(ANDROID) +/** The path to the Kernel Graph Manager Libraries */ +#define DVP_KGM_PATH "/system/lib/" +#elif defined(LINUX) || defined(CYGWIN) || defined(__QNX__) +/** The path to the Kernel Graph Manager Libraries */ +#define DVP_KGM_PATH "/usr/lib/" +#elif defined(DARWIN) +/** The path to the Kernel Graph Manager Libraries */ +#define DVP_KGM_PATH "/opt/local/lib/" +#else // WIN32 or SYSBIOS +/** The path to the Kernel Graph Manager Libraries */ +#define DVP_KGM_PATH "" +#endif + +/*! + * This structure maps the core to it's predefined priority. + */ +typedef struct _dvp_core_priority_t { + DVP_Core_e core; + DVP_U32 priority; +} DVP_Core_Priority_t; + +#if defined(TARGET_DVP_OMAP4) +/** This defines the list of priorities for the predefined cores */ +DVP_Core_Priority_t f_corePriorities[DVP_CORE_MAX] = { + {DVP_CORE_DSP, DVP_PRIORITY_HIGHEST+DVP_PRIORITY_INC}, + {DVP_CORE_SIMCOP, DVP_PRIORITY_HIGHEST}, + {DVP_CORE_MCU0, DVP_PRIORITY_NONE}, + {DVP_CORE_MCU1, DVP_PRIORITY_NONE}, + {DVP_CORE_EVE, DVP_PRIORITY_NONE}, + {DVP_CORE_GPU, DVP_PRIORITY_NONE}, + {DVP_CORE_CPU, DVP_PRIORITY_LOWEST}, +}; +#elif defined(TARGET_DVP_OMAP5) +/** This defines the list of priorities for the predefined cores */ +DVP_Core_Priority_t f_corePriorities[DVP_CORE_MAX] = { + {DVP_CORE_DSP, DVP_PRIORITY_HIGHEST+DVP_PRIORITY_INC}, + {DVP_CORE_SIMCOP, DVP_PRIORITY_HIGHEST}, + {DVP_CORE_MCU0, DVP_PRIORITY_NONE}, + {DVP_CORE_MCU1, DVP_PRIORITY_NONE}, + {DVP_CORE_EVE, DVP_PRIORITY_NONE}, + {DVP_CORE_GPU, DVP_PRIORITY_NONE}, + {DVP_CORE_CPU, DVP_PRIORITY_LOWEST}, +}; +#elif defined(TARGET_DVP_OMAP6) +/** This defines the list of priorities for the predefined cores */ +DVP_Core_Priority_t f_corePriorities[DVP_CORE_MAX] = { + {DVP_CORE_DSP, DVP_PRIORITY_HIGHEST+(2*DVP_PRIORITY_INC)}, + {DVP_CORE_SIMCOP, DVP_PRIORITY_HIGHEST+(1*DVP_PRIORITY_INC)}, + {DVP_CORE_MCU0, DVP_PRIORITY_NONE}, + {DVP_CORE_MCU1, DVP_PRIORITY_NONE}, + {DVP_CORE_EVE, DVP_PRIORITY_HIGHEST}, + {DVP_CORE_GPU, DVP_PRIORITY_NONE}, + {DVP_CORE_CPU, DVP_PRIORITY_LOWEST}, +}; +#else +/** This defines the list of priorities for the predefined cores */ +DVP_Core_Priority_t f_corePriorities[DVP_CORE_MAX] = { + {DVP_CORE_DSP, DVP_PRIORITY_NONE}, + {DVP_CORE_SIMCOP, DVP_PRIORITY_NONE}, + {DVP_CORE_MCU0, DVP_PRIORITY_NONE}, + {DVP_CORE_MCU1, DVP_PRIORITY_NONE}, + {DVP_CORE_EVE, DVP_PRIORITY_NONE}, + {DVP_CORE_GPU, DVP_PRIORITY_HIGHEST}, + {DVP_CORE_CPU, DVP_PRIORITY_LOWEST}, +}; + +#endif + +#if !defined(DVP_STATIC_MANAGERS) +static int DVP_FilenameSelector(const struct dirent *de) +{ + //DVP_PRINT(DVP_ZONE_KGB, "Checking for %s against %s\n", MODULE_NAME("dvp_kgm_*"), de->d_name); + if (de && 0 == fnmatch(MODULE_NAME("dvp_kgm_*"), de->d_name, +#if defined(__QNX__) || defined(DARWIN) + FNM_PERIOD|FNM_PATHNAME)) +#else + FNM_PERIOD|FNM_FILE_NAME)) +#endif + return 1; + else + return 0; +} + +#if defined(__QNX__) +typedef int (*sorting_f)(const void *, const void *); +#else +typedef int (*sorting_f)(const struct dirent **, const struct dirent **); +#endif + +static int dirent_sort(const struct dirent **a, const struct dirent **b) +{ + //DVP_PRINT(DVP_ZONE_KGB, "Compare %s to %s\n", (*a)->d_name, (*b)->d_name); + return strcmp((*a)->d_name, (*b)->d_name); +} + +/** A dynamic loader for DVP KGM's. */ +static DVP_BOOL DVP_FindManagers(DVP_t *dvp) +{ + DVP_U32 i = 0; + struct dirent **names = NULL; + mutex_init(&dvp->mgrLock); + dvp->numMgrs = scandir(DVP_KGM_PATH, &names, DVP_FilenameSelector,(sorting_f)dirent_sort); + DVP_PRINT(DVP_ZONE_KGB, "Found %d DVP Kernel Graph Managers in the system library path %s\n", dvp->numMgrs, DVP_KGM_PATH); + dvp->managers = (DVP_GraphManager_t *)calloc(dvp->numMgrs, sizeof(DVP_GraphManager_t)); + if (dvp->managers == NULL) + { + // ERROR + for (i = 0; i < dvp->numMgrs; i++) + free(names[i]); + if (names) + free(names); + return DVP_FALSE; + } + + for (i = 0; i < dvp->numMgrs; i++) + { + // Fill in the variables... pull the name of the KGM type out of the filename + sscanf(names[i]->d_name, MODULE_NAME("dvp_kgm_%[^.]"), dvp->managers[i].name); + strncpy(dvp->managers[i].dlname, names[i]->d_name, MAX_PATH); + DVP_PRINT(DVP_ZONE_KGB, "Found DVP KGM file %s (%s)\n", dvp->managers[i].dlname, dvp->managers[i].name); + free(names[i]); + names[i] = NULL; + } + free(names); + return DVP_TRUE; +} +#else + +#define DVP_KGM_CPU_NAME (DVP_KGM_PATH MODULE_NAME("dvp_kgm_cpu")) +#define DVP_KGM_SIMCOP_NAME (DVP_KGM_PATH MODULE_NAME("dvp_kgm_simcop")) +#define DVP_KGM_DSP_NAME (DVP_KGM_PATH MODULE_NAME("dvp_kgm_dsp")) +#define DVP_KGM_OCL_NAME (DVP_KGM_PATH MODULE_NAME("dvp_kgm_ocl")) + +/** The non-dynamic version of the loader */ +static DVP_BOOL DVP_FindManagers(DVP_t *dvp) +{ + DVP_U32 i = 0; +#if defined(TARGET_DVP_OMAP4) + dvp->numMgrs = 3; +#else + dvp->numMgrs = 2; +#endif + dvp->managers = (DVP_GraphManager_t *)calloc(dvp->numMgrs, sizeof(DVP_GraphManager_t)); + if (dvp->managers != NULL) + { +#if defined(TARGET_DVP_OMAP4) + strncpy(dvp->managers[0].dlname, DVP_KGM_SIMCOP_NAME, MAX_PATH); + strncpy(dvp->managers[1].dlname, DVP_KGM_DSP_NAME, MAX_PATH); + strncpy(dvp->managers[2].dlname, DVP_KGM_CPU_NAME, MAX_PATH); +#else + strncpy(dvp->managers[0].dlname, DVP_KGM_CPU_NAME, MAX_PATH); + strncpy(dvp->managers[1].dlname, DVP_KGM_OCL_NAME, MAX_PATH); +#endif + + for (i = 0; i < dvp->numMgrs; i++) + { + // Fill in the variables... pull the name of the KGM type out of the filename + sscanf(dvp->managers[i].dlname, DVP_KGM_PATH MODULE_NAME("dvp_kgm_%[^.]"), dvp->managers[i].name); + DVP_PRINT(DVP_ZONE_KGB, "Found DVP KGM file %s (%s)\n", dvp->managers[i].dlname, dvp->managers[i].name); + } + return DVP_TRUE; + } + else + return DVP_FALSE; +} +#endif + +/** + * This will get the next highest priority enabled core in the managers list given the priority you gave it. + */ +static DVP_U32 DVP_GetNextManagerIndex(DVP_t *dvp, DVP_U32 priority, DVP_U32 *pIndex) +{ + DVP_U32 i = 0; + DVP_U32 nextHighestIndex = 0; + DVP_U32 nextHighestPriority = DVP_PRIORITY_MAX; // start off with a high number + DVP_PRINT(DVP_ZONE_KGB, "DVP Finding Next Highest Priority Manager from %u\n",priority); + for (i = 0; i < dvp->numMgrs; i++) + { + DVP_PRINT(DVP_ZONE_KGB, "DVP Checking Core %u of priority %u (%u)\n",i,dvp->managers[i].priority,nextHighestPriority); + if (dvp->managers[i].enabled == true_e && dvp->managers[i].priority <= nextHighestPriority && dvp->managers[i].priority > priority) + { + nextHighestIndex = i; + nextHighestPriority = dvp->managers[i].priority; + } + } + if (nextHighestPriority == DVP_PRIORITY_MAX) + return 0; // no lower priority core exists, return a "false" + else + { + *pIndex = nextHighestIndex; + return nextHighestPriority; + } +} + +/** + * Finds a kernel within the Kernel Graph Manager's Kernel List. + * @param pManager The manager to search. + * @param kernel The kernel to find. + * @param pIndex The output pointer to the found index if return DVP_TRUE. + */ +static DVP_BOOL DVP_GetManagerKernelIndex(DVP_GraphManager_t *pManager, DVP_KernelNode_e kernel, DVP_U32 *pIndex) +{ + DVP_U32 i = 0; + if (pManager->enabled == false_e || pManager->kernels == NULL || pManager->handle == NULL) + { + DVP_PRINT(DVP_ZONE_WARNING, "Manager %s is disabled or has no kernels!\n", pManager->name); + return DVP_FALSE; + } + for (i = 0; i < pManager->numSupportedKernels; i++) + { + //DVP_PRINT(DVP_ZONE_KGB, "Looking for kernel %u at %s[%u]=>%u (%s)\n", kernel, pManager->name, i, pManager->kernels[i].kernel, pManager->kernels[i].name); + if (pManager->kernels[i].kernel == kernel) + { + DVP_PRINT(DVP_ZONE_KGB, "Manager %s supports kernel %s at index %u\n", pManager->name, pManager->kernels[i].name, i); + *pIndex = i; + return DVP_TRUE; + } + } + return DVP_FALSE; +} + + +void DVP_KernelGraphBossDeinit(DVP_t *dvp) +{ + if (dvp) + { + DVP_U32 i = 0; + + for (i = 0; i < dvp->numMgrs; i++) + { + if (dvp->managers[i].enabled == true_e) + { + DVP_PRINT(DVP_ZONE_KGB, "Shutting down %s Manager.\n",dvp->managers[i].name); + // deinitialize the proxy manager + dvp->managers[i].calls.deinit(); + + // disconnect the RPC mechanism + dvp_rpc_core_deinit(dvp->rpc, &dvp->managers[i].rpcc); + + // disable + dvp->managers[i].enabled = false_e; + } + + // unload the proxy manager module + DVP_KernelGraphManagerUnload(&dvp->managers[i]); + } + + mutex_deinit(&dvp->mgrLock); + dvp_rpc_deinit(&dvp->rpc); + dvp_mem_deinit(&dvp->mem); + +#if defined(ANDROID) + if (dvp->loads) { + char value[PROPERTY_VALUE_MAX]; + int count; + property_get(DVP_PROPERTY_KEY, value, DVP_PROPERTY_VAL_DFT); + sscanf(value, DVP_PROPERTY_VAL_FMT, &count); + count--; + sprintf(value, DVP_PROPERTY_VAL_FMT, count); + property_set(DVP_PROPERTY_KEY, value); + DVP_PRINT(DVP_ZONE_KGB, "There are currently %d users of the DVP Load Table\n", count); + if (count == 0) // no one is using it + { + // we need to reinitialize the table. + DVP_PRINT(DVP_ZONE_KGB, "Zeroing DVP Load Table.\n"); + + dvp->loads->initialized = false_e; + semaphore_delete(&dvp->loads->sem); + memset(dvp->loads->cores, 0, sizeof(DVP_Core_Load_t) * DVP_CORE_MAX); + } + } +#endif + shared_free(&dvp->shared_memory); + memset(dvp, 0xEF, sizeof(DVP_t)); + free(dvp); + + } +} + +DVP_t *DVP_KernelGraphBossInit(DVP_U32 mask) +{ + DVP_U32 errors = 0; + DVP_U32 i,m = 0; + DVP_t *dvp = (DVP_t*)calloc(1, sizeof(DVP_t)); + + if ((mask & DVP_KGB_INIT_KGMS) && dvp && DVP_FindManagers(dvp)) + { + for (i = 0; i < dvp->numMgrs; i++) + { + DVP_PRINT(DVP_ZONE_KGB, "Possible Manager: %s\n", dvp->managers[i].dlname); + } + + dvp->shared_memory = shared_alloc(DVP_LOAD_TABLE_NAME, sizeof(DVP_Load_t)); + if (dvp->shared_memory) + { + dvp->loads = dvp->shared_memory->data; + if (dvp->loads->initialized == false_e) + { + DVP_PRINT(DVP_ZONE_KGB, "Initialized DVP Load Table\n"); + semaphore_create(&dvp->loads->sem, 1, true_e); // only 1 process can access at a time + dvp->loads->initialized = true_e; + } + else + { + DVP_PRINT(DVP_ZONE_KGB, "DVP Load Table already exists!\n"); + // it's already been initialized, but is it stale? + } +#if defined(ANDROID) + { + char value[PROPERTY_VALUE_MAX]; + int count; + property_get(DVP_PROPERTY_KEY, value, DVP_PROPERTY_VAL_DFT); + sscanf(value, DVP_PROPERTY_VAL_FMT, &count); + count++; + sprintf(value, DVP_PROPERTY_VAL_FMT, count); + property_set(DVP_PROPERTY_KEY, value); + DVP_PRINT(DVP_ZONE_KGB, "There are currently %d users of the DVP Load Table\n", count); + if (count == 1) // we're the only one + { + // we need to reinitialize the table. + DVP_PRINT(DVP_ZONE_KGB, "Reinitializing Core Load Table Values, as we are the only users\n"); + memset(dvp->loads->cores, 0, sizeof(DVP_Core_Load_t) * DVP_CORE_MAX); + } + } +#endif + } + else + { +#if !defined(ANDROID) + dvp->shared_memory = calloc(1, sizeof(DVP_Load_t)); + if (dvp->shared_memory) + { + dvp->loads = (DVP_Load_t *)dvp->shared_memory; + semaphore_create(&dvp->loads->sem, 1, false_e); + dvp->loads->initialized = true_e; + } +#else + DVP_PRINT(DVP_ZONE_ERROR, "Could not allocate shared memory, is the shm_service running?\n"); + free(dvp); + return NULL; +#endif + } + + // initializes the shared RPC elements, memory, sysmgr, etc. + dvp->rpc = dvp_rpc_init(); + + // initialize the back reference for the sublibraries. + dvp->rpc->handle = (DVP_Handle)dvp; + + // initialize all the managers + for (m = 0; m < dvp->numMgrs; m++) + { + if (DVP_KernelGraphManagerLoad(&dvp->managers[m]) == 0) + errors++; + else + { + // get the kernels that the manager supports + dvp->managers[m].numSupportedKernels = dvp->managers[m].calls.getKernels(&dvp->managers[m].kernels); + + // get the local functions for RCM Server that the manager supports if any + dvp->managers[m].calls.getLocal(&dvp->managers[m].rpci.localFunctions, &dvp->managers[m].rpci.numLocalFunctions); + + // get the remote functions for the RCM Clients that the manager will call if any + dvp->managers[m].calls.getRemote(&dvp->managers[m].rpci.remoteFunctions, &dvp->managers[m].rpci.numRemoteFunctions); + + // get the value of the remote core which this code works with + dvp->managers[m].rpci.coreEnum = dvp->managers[m].calls.getCore(); + + // set the kgm priority + dvp->managers[m].priority = DVP_PRIORITY_USER_BASE; // assume it might be a user supplied kgm + for (i = 0; i < dimof(f_corePriorities); i++) + if (dvp->managers[m].rpci.coreEnum == f_corePriorities[i].core) + dvp->managers[m].priority = f_corePriorities[i].priority; + + // create the RPC for this manager + dvp->managers[m].rpcc = dvp_rpc_core_init(dvp->rpc, &dvp->managers[m].rpci); + + // initialize the maximum load of the core which this manager controls. + if (dvp->shared_memory) + dvp->loads->cores[dvp->managers[m].rpci.coreEnum].maximumLoad = dvp->managers[m].calls.getLoad(); + + // register the KGM's restart function with RPC + dvp_rpc_restart_callback_register(dvp->rpc, dvp->managers[m].rpcc, dvp->managers[m].calls.restart, NULL); + + // give the proxy it's handles (rpcc will be NULL for A9) + if (dvp->managers[m].calls.init(dvp->rpc, dvp->managers[m].rpcc) == DVP_FALSE) + { + DVP_PRINT(DVP_ZONE_WARNING, "WARNING: DVP Kernel Graph Manager %s failed to initialize!\n", dvp->managers[m].name); + errors++; + dvp->managers[m].enabled = false_e; + } + else + { + DVP_PRINT(DVP_ZONE_KGB, "KGB: %s manager has %u kernels\n",dvp->managers[m].name, dvp->managers[m].numSupportedKernels); + dvp->managers[m].enabled = true_e; + } + } + } + } + + if ((mask & DVP_KGB_INIT_MEM_MGR) && dvp) + { + dvp->mem = dvp_mem_init(); + if (dvp->mem == NULL) { + if ((mask & DVP_KGB_INIT_KGMS)) + errors+=dvp->numMgrs; // force an error condition + else + errors++; + } + } + + DVP_PRINT(DVP_ZONE_KGB, "There were %d issues during initialization!\n", errors); + + if ( (errors >= m && (mask & DVP_KGB_INIT_KGMS)) || + (errors > 0 && !(mask & DVP_KGB_INIT_KGMS))) + { + // there's no cores available. + DVP_PRINT(DVP_ZONE_ERROR, "No cores are available for DVP to use!\n"); + DVP_KernelGraphBossDeinit(dvp); + dvp = NULL; + } + + // debugging print for comparing what the ARM and other cores think the size of the node structure is + DVP_PRINT(DVP_ZONE_KGB, "sizeof(DVP_KernelNode_t)="FMT_SIZE_T" dvp=%p\n",sizeof(DVP_KernelNode_t),dvp); + + return dvp; +} + +DVP_BOOL DVP_CommitLoad(DVP_t *dvp, DVP_KernelGraphSection_t *section) +{ + if (dvp == NULL || section == NULL || section->numNodes == 0) + return DVP_FALSE; + else + { + DVP_BOOL ret = DVP_TRUE; +#ifdef DVP_USE_LOAD_TABLE + DVP_Core_e c; + DVP_PRINT(DVP_ZONE_LOAD, "LOAD: Grabbing Shared Memory Semaphore for section %p!\n",section); + semaphore_wait(&dvp->loads->sem); + // accumulate each coreLoad in the section into + // the load's currentLoad as long as it's below the maximumLoad. + for (c = DVP_CORE_MIN + 1; c < DVP_CORE_MAX; c++) + { + dvp->loads->cores[c].currentLoad += section->coreLoad[c]; + DVP_PRINT(DVP_ZONE_LOAD, "LOAD: Attempting to commit core %u load %4u\n", c, section->coreLoad[c]); + if (dvp->loads->cores[c].currentLoad > dvp->loads->cores[c].maximumLoad) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: Could not commit core load of %d as it exceeds maximum value of %d!\n", section->coreLoad[c], dvp->loads->cores[c].maximumLoad); + // unwind the loads + for (/*c=c*/; c > DVP_CORE_MIN; c--) + dvp->loads->cores[c].currentLoad -= section->coreLoad[c]; + ret = DVP_FALSE; + break; + } + } + semaphore_post(&dvp->loads->sem); +#endif + + return ret; + } +} + +void DVP_DecommitLoad(DVP_t *dvp, DVP_KernelGraphSection_t *section) +{ + if (dvp == NULL || section == NULL) + return; + else + { +#ifdef DVP_USE_LOAD_TABLE + DVP_Core_e c; + semaphore_wait(&dvp->loads->sem); + // remove the section's load from the cores + for (c = DVP_CORE_MIN + 1; c < DVP_CORE_MAX; c++) + dvp->loads->cores[c].currentLoad -= section->coreLoad[c]; + semaphore_post(&dvp->loads->sem); +#endif + } +} + +DVP_U32 DVP_ConfigureNodes(DVP_t *dvp, DVP_KernelGraphSection_t *section, DVP_BOOL force) +{ + DVP_U32 m = 0, n = 0, f = 0, faults = 0; + DVP_KernelNode_t *pNodes = section->pNodes; + DVP_U32 numNodes = section->numNodes; + clock_t total = 0; + + if (dvp == NULL || section == NULL) + return 1; + + for (n = 0; n < numNodes; n++) + { + DVP_PrintNode(DVP_ZONE_KGB, §ion->pNodes[n]); + if (pNodes[n].header.configured == DVP_FALSE || force == DVP_TRUE) + { + DVP_U32 triedMgrs = 0; + DVP_U32 mgrPriority = 0; + DVP_BOOL isKernelSupported = DVP_FALSE; + rtime_t diff, start = rtimer_now(); + + // did the user intentionally set an affinity? + if (pNodes[n].header.affinity != DVP_CORE_MIN) + { + DVP_BOOL found = DVP_FALSE; // haven't found the right manager yet + + // find which manager works on the desired core + for (m = 0; m < dvp->numMgrs; m++) + { + if (dvp->managers[m].calls.getCore() == pNodes[n].header.affinity) + { + // remember the index + pNodes[n].header.mgrIndex = m; + // get the function index + isKernelSupported = DVP_GetManagerKernelIndex(&dvp->managers[m], pNodes[n].header.kernel, &f); + if (isKernelSupported == DVP_TRUE) + { + DVP_PRINT(DVP_ZONE_KGB, "Node[%u] will be executed on %s core as %s [AFFINITY]\n", n, dvp->managers[m].name, dvp->managers[m].kernels[f].name); + found = DVP_TRUE; + // accumulate the load value for this kernel into the section's core loads + section->coreLoad[pNodes[n].header.affinity] += dvp->managers[m].kernels[f].load; + break; + } + } + } + if (found == DVP_TRUE) + { + pNodes[n].header.configured = DVP_TRUE; + continue; // don't try to set the manager based on priority or load + } + else + { + // if we've run out of managers to check (or nothing matched) + // we ignore the affinity in future checks + pNodes[n].header.affinity = DVP_CORE_MIN; + } + } + // determine which manager will execute the function based on the priority of the manager then of the kernel. + do { + mgrPriority = DVP_GetNextManagerIndex(dvp, mgrPriority, &m); + if (mgrPriority != 0) + isKernelSupported = DVP_GetManagerKernelIndex(&dvp->managers[m], pNodes[n].header.kernel, &f); + if (mgrPriority == 0 || isKernelSupported == DVP_FALSE) + { + DVP_PRINT(DVP_ZONE_WARNING, "KGB: WARNING! Kernel %u is not supported on %s manager\n", pNodes[n].header.kernel,dvp->managers[m].name); + triedMgrs++; + } + else + { + // remember the manager index and function index. + pNodes[n].header.mgrIndex = m; + pNodes[n].header.funcIndex = f; + + // accumulate the load into the section's coreLoad + section->coreLoad[dvp->managers[m].calls.getCore()] += dvp->managers[m].kernels[f].load; + + DVP_PRINT(DVP_ZONE_KGB, "Node[%u] will be executed on %s core as %s with %u Mhz\n", n, dvp->managers[m].name, dvp->managers[m].kernels[f].name, dvp->managers[m].kernels[f].load); + break; + } + } while (triedMgrs < dvp->numMgrs); + if (triedMgrs >= dvp->numMgrs) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! No core supports kernel %u!\n", pNodes[n].header.kernel); + faults++; + break; + } + + // once it's configured don't do it again! (loads may change that though) + pNodes[n].header.configured = DVP_TRUE; + + diff = rtimer_now() - start; + total += diff; + } + } + if (total > 0) + { + DVP_PRINT(DVP_ZONE_PERF, "KGB: Graph Setup took %lf secs\n", (float)total/rtimer_freq()); + } + return faults; +} + +DVP_U32 DVP_KernelGraphBoss(DVP_t *dvp, DVP_KernelGraphSection_t *section, DVP_BOOL sync) +{ + DVP_U32 n = 0; // node index + DVP_U32 faults = 0; + DVP_U32 processed = 0; + DVP_KernelNode_t *pNodes = section->pNodes; + DVP_U32 numNodes = section->numNodes; + DVP_Perf_t *perf = &(section->perf); + + DVP_PRINT(DVP_ZONE_KGB, "Executing Section %p with %u nodes (%s)\n", section, section->numNodes, (sync?"SYNC":"QUEUED")); + + DVP_PerformanceStart(perf); + + // configure the nodes + faults = DVP_ConfigureNodes(dvp, section, DVP_FALSE); + + // we're going to try this over and over until we can execute with no faults in configuration. + do { + if (faults == 0 && DVP_CommitLoad(dvp, section) == DVP_TRUE) + { + DVP_PRINT(DVP_ZONE_KGB, "KGB: Executing Graph!\n"); + for (n = 0; n < numNodes; /* no inc */) + { + DVP_U32 targetMgrIndex = pNodes[n].header.mgrIndex; + DVP_U32 subgraphNumNodes = 1; // at least one node is on this core... + DVP_U32 numNodesProcessed = 0; +#ifdef DVP_OPTIMIZED_GRAPHS + DVP_U32 i; + // determine how many nodes forward of the current node are on the same core... + for (i = n+1; i < numNodes; i++) + { + if (pNodes[i].header.mgrIndex == targetMgrIndex) + subgraphNumNodes++; + else + break; + } +#endif + DVP_PRINT(DVP_ZONE_KGB, "KGB: Executing %u nodes on %s core\n", subgraphNumNodes, dvp->managers[pNodes[n].header.mgrIndex].name); + numNodesProcessed = dvp->managers[pNodes[n].header.mgrIndex].calls.manager(pNodes,n,subgraphNumNodes, sync); + // increment the processed by the number literally processed (regardless of errors) + processed += numNodesProcessed; + DVP_PRINT(DVP_ZONE_KGB, "KGB: Executed %u nodes on %s core (%u total processed)\n", numNodesProcessed, dvp->managers[pNodes[n].header.mgrIndex].name, processed); + // increment the graph by the number of nodes given the subgraph! + n += subgraphNumNodes; // we can't use the processed number here. +#ifndef DVP_CONTINUE_ON_ERRORS + if (numNodesProcessed != subgraphNumNodes) + break; // something went wrong in the graph +#endif + } + DVP_DecommitLoad(dvp, section); + // success! + break; + } + else + { + DVP_PRINT(DVP_ZONE_WARNING, "KGB-RM: Graph could not be executed due to a shortage of resources.\n"); + // reconfigure the graph + faults = DVP_ConfigureNodes(dvp, section, DVP_TRUE); + } + } while (faults == 0); + + // if there are faults it should stop the processing of the graph. + if (faults > 0) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! There are unhandled nodes in the graph. Processing can not continue!\n"); + } + + DVP_PerformanceStop(perf); + + DVP_PRINT(DVP_ZONE_KGB, "KGB: Processed %u nodes!\n", processed); + +#if defined(GRE_DEBUG) && (DVP_ZONE_LOAD != 0) + { + DVP_Core_e c; + //semaphore_wait(&dvp->loads->sem); + for (c = DVP_CORE_MIN + 1; c < DVP_CORE_MAX; c++) + { + DVP_PRINT(DVP_ZONE_LOAD, "Core[%u] Current Load=%4u Maximum Load=%4u\n", c, dvp->loads->cores[c].currentLoad, dvp->loads->cores[c].maximumLoad); + } + //semaphore_post(&dvp->loads->sem); + } +#endif + + return processed; +} + + +void DVP_SetMaxLoad(DVP_t *dvp, DVP_Core_e core, DVP_U32 load) +{ + if(dvp) + { + DVP_U32 m; + for (m = 0; m < dvp->numMgrs; m++) + { + if (dvp->managers[m].enabled && dvp->managers[m].calls.getCore() == core) + { +#if defined(DVP_USE_LOAD_TABLE) + if (dvp->loads->initialized) + { + semaphore_wait(&dvp->loads->sem); + dvp->loads->cores[core].maximumLoad = load; + semaphore_post(&dvp->loads->sem); + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: Load Table is not initialized!\n"); + } +#endif + DVP_PRINT(DVP_ZONE_LOAD, "DVP: Core[%u] now has table max load of %u\n", core, load); + } + } + } +} + +DVP_U32 DVP_GetMaxLoad(DVP_t *dvp, DVP_Core_e core, DVP_U32 *pCoreMax) +{ + DVP_U32 load = 0; + if(dvp) + { + DVP_U32 m; + for (m = 0; m < dvp->numMgrs; m++) + { + if (dvp->managers[m].enabled && dvp->managers[m].calls.getCore() == core) + { + *pCoreMax = dvp->managers[m].calls.getLoad(); +#if defined(DVP_USE_LOAD_TABLE) + if (dvp->loads->initialized) + { + semaphore_wait(&dvp->loads->sem); + load = dvp->loads->cores[core].maximumLoad; + semaphore_post(&dvp->loads->sem); + } +#endif + DVP_PRINT(DVP_ZONE_LOAD, "DVP: Core[%u] has table max load of %u and HW max load of %u\n", core, load, *pCoreMax); + } + } + } + return load; +} + +void DVP_QueryCore(DVP_t *dvp, DVP_Core_e core, DVP_CoreInfo_t *info) +{ + DVP_U32 m = 0; + DVP_BOOL found = DVP_FALSE; + if (info) + { + for (m = 0; m < dvp->numMgrs; m++) + { + DVP_PRINT(DVP_ZONE_KGB, "Quering Mgr %u for Core %d\n", m, core); + if (dvp->managers[m].enabled == true_e && dvp->managers[m].calls.getCore() == core) + { + DVP_U32 k = 0; + info->enabled = DVP_TRUE; + info->numKernels += dvp->managers[m].numSupportedKernels; + info->kernels = dvp->managers[m].kernels; + found = DVP_TRUE; + DVP_PRINT(DVP_ZONE_KGB, "Scanning Mgr: %u for which kernel libraries are supported out of %u kernels\n", + m, dvp->managers[m].numSupportedKernels); + for (k = 0; k < dvp->managers[m].numSupportedKernels; k++) + { + DVP_KernelNode_e kernel = dvp->managers[m].kernels[k].kernel; + DVP_PRINT(DVP_ZONE_KGB, "\tKernel: 0x%08x\n", kernel); + if (kernel > DVP_KN_LIBRARY_START) + { + DVP_U32 lib = DVP_KN_LIBRARY_MASK(kernel); + DVP_PRINT(DVP_ZONE_KGB, "Mgr: %u Kernel:%x is in Library: 0x%x\n", m, kernel, lib); + info->libraries[lib] = DVP_TRUE; + } + } + } + } + } + if (found == DVP_FALSE) + { + info->enabled = DVP_FALSE; + } +} + +DVP_BOOL DVP_QueryCoreForKernel(DVP_t *dvp, DVP_KernelNode_e kernel, DVP_Core_e core) +{ + DVP_U32 m = 0; + for (m = 0; m < dvp->numMgrs; m++) + { + DVP_PRINT(DVP_ZONE_KGB, "Checking Mgr %u for Core %d\n", m, core); + if (dvp->managers[m].enabled == true_e && dvp->managers[m].calls.getCore() == core) + { + DVP_U32 k; + for (k = 0; k < dvp->managers[m].numSupportedKernels; k++) + { + if (kernel == dvp->managers[m].kernels[k].kernel) + { + return DVP_TRUE; + } + } + } + } + return DVP_FALSE; +} diff --git a/source/dvp/dvp_kgraph/dvp_kgraph.c b/source/dvp/dvp_kgraph/dvp_kgraph.c new file mode 100644 index 0000000..441fb2b --- /dev/null +++ b/source/dvp/dvp_kgraph/dvp_kgraph.c @@ -0,0 +1,614 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +// external +#include +#include +// internal +#include +#include + +#define MAX_SECTIONS (4) // a silly upper limit +#define MAX_QUEUE_DEPTH (2) + +//****************************************************************************** +// TYPEDEFS +//****************************************************************************** + +typedef struct _dvp_kgw_data_t { + semaphore_t sem; + uint32_t count; +} DVP_KernelGraphWorker_t; + +typedef struct _dvp_kgc_t { + thread_t hThread; + DVP_t *dvp; + DVP_KernelGraph_t *graph; + DVP_KernelGraphSection_t *section; + DVP_U32 numNodes; + DVP_U32 index; + mutex_t *lock; + void *cookie; + DVP_SectionComplete_f callback; +} DVP_KernelGraphCollector_t; + + +//****************************************************************************** +// GLOBAL VARIABLES +//****************************************************************************** + +uint32_t dvp_zone_mask = 0x3; + +#if defined(DVP_RUNTIME_DEBUG) +#pragma message("DVP Debugging in RUNTIME mode! export DVP_ZONE_MASK to affect.") +#endif + +//****************************************************************************** +// LOCAL VARIABLES +//****************************************************************************** + +static threadpool_t *pool; +static DVP_KernelGraphCollector_t collectors[MAX_SECTIONS]; +static DVP_KernelGraphWorker_t workData; + +//****************************************************************************** +// LOCAL FUNCTIONS +//****************************************************************************** + +static bool_e dvp_kernelgraph_worker(threadpool_worker_t *worker) +{ + DVP_KernelGraphWorker_t *kgw = (DVP_KernelGraphWorker_t *)worker->arg; + DVP_KernelGraphCollector_t *collector = (DVP_KernelGraphCollector_t *)worker->data; + DVP_U32 numNodesExecuted = 0; + DVP_PRINT(DVP_ZONE_KGAPI, "DVP KGW %u Thread "THREAD_FMT" Running!\n", worker->index, worker->handle); + + numNodesExecuted = DVP_KernelGraphBoss(collector->dvp,collector->section, DVP_FALSE); + + // make the callback thread-safe + semaphore_wait(&kgw->sem); + kgw->count++; // increment the number of sections processed. + if (collector->callback) + collector->callback(collector->cookie, collector->graph, collector->index, numNodesExecuted); + DVP_PRINT(DVP_ZONE_KGAPI, "DVP KGW %u Thread "THREAD_FMT" Finished! (Nodes: %u Count: %u)\n", worker->index, worker->handle, numNodesExecuted, kgw->count); + semaphore_post(&kgw->sem); + + if (numNodesExecuted > 0) + return true_e; + else + return false_e; +} + +static void dvp_graphlock_init(DVP_GraphLock_t *gl) +{ + gl->m_enabled = true_e; + gl->m_count = 0; + mutex_init(&gl->m_lock); + event_init(&gl->m_wait, false_e); + event_set(&gl->m_wait); +} + +static DVP_BOOL dvp_graph_lock(DVP_GraphLock_t *gl) +{ + mutex_lock(&gl->m_lock); + if (gl->m_enabled) + { + gl->m_count++; + event_reset(&gl->m_wait); + } + mutex_unlock(&gl->m_lock); + return (gl->m_enabled == true_e ? DVP_TRUE : DVP_FALSE); +} + +static void dvp_graph_unlock(DVP_GraphLock_t *gl) +{ + mutex_lock(&gl->m_lock); + if (gl->m_enabled) + { + gl->m_count--; + if (gl->m_count == 0) + event_set(&gl->m_wait); + } + mutex_unlock(&gl->m_lock); +} + +static void dvp_graphlock_wait(DVP_GraphLock_t *gl) +{ + event_wait(&gl->m_wait, EVENT_FOREVER); + mutex_lock(&gl->m_lock); + gl->m_enabled = false_e; + mutex_unlock(&gl->m_lock); +} + +static void dvp_graphlock_deinit(DVP_GraphLock_t *gl) +{ + gl->m_enabled = false_e; + gl->m_count = 0; + event_deinit(&gl->m_wait); + mutex_deinit(&gl->m_lock); +} + +//****************************************************************************** +// GLOBAL FUNCTIONS +//****************************************************************************** + +DVP_Handle DVP_KernelGraph_Init() +{ + DVP_t *dvp = NULL; + semaphore_create(&workData.sem, 1, false_e); + workData.count = 0; + memset(collectors, 0, sizeof(DVP_KernelGraphCollector_t) * MAX_SECTIONS); + pool = threadpool_create(MAX_SECTIONS, MAX_QUEUE_DEPTH, sizeof(DVP_KernelGraphCollector_t), dvp_kernelgraph_worker, &workData); + dvp = DVP_KernelGraphBossInit(DVP_KGB_INIT_ALL); + if (dvp) + dvp_graphlock_init(&dvp->graphLock); + return (DVP_Handle)dvp; +} + +DVP_Handle DVP_MemImporter_Create() +{ + DVP_t *dvp = NULL; + dvp = DVP_KernelGraphBossInit(DVP_KGB_INIT_MEM_MGR); + return (DVP_Handle)dvp; +} + +void DVP_KernelGraph_Deinit(DVP_Handle handle) +{ + DVP_t *dvp = (DVP_t *)handle; + DVP_PRINT(DVP_ZONE_KGAPI, "Deconstructing DVP=%p! This will block until graphs have completed!\n",dvp); + if (dvp) { + dvp_graphlock_wait(&dvp->graphLock); // this will block until all graphs have exited. + DVP_PRINT(DVP_ZONE_KGAPI, "Graphs should all be complete!\n"); + // if the thread pools are active, tear them down, then deinit DVP + threadpool_destroy(pool); + semaphore_delete(&workData.sem); + dvp_graphlock_deinit(&dvp->graphLock); + DVP_KernelGraphBossDeinit(dvp); + } +} + +void DVP_MemImporter_Free(DVP_Handle handle) +{ + DVP_t *dvp = (DVP_t *)handle; + if (dvp) { + DVP_KernelGraphBossDeinit(dvp); + } +} + +DVP_U32 DVP_KernelGraph_Process(DVP_Handle handle, DVP_KernelGraph_t *pGraph, void *cookie, DVP_SectionComplete_f callback) +{ + DVP_t *dvp = (DVP_t *)handle; + DVP_U32 numSectionsRun = 0; + DVP_U32 section = 0; + DVP_U32 order = 0; + DVP_U32 numOrder = 0; + DVP_KernelGraphSection_t *ppSections[MAX_SECTIONS]; // only up to MAX_SECTIONS in parallel. + + // make sure to "lock the graph", if we can't then we're tearing down. + if (dvp_graph_lock(&dvp->graphLock) == DVP_FALSE) + return 0; + + DVP_PerformanceStart(&(pGraph->totalperf)); + + for (order = 0; /* no order limit */; order++) + { + // initialize each cycle + numOrder = 0; + memset(ppSections, 0, sizeof(DVP_KernelGraphSection_t *)*MAX_SECTIONS); + + // determine how many graph want to execute in this order. + for (section = 0; section < pGraph->numSections; section++) + { + // if the section is of the correct order, the number of orders is less than the max and if the section is not skipped + if (pGraph->order[section] == order && numOrder < MAX_SECTIONS && pGraph->sections[section].skipSection == DVP_FALSE) + { + ppSections[numOrder] = &pGraph->sections[section]; + numOrder++; + } + else if (numOrder >= MAX_SECTIONS) + { + DVP_PRINT(DVP_ZONE_ERROR, "Can't run more than %u graphs in parallel at any given time\n", MAX_SECTIONS); + return numSectionsRun; + } + else if (pGraph->sections[section].skipSection == DVP_TRUE) + { + DVP_PRINT(DVP_ZONE_KGAPI, "Skipping Graph Section %p[%u]\n", &pGraph->sections[section], section); + } + } + + DVP_PRINT(DVP_ZONE_KGAPI, "DVP_KernelGraphs => Order %u has %u sections\n", order, numOrder); + + if (numOrder > 1) // one or multiple sections are going to run in parallel. + { + DVP_U32 s,g = 0; + void *workitems[dimof(collectors)]; + + for (g = 0; g < numOrder; g++) + { + collectors[g].dvp = dvp; + collectors[g].graph = pGraph; + collectors[g].section = ppSections[g]; + for (s = 0; s < pGraph->numSections; s++) + if (collectors[g].section->pNodes == pGraph->sections[s].pNodes) + collectors[g].index = s; + collectors[g].cookie = cookie; + collectors[g].callback = callback; + workitems[g] = &collectors[g]; + } + + if (threadpool_issue(pool, workitems, numOrder) == true_e) + { + DVP_PRINT(DVP_ZONE_KGAPI, "DVP_KernelGraphs issued %u sections to execute in parallel\n", numOrder); + } + + if (threadpool_complete(pool, true_e) == true_e) + { + DVP_PRINT(DVP_ZONE_KGAPI, "DVP_KernelGraphs completed %u sections\n", numOrder); + numSectionsRun += g; + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: FAILED TO WAIT FOR SECTIONS TO COMPLETE!\n"); + } + } + else if (numOrder == 1) // special optimized case + { + DVP_U32 numNodesExecuted = 0; + DVP_PRINT(DVP_ZONE_KGAPI, "Optimized single section mode!\n"); + + // force inline or synchronous execution. + // This thread will do the local computation or call remote cores. + numNodesExecuted = DVP_KernelGraphBoss(dvp,ppSections[0], DVP_TRUE); + if (callback) + { + // find the section index + for (section = 0; section < pGraph->numSections; section++) + if (ppSections[0] == &pGraph->sections[section]) + break; + callback(cookie, pGraph, section, numNodesExecuted); + } + // increment the number of graphs ran regardless of the + // presence of a callback. + numSectionsRun++; + } + else + break; // if no graphs of this order, then exit. + } + DVP_PerformanceStop(&(pGraph->totalperf)); + dvp_graph_unlock(&dvp->graphLock); + return numSectionsRun; +} + + +DVP_U32 DVP_GetCoreCapacity(DVP_Handle handle, DVP_Core_e core) +{ + if (handle) + { + DVP_t *dvp = (DVP_t *)handle; + DVP_U32 hwMaxLoad = 0; + DVP_U32 newMaxload = DVP_GetMaxLoad(dvp, core, &hwMaxLoad); + if (hwMaxLoad != 0) { + return (newMaxload * DVP_CAPACITY_DATA_RANGE)/hwMaxLoad; + } + } + return 0; +} + +void DVP_SetCoreCapacity(DVP_Handle handle, DVP_Core_e core, DVP_U32 limit) +{ + if (handle) + { + DVP_t *dvp = (DVP_t *)handle; + DVP_U32 newMaxLoad, hwMaxLoad = 0; + DVP_GetMaxLoad(dvp, core, &hwMaxLoad); + if (limit > DVP_CAPACITY_DATA_RANGE) + limit = DVP_CAPACITY_DATA_RANGE; + newMaxLoad = (limit * hwMaxLoad)/DVP_CAPACITY_DATA_RANGE; + DVP_SetMaxLoad(dvp, core, newMaxLoad); + } +} + +void DVP_Perf_Clear(DVP_Perf_t *perf) +{ + memset(perf, 0, sizeof(DVP_Perf_t)); + perf->rate = rtimer_freq(); + perf->minTime = MAX_RTIMER_T; +} + +void DVP_PerformanceClear(DVP_Handle handle __attribute__ ((unused)), DVP_KernelNode_t *pNodes, DVP_U32 numNodes) +{ + DVP_U32 i = 0; + for (i = 0; i < numNodes; i++) + { + DVP_Perf_Clear(&pNodes[i].header.perf); + } +} + +void DVP_PerformanceStart(DVP_Perf_t *pPerf) +{ + if (pPerf) + pPerf->tmpTime = rtimer_now(); +} + +void DVP_PerformanceStop(DVP_Perf_t *pPerf) +{ + if (pPerf) + { + rtime_t now = rtimer_now(); + pPerf->tmpTime = (now - pPerf->tmpTime); + pPerf->numTimes++; + if (pPerf->minTime > pPerf->tmpTime) + pPerf->minTime = pPerf->tmpTime; + if (pPerf->maxTime < pPerf->tmpTime) + pPerf->maxTime = pPerf->tmpTime; + pPerf->sumTime += pPerf->tmpTime; + pPerf->avgTime = pPerf->sumTime/pPerf->numTimes; + } +} + +void DVP_PerformancePrint(DVP_Perf_t *pPerf, const char *prefix) +{ + pPerf = pPerf; // warnings + prefix = prefix; // warnings + DVP_PRINT(DVP_ZONE_PERF, "%s: count=%9u (us) min="FMT_U64(14)" max="FMT_U64(14)" avg="FMT_U64(14)" sum="FMT_U64(14)" last="FMT_U64(14)"\n", prefix, + pPerf->numTimes, + (DVP_U64)rtimer_to_us(pPerf->minTime), + (DVP_U64)rtimer_to_us(pPerf->maxTime), + (DVP_U64)rtimer_to_us(pPerf->avgTime), + (DVP_U64)rtimer_to_us(pPerf->sumTime), + (DVP_U64)rtimer_to_us(pPerf->tmpTime)); +} + +void DVP_PrintPerformanceCSV(DVP_Handle handle, DVP_KernelNode_t *pNodes, DVP_U32 numNodes) +{ + DVP_U32 i = 0; + DVP_t *dvp = (DVP_t *)handle; + + // print out the performance info + dvp = dvp; // warnings + pNodes = pNodes; // warnings + + DVP_PRINT(DVP_ZONE_PERF, "Node, %6s, %8s, %14s, %14s, %14s, %14s,\n", + "Core", "Kernel", "Minmum","Maximum","Average","Summation"); + for (i = 0; i < numNodes; i++) + { + DVP_PRINT(DVP_ZONE_PERF, "%4u, %6s[%u], %8u, "FMT_U64(14)", "FMT_U64(14)", "FMT_U64(14)", "FMT_U64(14)",\n", i, dvp->managers[pNodes[i].header.mgrIndex].name, pNodes[i].header.mgrIndex, pNodes[i].header.kernel, + (DVP_U64)rtimer_from_rate_to_us(pNodes[i].header.perf.minTime, pNodes[i].header.perf.rate), + (DVP_U64)rtimer_from_rate_to_us(pNodes[i].header.perf.maxTime, pNodes[i].header.perf.rate), + (DVP_U64)rtimer_from_rate_to_us(pNodes[i].header.perf.avgTime, pNodes[i].header.perf.rate), + (DVP_U64)rtimer_from_rate_to_us(pNodes[i].header.perf.sumTime, pNodes[i].header.perf.rate)); + } +} + +void DVP_PrintPerformanceSection(DVP_Handle handle, DVP_KernelGraphSection_t *pSection) +{ + DVP_t *dvp = (DVP_t *)handle; + DVP_KernelNode_t *pNodes = pSection->pNodes; + DVP_U32 numNodes = pSection->numNodes; + DVP_Perf_t *perf = &pSection->perf; + DVP_U32 i; + DVP_Core_e c; + DVP_Perf_t overhead; + + DVP_Perf_Clear(&overhead); + overhead.minTime = 0; + + dvp = dvp; // warnings + + DVP_PRINT(DVP_ZONE_PERF, "rtimer_freq() = "FMT_RTIMER_T"\n", rtimer_freq()); + DVP_PRINT(DVP_ZONE_PERF, "Node Performance (us):\n"); + DVP_PRINT(DVP_ZONE_PERF, "Node, %9s, %10s, %14s, %14s, %14s, %14s, %14s\n", + "Core", "Kernel", "Minmum","Maximum","Average","Summation", "Error Code"); + for (i = 0; i < numNodes; i++) + { + // if the minimum was never set, set it to zero now. + if (pNodes[i].header.perf.minTime == MAX_RTIMER_T) + pNodes[i].header.perf.minTime = 0; + + overhead.minTime += rtimer_from_rate_to_us(pNodes[i].header.perf.minTime, pNodes[i].header.perf.rate); + overhead.avgTime += rtimer_from_rate_to_us(pNodes[i].header.perf.avgTime, pNodes[i].header.perf.rate); + overhead.maxTime += rtimer_from_rate_to_us(pNodes[i].header.perf.maxTime, pNodes[i].header.perf.rate); + overhead.sumTime += rtimer_from_rate_to_us(pNodes[i].header.perf.sumTime, pNodes[i].header.perf.rate); + + DVP_PRINT(DVP_ZONE_PERF, "%4u, %6s[%u], 0x%08x, "FMT_U64(14)", "FMT_U64(14)", "FMT_U64(14)", "FMT_U64(14)", %14d\n", + i, dvp->managers[pNodes[i].header.mgrIndex].name, + pNodes[i].header.mgrIndex, + pNodes[i].header.kernel, + (DVP_U64)rtimer_from_rate_to_us(pNodes[i].header.perf.minTime, pNodes[i].header.perf.rate), + (DVP_U64)rtimer_from_rate_to_us(pNodes[i].header.perf.maxTime, pNodes[i].header.perf.rate), + (DVP_U64)rtimer_from_rate_to_us(pNodes[i].header.perf.avgTime, pNodes[i].header.perf.rate), + (DVP_U64)rtimer_from_rate_to_us(pNodes[i].header.perf.sumTime, pNodes[i].header.perf.rate), + pNodes[i].header.error); + } + + DVP_PRINT(DVP_ZONE_PERF, "Graph Section Perf (us):\n"); + DVP_PRINT(DVP_ZONE_PERF, "%4u, "FMT_U64(32)", "FMT_U64(14)", "FMT_U64(14)", "FMT_U64(14)",\n", numNodes, + (DVP_U64)rtimer_to_us(perf->minTime), + (DVP_U64)rtimer_to_us(perf->maxTime), + (DVP_U64)rtimer_to_us(perf->avgTime), + (DVP_U64)rtimer_to_us(perf->sumTime)); + overhead.minTime = rtimer_to_us(perf->minTime) - overhead.minTime; + overhead.maxTime = rtimer_to_us(perf->maxTime) - overhead.maxTime; + overhead.avgTime = rtimer_to_us(perf->avgTime) - overhead.avgTime; + overhead.sumTime = rtimer_to_us(perf->sumTime) - overhead.sumTime; + DVP_PRINT(DVP_ZONE_PERF, "Section Overhead (Threading + IPC):\n"); + DVP_PRINT(DVP_ZONE_PERF, "%4u, "FMT_U64(32)", "FMT_U64(14)", "FMT_U64(14)", "FMT_U64(14)",\n", numNodes, + (DVP_U64)overhead.minTime, + (DVP_U64)overhead.maxTime, + (DVP_U64)overhead.avgTime, + (DVP_U64)overhead.sumTime); + + DVP_PRINT(DVP_ZONE_PERF, "Graph Section Core Load:\n"); + for (c = DVP_CORE_MIN + 1; c < DVP_CORE_MAX; c++) + { + DVP_PRINT(DVP_ZONE_PERF, "[%u] %4u\n", c, pSection->coreLoad[c]); + } +} + +void DVP_PrintPerformanceGraph(DVP_Handle handle, DVP_KernelGraph_t *pGraph) +{ + DVP_Perf_t *perf = &pGraph->totalperf; + DVP_U32 totalNumNodes = 0; + DVP_U32 i = 0; + + perf = perf; // warnings + + for (i = 0; i < pGraph->numSections; i++) + { + DVP_PrintPerformanceSection(handle, &pGraph->sections[i]); + totalNumNodes += pGraph->sections[i].numNodes; + } + + DVP_PRINT(DVP_ZONE_PERF, "Overall Graph %p Perf (us):\n", pGraph); + DVP_PRINT(DVP_ZONE_PERF, "%4u, "FMT_U64(32)", "FMT_U64(14)", "FMT_U64(14)", "FMT_U64(14)",\n", totalNumNodes, + (DVP_U64)rtimer_to_us(perf->minTime), + (DVP_U64)rtimer_to_us(perf->maxTime), + (DVP_U64)rtimer_to_us(perf->avgTime), + (DVP_U64)rtimer_to_us(perf->sumTime)); + +} + +void DVP_PrintNode(DVP_U32 zone, DVP_KernelNode_t *node) +{ + if (zone && node) + { + DVP_PRINT(zone, "DVP_KernelNode_t:%p KERN:%08x AFFINITY:%d\n", node, node->header.kernel, node->header.affinity); + } +} + +void DVP_PrintImage(DVP_U32 zone, DVP_Image_t *img) +{ + if (zone && img) + { + char fcc[5]; + strncpy(fcc, (char *)&img->color, sizeof(fcc)); + fcc[4] = '\0'; + DVP_PRINT(zone, + "DVP_Image_t:%p TYPE:%d DATA[%u]{%p, %p, %p} BASE[%u]{%p, %p, %p} W,H=%u,%u dX,dY=%d,%d x0,y0=%u,%u FOURCC=%4s (0x%08x) SIZE:%u RESV:%p FLUSH=%s INV=%s\n", + img, img->memType, img->planes, img->pData[0], img->pData[1], img->pData[2], + img->planes, img->pBuffer[0], img->pBuffer[1], img->pBuffer[2], + img->width, img->height, img->x_stride, img->y_stride, img->x_start, img->y_start, + fcc, img->color, img->numBytes,img->reserved, + (img->skipCacheOpFlush?"FALSE":"TRUE"), + (img->skipCacheOpInval?"FALSE":"TRUE")); + } +} + +void DVP_PrintBuffer(DVP_U32 zone, DVP_Buffer_t *buf) +{ + if (zone && buf) + { + DVP_PRINT(zone, "DVP_Buffer_t:%p TYPE:%d DATA:%p ELEM:%u BYTES:%u RESV:%p FLUSH=%s INV=%s\n", + buf, + buf->memType, + buf->pData, + buf->elemSize, + buf->numBytes, + buf->reserved, + (buf->skipCacheOpFlush?"FALSE":"TRUE"), + (buf->skipCacheOpInval?"FALSE":"TRUE")); + } +} + +void DVP_QuerySystem(DVP_Handle handle, const DVP_CoreInfo_t info[DVP_CORE_MAX]) +{ + DVP_t *dvp = (DVP_t *)handle; + DVP_Core_e c; + for (c = DVP_CORE_MIN+1; c < DVP_CORE_MAX; c++) + { + DVP_QueryCore(dvp, c, (DVP_CoreInfo_t *)&info[c]); + } +} + +void DVP_QueryKernel(DVP_Handle handle, DVP_KernelNode_e kernel, DVP_BOOL present[DVP_CORE_MAX]) +{ + DVP_t *dvp = (DVP_t *)handle; + DVP_Core_e c; + for (c = DVP_CORE_MIN+1; c < DVP_CORE_MAX; c++) + { + present[c] = DVP_QueryCoreForKernel(dvp, kernel, c); + } +} + +DVP_Error_e DVP_KernelGraphSection_Init(DVP_Handle handle, + DVP_KernelGraph_t *graph, + DVP_U32 sectionIndex, + DVP_KernelNode_t *pNodes, + DVP_U32 numNodes) +{ + DVP_t *dvp = (DVP_t *)handle; + if (dvp && graph && sectionIndex < graph->numSections) + { + graph->sections[sectionIndex].pNodes = pNodes; + graph->sections[sectionIndex].numNodes = numNodes; + return DVP_SUCCESS; + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: Invalid Parameters to %s!\n", __FUNCTION__); + return DVP_ERROR_INVALID_PARAMETER; + } +} + +void DVP_KernelGraph_Free(DVP_Handle handle, DVP_KernelGraph_t *graph) +{ + DVP_t *dvp = (DVP_t *)handle; + if (dvp && graph) + { + free(graph->sections); + free(graph->order); + free(graph); + } +} + +DVP_KernelGraph_t *DVP_KernelGraph_Alloc(DVP_Handle handle, DVP_U32 numSections) +{ + DVP_t *dvp = (DVP_t *)handle; + if (dvp) + { + DVP_KernelGraph_t *graph = (DVP_KernelGraph_t *)calloc(1, sizeof(DVP_KernelGraph_t)); + if (graph && numSections > 0) + { + DVP_Perf_t perf = DVP_PERF_INIT; + graph->sections = (DVP_KernelGraphSection_t *)calloc(numSections, sizeof(DVP_KernelGraphSection_t)); + graph->numSections = numSections; + graph->order = (DVP_U32 *)calloc(numSections, sizeof(DVP_U32)); + memcpy(&graph->totalperf, &perf, sizeof(perf)); + + if (graph->sections == NULL || graph->order == NULL) + { + DVP_KernelGraph_Free(handle, graph); + graph = NULL; + } + else + { + DVP_U32 s = 0; + DVP_U32 coreLoads[DVP_CORE_MAX] = DVP_CORE_LOAD_INIT; + for (s = 0; s < numSections; s++) + { + memcpy(&graph->sections[s].perf, &perf, sizeof(perf)); + memcpy(&graph->sections[s].coreLoad, coreLoads, sizeof(coreLoads)); + //graph->order[s] = 0; + } + } + } + return graph; + } + return NULL; +} + +/******************************************************************************/ diff --git a/source/dvp/dvp_kgraph/dvp_kmdl.c b/source/dvp/dvp_kgraph/dvp_kmdl.c new file mode 100644 index 0000000..3087453 --- /dev/null +++ b/source/dvp/dvp_kgraph/dvp_kmdl.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +#include + +DVP_U32 DVP_KernelGraphManagerLoad(DVP_GraphManager_t *pManager) +{ + pManager->handle = module_load(pManager->dlname); + if (pManager->handle != NULL) + { + module_error(); + pManager->calls.init = (DVP_GraphManagerInit_f) module_symbol(pManager->handle, "DVP_KernelGraphManagerInit"); + pManager->calls.manager = (DVP_GraphManager_f) module_symbol(pManager->handle, "DVP_KernelGraphManager"); + pManager->calls.getKernels = (DVP_GetSupportedKernels_f) module_symbol(pManager->handle, "DVP_GetSupportedKernels"); + pManager->calls.getLocal = (DVP_GetSupportedLocalCalls_f) module_symbol(pManager->handle, "DVP_GetSupportedLocalCalls"); + pManager->calls.getRemote = (DVP_GetSupportedRemoteCalls_f)module_symbol(pManager->handle, "DVP_GetSupportedRemoteCalls"); + pManager->calls.getCore = (DVP_GetSupportedRemoteCore_f) module_symbol(pManager->handle, "DVP_GetSupportedRemoteCore"); + pManager->calls.getLoad = (DVP_GetMaximumLoad_f) module_symbol(pManager->handle, "DVP_GetMaximumLoad"); + pManager->calls.deinit = (DVP_GraphManagerDeinit_f) module_symbol(pManager->handle, "DVP_KernelGraphManagerDeinit"); + pManager->calls.restart = (DVP_GraphManagerRestart_f) module_symbol(pManager->handle, "DVP_KernelGraphManagerRestart"); + if (pManager->calls.init == NULL || + pManager->calls.manager == NULL || + pManager->calls.getKernels == NULL || + pManager->calls.getLocal == NULL || + pManager->calls.getRemote == NULL || + pManager->calls.getCore == NULL || + pManager->calls.getLoad == NULL || + pManager->calls.deinit == NULL) // we don't check restart yet + { + module_unload(pManager->handle); + pManager->handle = NULL; + memset(&pManager->calls, 0xFE, sizeof(DVP_GraphManager_Calls_t)); + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: Failed to load library %s, error=%s\n", pManager->dlname, module_error()); + return 0; + } + else + return 1; + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: Failed to load library %s, error=%s\n",pManager->dlname,module_error()); + return 0; + } +} + +DVP_U32 DVP_KernelGraphManagerUnload(DVP_GraphManager_t *pManager) +{ + if (pManager->handle != NULL) + { + memset(&pManager->calls, 0, sizeof(pManager->calls)); + module_unload(pManager->handle); + pManager->handle = NULL; + pManager->enabled = false_e; + pManager->kernels = NULL; + pManager->numSupportedKernels = 0; + } + return 1; +} diff --git a/source/dvp/dvp_kgraph/dvp_mem.c b/source/dvp/dvp_kgraph/dvp_mem.c new file mode 100644 index 0000000..a2665b3 --- /dev/null +++ b/source/dvp/dvp_kgraph/dvp_mem.c @@ -0,0 +1,896 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +// dims mutex_t +static mutex_t dims_mutex = MUTEX_INITIAL; + +void dvp_free(DVP_Handle handle, DVP_PTR ptr, DVP_U32 numElem, DVP_U32 sizeElem) +{ + DVP_Dim_t dims[1] = { {{{sizeElem, numElem, 1}}} }; + dvp_mem_free(handle, DVP_MTYPE_DEFAULT, dimof(dims), 2, dims, &ptr); +} + +DVP_PTR dvp_malloc(DVP_Handle handle, DVP_U32 size) +{ + DVP_Dim_t dims[1] = { {{{size, 1, 1}}} }; + DVP_PTR ptrs[1] = {NULL}; + DVP_Dim_t strs[1] = { {{{0,0,0}}} }; + DVP_MemType_e mtype = DVP_MTYPE_DEFAULT; // The default type per platform is defined in the dvp_types.h + dvp_mem_calloc(handle, mtype, dimof(ptrs), 1, dims, ptrs, strs); + return ptrs[0]; +} + +DVP_PTR dvp_calloc(DVP_Handle handle, DVP_U32 numElem, DVP_U32 sizeElem) +{ + DVP_Dim_t dims[1] = { {{{sizeElem, numElem, 1}}} }; + DVP_PTR ptrs[1] = {NULL}; + DVP_Dim_t strs[1] = { {{{0,0,0}}} }; + DVP_MemType_e mtype = DVP_MTYPE_DEFAULT; // The default type per platform is defined in the dvp_types.h + dvp_mem_calloc(handle, mtype, dimof(ptrs), 2, dims, ptrs, strs); + return ptrs[0]; +} + +void DVP_Image_Dup(DVP_Image_t *dst, DVP_Image_t *src) +{ + memcpy(dst, src, sizeof(DVP_Image_t)); +} + +DVP_U32 DVP_Image_PlaneSize(DVP_Image_t *pImage, DVP_U32 plane) +{ + DVP_U32 lineSize = 0; + DVP_U32 planeSize = 0; + + if (pImage == NULL) + return 0; + + lineSize = pImage->x_stride * pImage->bufWidth; + planeSize = pImage->y_stride * pImage->bufHeight; // potentially overestimated + + if (plane > 0) + { + switch (pImage->color) + { + case FOURCC_NV12: + case FOURCC_NV21: + // lineSize == lineSize // due to macropixel * w/2 + planeSize = lineSize * pImage->bufHeight/2; + break; + case FOURCC_YU16: + case FOURCC_YV16: + // lineSize == lineSize // due to macropixel * w/2 + planeSize = lineSize * pImage->bufHeight; + break; + case FOURCC_YV12: + case FOURCC_IYUV: + if (lineSize == (DVP_U32)abs(pImage->y_stride)) // non-TILED + lineSize /= 2; + planeSize = lineSize * pImage->bufHeight/2; + break; + case FOURCC_YUV9: + case FOURCC_YVU9: + if (lineSize == (DVP_U32)abs(pImage->y_stride)) // non-TILED + lineSize /= 4; + planeSize = lineSize * pImage->bufHeight/4; + break; + default: + break; + } + } + return planeSize; +} + +DVP_U32 DVP_Image_Size(DVP_Image_t *pImage) +{ + DVP_U32 p,size = 0; + for (p = 0; p < pImage->planes; p++) + size += DVP_Image_PlaneSize(pImage, p); + return size; +} + +DVP_Dim_t *DVP_Image_Dims(DVP_Image_t *pImage) +{ + static DVP_Dim_t dims[DVP_MAX_PLANES]; + + memset(dims, 0, sizeof(dims)); + + switch (pImage->color) + { + // semi-planar + case FOURCC_NV12: + case FOURCC_NV21: + dims[0].img.bpp = 1; + dims[0].img.width = pImage->bufWidth; + dims[0].img.height = pImage->bufHeight; + dims[1].img.bpp = dims[0].img.bpp*2; + dims[1].img.width = dims[0].img.width/2; + dims[1].img.height = dims[0].img.height/2; + break; + case FOURCC_YUV9: + case FOURCC_YVU9: + dims[0].img.bpp = 1; + dims[0].img.width = pImage->bufWidth; + dims[0].img.height = pImage->bufHeight; + dims[1].img.bpp = dims[2].img.bpp = dims[0].img.bpp; + dims[1].img.width = dims[2].img.width = dims[0].img.width/4; + dims[1].img.height = dims[2].img.height = dims[0].img.height/4; + break; + case FOURCC_YV12: + case FOURCC_IYUV: + dims[0].img.bpp = 1; + dims[0].img.width = pImage->bufWidth; + dims[0].img.height = pImage->bufHeight; + dims[1].img.bpp = dims[2].img.bpp = dims[0].img.bpp; + dims[1].img.width = dims[2].img.width = dims[0].img.width/2; + dims[1].img.height = dims[2].img.height = dims[0].img.height/2; + break; + case FOURCC_YU16: + case FOURCC_YV16: + dims[0].img.bpp = 1; + dims[0].img.width = pImage->bufWidth; + dims[0].img.height = pImage->bufHeight; + dims[1].img.bpp = dims[2].img.bpp = dims[0].img.bpp*2; + dims[1].img.width = dims[2].img.width = dims[0].img.width/2; + dims[1].img.height = dims[2].img.height = dims[0].img.height; + break; +#if defined(DVP_USE_TILER) + case FOURCC_UYVY: + case FOURCC_YUY2: + case FOURCC_VYUY: + case FOURCC_YVYU: + dims[0].img.bpp = 4; + dims[0].img.width = pImage->bufWidth/2; + dims[0].img.height = pImage->bufHeight; + break; +#endif + // iso-planar (includes single plane) + default: + { + DVP_U32 p = 0; + for (p = 0; p < pImage->planes; p++) { + dims[p].img.bpp = pImage->x_stride; + dims[p].img.width = pImage->bufWidth; + dims[p].img.height = pImage->bufHeight; + } + break; + } + } + return dims; +} + +DVP_BOOL DVP_Image_Free(DVP_Handle handle, DVP_Image_t *pImage) +{ + DVP_BOOL ret = DVP_FALSE; + if (handle && pImage && pImage->memType != DVP_MTYPE_DISPLAY_2DTILED) + { + DVP_Dim_t *dims = NULL; + DVP_U32 ndims = 3; + DVP_U32 nptrs = pImage->planes; + + mutex_lock(&dims_mutex); + dims = DVP_Image_Dims(pImage); +#if defined(DVP_USE_TILER) + nptrs = 1; // tiler buffers are allocated in bulk but freed alone +#endif +#if defined(DVP_USE_BO) + if (pImage->memType == DVP_MTYPE_GRALLOC_2DTILED || + pImage->memType == DVP_MTYPE_MPUNONCACHED_2DTILED) + free(pImage->reserved); // free the array of pointers to omap_bo's +#endif + ret = dvp_mem_free(handle, pImage->memType, nptrs, ndims, dims, (DVP_PTR *)pImage->pBuffer); + mutex_unlock(&dims_mutex); + } + else if (handle && pImage && pImage->memType == DVP_MTYPE_DISPLAY_2DTILED) + { + // dissociate the display buffer with the remote cores + DVP_t *dvp = (DVP_t *)handle; + DVP_U32 nptrs = pImage->planes; + DVP_U32 p = 0; +#if defined(DVP_USE_TILER) || defined(GRALLOC_USE_MULTIPLE_POINTERS) + if (pImage->color == FOURCC_NV12) + nptrs = 1; +#endif + for (p = 0; p < nptrs; p++) + { + ret = dvp_rpc_dissociate(dvp->rpc, dvp->mem, pImage->pBuffer[p], pImage->reserved, pImage->numBytes, pImage->memType); + if (ret == DVP_FALSE) + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to dissociate Display buffer %p with remote core!\n", pImage->pBuffer[p]); + } + } + } + return ret; +} + +DVP_BOOL DVP_Image_Alloc(DVP_Handle handle, DVP_Image_t *pImage, DVP_MemType_e dvpMemType) +{ + DVP_BOOL ret = DVP_FALSE; + if (handle && pImage && dvpMemType != DVP_MTYPE_DISPLAY_2DTILED) + { + DVP_U32 ndims = 3; + DVP_U32 nptrs = pImage->planes; + DVP_U32 p = 0; + DVP_Dim_t *dims = NULL; + DVP_Dim_t strides[DVP_MAX_PLANES] = {{{{0,0,0}}}, + {{{0,0,0}}}, + {{{0,0,0}}}, + {{{0,0,0}}}}; + + mutex_lock(&dims_mutex); + dims = DVP_Image_Dims(pImage); + if (dvp_mem_calloc(handle, dvpMemType, nptrs, ndims, dims, (DVP_PTR *)pImage->pBuffer, strides) == DVP_TRUE) + { + for (p = 0; p < pImage->planes; p++) + pImage->pData[p] = pImage->pBuffer[p]; // assign each pointer + + pImage->memType = dvpMemType; + // just take the first plane's strides since DVP_Image_t does not track each plane. +#if defined(DVP_USE_TILER) + if (pImage->color == FOURCC_UYVY || pImage->color == FOURCC_YUY2 || + pImage->color == FOURCC_VYUY || pImage->color == FOURCC_YVYU) + { + strides[0].dim.x = 2; // was set to 4 to force 32 TILER allocations + } +#endif + pImage->x_stride = strides[0].dim.x; + pImage->y_stride = strides[0].dim.y; + pImage->numBytes = strides[0].dim.z; +#if defined(DVP_USE_GRALLOC) + if (pImage->memType == DVP_MTYPE_GRALLOC_2DTILED) + { + // these will probably be used by the camera, so they need to have the reserved field set to the pointer to the gralloc data + DVP_t *dvp = (DVP_t *)handle; + pImage->reserved = (DVP_PTR)dvp_rpc_get_handle(dvp->rpc, pImage->pBuffer[0]); + if (pImage->pBuffer[1] == NULL) + { + pImage->pData[1] = pImage->pBuffer[1] = &pImage->pBuffer[0][pImage->y_stride*pImage->bufHeight]; + } + } +#elif defined(DVP_USE_BO) + if (pImage->memType == DVP_MTYPE_GRALLOC_2DTILED || // i regret naming it this way now... + pImage->memType == DVP_MTYPE_MPUNONCACHED_2DTILED) + { + DVP_t *dvp = (DVP_t *)handle; + // allocate an array of bo pointers for the + alloc_omap_bo_t **bos = (alloc_omap_bo_t *)calloc(pImage->planes, sizeof(alloc_omap_bo_t *)); + if (bos) + { + DVP_U32 p = 0; + for (p = 0; p < pImage->planes; p++) + bos[p] = (alloc_omap_bo_t *)dvp_rpc_get_handle(dvp->rpc, pImage->pBuffer[p]); + pImage->reserved = (DVP_PTR)bos; + } + } +#endif + ret = DVP_TRUE; + } + mutex_unlock(&dims_mutex); + } + else if (handle && pImage && dvpMemType == DVP_MTYPE_DISPLAY_2DTILED) + { + // display buffers need to be associated with the remote cores, only UYVY or NV12 is supported + DVP_t *dvp = (DVP_t *)handle; + DVP_U32 planeSize = 0; + if (pImage->color == FOURCC_UYVY) // TILER + { + ret = dvp_rpc_associate(dvp->rpc, dvp->mem, pImage->pBuffer[0], (DVP_VALUE)pImage->reserved, pImage->numBytes, dvpMemType); + if (ret == DVP_FALSE) + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to associate Display buffer %p with remote core!\n", pImage->pBuffer[0]); + } + } + else if (pImage->color == FOURCC_NV12) // TILER/ION + { +#if !defined(DVP_USE_TILER) && defined(GRALLOC_USE_MULTIPLE_POINTERS) + planeSize = DVP_Image_PlaneSize(pImage, 0); + ret = dvp_rpc_associate(dvp->rpc, dvp->mem, pImage->pBuffer[0], (DVP_VALUE)pImage->reserved, planeSize, dvpMemType); + if (ret == DVP_FALSE) + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to associate Display buffer %p with remote core!\n", pImage->pBuffer[0]); + } + planeSize = DVP_Image_PlaneSize(pImage, 1); + ret = dvp_rpc_associate(dvp->rpc, dvp->mem, pImage->pBuffer[1], (DVP_VALUE)NULL, planeSize, dvpMemType); + if (ret == DVP_FALSE) + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to associate Display buffer %p with remote core!\n", pImage->pBuffer[1]); + } +#else + planeSize = DVP_Image_PlaneSize(pImage,0) + DVP_Image_PlaneSize(pImage, 1); + ret = dvp_rpc_associate(dvp->rpc, dvp->mem, pImage->pBuffer[0], (DVP_VALUE)pImage->reserved, planeSize, dvpMemType); + if (ret == DVP_FALSE) + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to associate Display buffer %p with remote core!\n", pImage->pBuffer[0]); + } +#endif + } + } + DVP_PrintImage(DVP_ZONE_MEM, pImage); + return ret; +} + +DVP_BOOL DVP_Image_Share(DVP_Handle handle, DVP_Image_t *pImage, DVP_S32 *fds) +{ + DVP_BOOL ret = DVP_FALSE; + if (handle && pImage && pImage->memType != DVP_MTYPE_DISPLAY_2DTILED) + { + DVP_U32 nptrs = pImage->planes; + ret = dvp_mem_share(handle, pImage->memType, nptrs, (DVP_PTR *)pImage->pBuffer, fds); + } + return ret; +} + +DVP_BOOL DVP_Image_Import(DVP_Handle handle, DVP_Image_t *pImage, DVP_S32 *shared_fds, DVP_VALUE *hdls) +{ + DVP_BOOL ret = DVP_FALSE; + if (handle && pImage && pImage->memType != DVP_MTYPE_DISPLAY_2DTILED) + { + DVP_Dim_t *dims = NULL; + DVP_U32 ndims = 3; + DVP_U32 nptrs = pImage->planes; + DVP_Dim_t strides[DVP_MAX_PLANES] = {{{{0,0,0}}}, + {{{0,0,0}}}, + {{{0,0,0}}}, + {{{0,0,0}}}}; + mutex_lock(&dims_mutex); + dims = DVP_Image_Dims(pImage); +#if defined(DVP_USE_TILER) + nptrs = 1; // tiler buffers are allocated in bulk but freed alone +#endif + if (dvp_mem_import(handle, pImage->memType, nptrs, ndims, dims, (DVP_PTR *)pImage->pBuffer, strides, shared_fds, hdls) == DVP_TRUE) + { + DVP_U32 p; +#if defined(DVP_USE_TILER) + if (pImage->color == FOURCC_UYVY || pImage->color == FOURCC_YUY2 || + pImage->color == FOURCC_VYUY || pImage->color == FOURCC_YVYU) + { + strides[0].dim.x = 2; // was set to 4 to force 32 TILER allocations + } +#endif + for (p = 0; p < pImage->planes; p++) + pImage->pData[p] = pImage->pBuffer[p]; // assign each pointer + pImage->x_stride = strides[0].dim.x; + pImage->y_stride = strides[0].dim.y; + pImage->numBytes = strides[0].dim.z; + ret = DVP_TRUE; + } + mutex_unlock(&dims_mutex); + } + return ret; +} + +DVP_BOOL DVP_Image_Free_Import(DVP_Handle handle, DVP_Image_t *pImage, DVP_VALUE *hdls) +{ + DVP_BOOL ret = DVP_FALSE; + if (handle && pImage && pImage->memType != DVP_MTYPE_DISPLAY_2DTILED) + { + DVP_U32 ndims = 3; + DVP_Dim_t *dims = NULL; + DVP_U32 nptrs = pImage->planes; + mutex_lock(&dims_mutex); + dims = DVP_Image_Dims(pImage); +#if defined(DVP_USE_TILER) + nptrs = 1; // tiler buffers are allocated in bulk but freed alone +#endif + ret = dvp_mem_free_import(handle, pImage->memType, ndims, dims, nptrs, (DVP_PTR *)pImage->pBuffer, hdls); + mutex_unlock(&dims_mutex); + } + return ret; +} + +void DVP_Image_Fill(DVP_Image_t *pImage, DVP_S08 *ptr, uint32_t size) +{ + if (size >= (pImage->height*pImage->width*pImage->x_stride)) + { + uint32_t i,y,l; + for (y = 0; y < pImage->height; y++) + { + i = (y * pImage->y_stride); + l = (pImage->width * pImage->x_stride); + memcpy(&pImage->pData[0][i], &ptr[y*l], l); + } + } +} + +DVP_BOOL DVP_Image_Copy(DVP_Image_t *pDst, DVP_Image_t *pSrc) +{ + DVP_U32 p,x,y,i,j,l; + DVP_PrintImage(DVP_ZONE_MEM, pSrc); + DVP_PrintImage(DVP_ZONE_MEM, pDst); + + if (pSrc == NULL || pDst == NULL) + return DVP_FALSE; + + for (p = 0; p < pSrc->planes; p++) + if (pSrc->pData[p] == NULL) + return DVP_FALSE; + + for (p = 0; p < pDst->planes; p++) + if (pDst->pData[p] == NULL) + return DVP_FALSE; + + if (pSrc->width > pDst->width || + pSrc->height > pDst->height) + return DVP_FALSE; + + if (pDst->color == pSrc->color) + { + DVP_U32 xscale[DVP_MAX_PLANES] = {1,1,1,1}; + DVP_U32 yscale[DVP_MAX_PLANES] = {1,1,1,1}; + + switch (pSrc->color) + { + case FOURCC_IYUV: // YUV420 planar formats + case FOURCC_YV12: + xscale[1] = yscale[1] = 2; + xscale[2] = yscale[2] = 2; + break; + case FOURCC_YVU9: // YUV411 planar formats + case FOURCC_YUV9: + xscale[1] = yscale[1] = 4; + xscale[2] = yscale[2] = 4; + break; + case FOURCC_YV16: // YUV422 planar formats + case FOURCC_YU16: + xscale[1] = xscale[2] = 2; + yscale[1] = yscale[2] = 1; + break; + case FOURCC_NV12: + case FOURCC_NV21: + // xscale is literally 2 but macro pixel makes it equivalent to 1. + yscale[1] = 2; + break; + case FOURCC_YV24: // 4:4:4 planar formats + case FOURCC_YU24: + case FOURCC_RGBP: + case FOURCC_RGB565: + default: + // default values are fine + break; + } + + for (p = 0; p < pSrc->planes; p++) + { + for (y = 0; y < (pSrc->height/yscale[p]); y++) + { + i = (y * pSrc->y_stride); + j = (y * pDst->y_stride); + l = (pSrc->width * pSrc->x_stride)/xscale[p]; + memcpy(&pDst->pData[p][j], &pSrc->pData[p][i], l); + } + } + return DVP_TRUE; + } + else + { + // convert the colors + if (pSrc->color == FOURCC_Y800 && (pDst->color == FOURCC_UYVY || pDst->color == FOURCC_VYUY)) + { + DVP_U08 *luma; + DVP_U08 *xyxy; + for (y = pSrc->y_start; y < pSrc->height; y++) + { + for (x = pSrc->x_start; x < pSrc->width; x+=2) // macro pixel + { + i = (y * pSrc->y_stride) + (x * pSrc->x_stride); + j = (y * pDst->y_stride) + (x * pDst->x_stride); + luma = &pSrc->pData[0][i]; + xyxy = &pDst->pData[0][j]; + xyxy[0] = 128; // "zero" Chromance + xyxy[1] = luma[0]; + xyxy[2] = 128; // "zero" Chromance + xyxy[3] = luma[1]; + } + } + return DVP_TRUE; + } + if (pSrc->color == FOURCC_Y800 && (pDst->color == FOURCC_YUY2 || pDst->color == FOURCC_YVYU)) + { + DVP_U08 *luma; + DVP_U08 *yxyx; + for (y = pSrc->y_start; y < pSrc->height; y++) + { + for (x = pSrc->x_start; x < pSrc->width; x+=2) // macro pixel + { + i = (y * pSrc->y_stride) + (x * pSrc->x_stride); + j = (y * pDst->y_stride) + (x * pDst->x_stride); + luma = &pSrc->pData[0][i]; + yxyx = &pDst->pData[0][j]; + yxyx[0] = luma[0]; + yxyx[1] = 128; // "zero" Chromance + yxyx[2] = luma[1]; + yxyx[3] = 128; // "zero" Chromance + } + } + return DVP_TRUE; + } + else if ((pDst->color == FOURCC_UYVY || pDst->color == FOURCC_VYUY) && + (pSrc->color == FOURCC_YVYU || pSrc->color == FOURCC_YUY2)) + { + // reswizzle + DVP_U08 *xyxy; + DVP_U08 *yxyx; + for (y = pSrc->y_start; y < pSrc->height; y++) + { + for (x = pSrc->x_start; x < pSrc->width; x+=2) // macro pixels + { + i = (y * pSrc->y_stride) + (x * pSrc->x_stride); + j = (y * pDst->y_stride) + (x * pDst->x_stride); + yxyx = &pSrc->pData[0][i]; + xyxy = &pDst->pData[0][j]; + if (pSrc->color == FOURCC_YUY2) + { + if (pDst->color == FOURCC_UYVY) + { + //UYVY YUYV + xyxy[0] = yxyx[1]; + xyxy[1] = yxyx[0]; + xyxy[2] = yxyx[3]; + xyxy[3] = yxyx[2]; + } + else + { + //VYUY YUYV + xyxy[0] = yxyx[3]; + xyxy[1] = yxyx[0]; + xyxy[2] = yxyx[1]; + xyxy[3] = yxyx[2]; + } + } + else + { + if (pDst->color == FOURCC_UYVY) + { + //UYVY YVYU + xyxy[0] = yxyx[3]; + xyxy[1] = yxyx[0]; + xyxy[2] = yxyx[1]; + xyxy[3] = yxyx[2]; + } + else + { + //VYUY YVYU + xyxy[0] = yxyx[1]; + xyxy[1] = yxyx[0]; + xyxy[2] = yxyx[3]; + xyxy[3] = yxyx[2]; + } + } + } + } + return DVP_TRUE; + } + // some semi-planar or planar + else if ((pSrc->color == FOURCC_NV12 || + pSrc->color == FOURCC_YU24 || + pSrc->color == FOURCC_YV24 || + pSrc->color == FOURCC_YU16 || + pSrc->color == FOURCC_YV16 || + pSrc->color == FOURCC_IYUV || + pSrc->color == FOURCC_YV12 || + pSrc->color == FOURCC_YUV9 || + pSrc->color == FOURCC_YVU9) && + pDst->color == FOURCC_Y800) + { + // a "luma" extract kind-of + for (y = pSrc->y_start; y < pSrc->height; y++) + { + uint32_t i = (y * pSrc->y_stride); + uint32_t j = (y * pDst->y_stride); + uint32_t l = (pSrc->x_stride * pSrc->width); + memcpy(&pDst->pData[0][j], &pSrc->pData[0][i], l); + } + return DVP_TRUE; + } + } + return DVP_FALSE; +} + +void DVP_Image_Init(DVP_Image_t *pImage, DVP_U32 width, DVP_U32 height, fourcc_t fourcc) +{ + // clean out any dirty values + memset(pImage, 0, sizeof(DVP_Image_t)); + + pImage->planes = 1; // assume single plane + pImage->x_stride = 1; // default size + + if (fourcc == FOURCC_YUV9 || + fourcc == FOURCC_YVU9 || + fourcc == FOURCC_YV12 || + fourcc == FOURCC_IYUV || + fourcc == FOURCC_YU16 || + fourcc == FOURCC_YV16 || + fourcc == FOURCC_YU24 || + fourcc == FOURCC_YV24 || + fourcc == FOURCC_RGBP || + fourcc == FOURCC_HSLP) + pImage->planes = 3; + + if (fourcc == FOURCC_UYVY || + fourcc == FOURCC_YUY2 || + fourcc == FOURCC_VYUY || + fourcc == FOURCC_YVYU) + pImage->x_stride = 2; + + if (fourcc == FOURCC_BGR || + fourcc == FOURCC_RGB) + pImage->x_stride = 3; + + if (fourcc == FOURCC_RGBA || + fourcc == FOURCC_BGRA || + fourcc == FOURCC_ARGB) + pImage->x_stride = 4; + + if (fourcc == FOURCC_NV12 || + fourcc == FOURCC_NV21) + pImage->planes = 2; + + if (fourcc == FOURCC_Y16) + pImage->x_stride = 2; + + if (fourcc == FOURCC_Y32) + pImage->x_stride = 4; + + if (fourcc == FOURCC_RGB565 || + fourcc == FOURCC_BGR565) + pImage->x_stride = 2; + + // calculate the number of bytes (assumes isometric planes) + pImage->numBytes = height * width * pImage->x_stride * pImage->planes; + + // 4:2:0 sizes are different + if (fourcc == FOURCC_NV12 || + fourcc == FOURCC_NV21 || + fourcc == FOURCC_IYUV || + fourcc == FOURCC_YV12) + pImage->numBytes = (height * width * 3)/2; + + // 4:2:2 sizes are also different + if (fourcc == FOURCC_YV16 || + fourcc == FOURCC_YU16) + pImage->numBytes = (height * width) + 2*(height * width/2); + + pImage->width = width; + pImage->height = height; + pImage->bufWidth = width; + pImage->bufHeight = height; + pImage->color = fourcc; +} + +void DVP_Image_Deinit(DVP_Image_t *pImage) +{ + memset(pImage, 0xEF, sizeof(DVP_Image_t)); +} + +size_t DVP_Image_Unserialize(DVP_Image_t *pImage, uint8_t *buffer, size_t len) +{ + size_t offset = 0; + uint32_t p,y,i,l; + DVP_Dim_t *dims = NULL; + DVP_Image_t image; + bool_e copy = false_e; + + UNSERIALIZE_UNIT(buffer, offset, len, image.planes); + UNSERIALIZE_UNIT(buffer, offset, len, image.width); + UNSERIALIZE_UNIT(buffer, offset, len, image.height); + UNSERIALIZE_UNIT(buffer, offset, len, image.bufWidth); + UNSERIALIZE_UNIT(buffer, offset, len, image.bufHeight); + UNSERIALIZE_UNIT(buffer, offset, len, image.x_start); + UNSERIALIZE_UNIT(buffer, offset, len, image.y_start); + //UNSERIALIZE_UNIT(buffer, offset, len, image.x_stride); + //UNSERIALIZE_UNIT(buffer, offset, len, image.y_stride); + UNSERIALIZE_UNIT(buffer, offset, len, image.color); + UNSERIALIZE_UNIT(buffer, offset, len, image.numBytes); + //UNSERIALIZE_UNIT(buffer, offset, len, image.memType); + //UNSERIALIZE_UNIT(buffer, offset, len, image.skipCacheOpInval); + //UNSERIALIZE_UNIT(buffer, offset, len, image.skipCacheOpFlush); + + // only copy if the images are a match. + if (image.color == pImage->color && + image.bufWidth == pImage->bufWidth && + image.bufHeight == pImage->bufHeight) + copy = true_e; + + mutex_lock(&dims_mutex); + dims = DVP_Image_Dims(&image); + for (p = 0; p < image.planes; p++) + { + for (y = pImage->y_start; y < (uint32_t)dims[p].img.height; y++) + { + // @TODO This should be identical across all planes + i = (y * pImage->y_stride) + (0 * dims[p].dim.x); + // @TODO This should be identical across all planes + l = (pImage->x_stride * dims[p].img.width); + if (copy) { + UNSERIALIZE_ARRAY(buffer, offset, len, &pImage->pBuffer[p][i], l); + } else { + offset += l; + } + } + } + mutex_unlock(&dims_mutex); + return offset; + +} + +size_t DVP_Image_Serialize(DVP_Image_t *pImage, uint8_t *buffer, size_t len) +{ + size_t offset = 0; + uint32_t p,y,i,l; + DVP_Dim_t *dims = NULL; + + SERIALIZE_UNIT(buffer, offset, len, pImage->planes); + SERIALIZE_UNIT(buffer, offset, len, pImage->width); + SERIALIZE_UNIT(buffer, offset, len, pImage->height); + SERIALIZE_UNIT(buffer, offset, len, pImage->bufWidth); + SERIALIZE_UNIT(buffer, offset, len, pImage->bufHeight); + SERIALIZE_UNIT(buffer, offset, len, pImage->x_start); + SERIALIZE_UNIT(buffer, offset, len, pImage->y_start); + //SERIALIZE_UNIT(buffer, offset, len, pImage->x_stride); + //SERIALIZE_UNIT(buffer, offset, len, pImage->y_stride); + SERIALIZE_UNIT(buffer, offset, len, pImage->color); + SERIALIZE_UNIT(buffer, offset, len, pImage->numBytes); + //SERIALIZE_UNIT(buffer, offset, len, pImage->memType); + //SERIALIZE_UNIT(buffer, offset, len, pImage->skipCacheOpInval); + //SERIALIZE_UNIT(buffer, offset, len, pImage->skipCacheOpFlush); + + mutex_lock(&dims_mutex); + dims = DVP_Image_Dims(pImage); + for (p = 0; p < pImage->planes; p++) + { + for (y = 0; y < (uint32_t)dims[p].img.height; y++) + { + // @TODO This should be identical across all planes + i = (y * pImage->y_stride) + (0 * dims[p].dim.x); + // @TODO This should be identical across all planes + l = (pImage->x_stride * dims[p].img.width); + SERIALIZE_ARRAY(buffer, offset, len, &pImage->pBuffer[p][i], l); + } + } + mutex_unlock(&dims_mutex); + return offset; +} + +DVP_BOOL DVP_Buffer_Free(DVP_Handle handle, DVP_Buffer_t *pBuffer) +{ + if (handle && pBuffer) + { + DVP_U32 numElem = pBuffer->numBytes/pBuffer->elemSize; + DVP_Dim_t dims[1] = { {{{pBuffer->elemSize, numElem, 1}}} }; + return dvp_mem_free(handle, pBuffer->memType, dimof(dims), 2, dims, (DVP_PTR *)&pBuffer->pData); + } + return DVP_FALSE; +} + +DVP_BOOL DVP_Buffer_Alloc(DVP_Handle handle, DVP_Buffer_t *pBuffer, DVP_MemType_e dvpMemType) +{ + DVP_BOOL ret = DVP_FALSE; + if (handle && pBuffer) + { + DVP_U32 numElem = pBuffer->numBytes/pBuffer->elemSize; + DVP_Dim_t dims[1] = { {{{pBuffer->elemSize, numElem, 1}}} }; + DVP_PTR ptrs[1] = {NULL}; + DVP_Dim_t strs[1] = { {{{0,0,0}}} }; + ret = dvp_mem_calloc(handle, dvpMemType, dimof(ptrs), 2, dims, ptrs, strs); + if (ret == DVP_TRUE) { + pBuffer->memType = dvpMemType; + pBuffer->pData = (DVP_U08 *)ptrs[0]; + } + } + return ret; +} + +void DVP_Buffer_Init(DVP_Buffer_t *pBuffer, DVP_U32 elemSize, DVP_U32 numElems) +{ + // clean out any dirty values + memset(pBuffer, 0, sizeof(DVP_Buffer_t)); + + pBuffer->elemSize = elemSize; + pBuffer->numBytes = elemSize*numElems; +} + +void DVP_Buffer_Deinit(DVP_Buffer_t *pBuffer) +{ + memset(pBuffer, 0xEF, sizeof(DVP_Buffer_t)); +} + +DVP_BOOL DVP_Buffer_Share(DVP_Handle handle, DVP_Buffer_t *pBuffer, DVP_S32 *shared_fd) +{ + DVP_BOOL ret = DVP_FALSE; + if (handle && pBuffer) + { + ret = dvp_mem_share(handle, pBuffer->memType, 1, (DVP_PTR *)&pBuffer->pData, shared_fd); + } + return ret; +} + +DVP_BOOL DVP_Buffer_Import(DVP_Handle handle, DVP_Buffer_t *pBuffer, DVP_S32 shared_fd, DVP_VALUE *hdl) +{ + DVP_BOOL ret = DVP_FALSE; + if (handle && pBuffer) + { + DVP_U32 numElem = pBuffer->numBytes/pBuffer->elemSize; + DVP_Dim_t dims[1] = { {{{pBuffer->elemSize, numElem, 1}}} }; + DVP_PTR ptrs[1] = {NULL}; + DVP_Dim_t strs[1] = { {{{0,0,0}}} }; + if (dvp_mem_import(handle, pBuffer->memType, 1, 2, dims, (DVP_PTR *)ptrs, strs, &shared_fd, hdl) == DVP_TRUE) + { + pBuffer->pData = (DVP_U08 *)ptrs[0]; + ret = DVP_TRUE; + } + } + return ret; +} + +DVP_BOOL DVP_Buffer_Free_Import(DVP_Handle handle, DVP_Buffer_t *pBuffer, DVP_VALUE hdl) +{ + DVP_BOOL ret = DVP_FALSE; + if (handle && pBuffer) + { + DVP_U32 numElem = pBuffer->numBytes/pBuffer->elemSize; + DVP_Dim_t dims[1] = { {{{pBuffer->elemSize, numElem, 1}}} }; + ret = dvp_mem_free_import(handle, pBuffer->memType, 2, dims, 1, (DVP_PTR *)&pBuffer->pData, &hdl); + } + return ret; +} + +DVP_KernelNode_t *DVP_KernelNode_Alloc(DVP_Handle handle, DVP_U32 numNodes) +{ + DVP_U32 i = 0; + DVP_KernelNode_t *pNodes = NULL; + DVP_Dim_t dims[] = {{{{sizeof(DVP_KernelNode_t), numNodes, 1}}}}; + DVP_Dim_t strs[] = {{{{0,0,0}}}}; + DVP_PTR ptrs[] = {NULL}; + if (dvp_mem_calloc(handle, DVP_MTYPE_KERNELGRAPH, dimof(ptrs), 2, dims, ptrs, strs) == DVP_TRUE) + { + pNodes = (DVP_KernelNode_t *)ptrs[0]; + for (i = 0; i < numNodes; i++) + { + pNodes[i].header.configured = DVP_FALSE; + pNodes[i].header.affinity = DVP_CORE_MIN; + DVP_Perf_Clear(&pNodes[i].header.perf); + } + } + return pNodes; +} + +void DVP_KernelNode_Free(DVP_Handle handle, DVP_KernelNode_t *pNodes, DVP_U32 numNodes) +{ + if (handle && pNodes && numNodes > 0) + { + DVP_Dim_t dims[] = {{{{sizeof(DVP_KernelNode_t), numNodes, 1}}}}; + DVP_PTR ptrs[] = {pNodes}; + DVP_U32 n = 0; + + // make sure the debugging handles are closed so that the data has been + // committed to the files. + for (n = 0; n < numNodes; n++) { + DVP_ImageDebug_t *img = dvp_knode_to(&pNodes[n],DVP_ImageDebug_t); +#if defined(DVP_USE_FS) + if (pNodes[n].header.kernel == DVP_KN_IMAGE_DEBUG && img->fp) + fclose(img->fp); + if (pNodes[n].header.kernel == DVP_KN_BUFFER_DEBUG && img->fp) + fclose(img->fp); +#endif + } + + memset(pNodes, 0, numNodes*sizeof(DVP_KernelNode_t)); + dvp_mem_free(handle, DVP_MTYPE_KERNELGRAPH, dimof(ptrs), 2, dims, ptrs); + } +} diff --git a/source/dvp/dvp_kgraph/dvp_mem_int.c b/source/dvp/dvp_kgraph/dvp_mem_int.c new file mode 100644 index 0000000..033c638 --- /dev/null +++ b/source/dvp/dvp_kgraph/dvp_mem_int.c @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include + +typedef struct _dvp_mem_correlate_t { + allocator_memory_type_e amtype; + DVP_MemType_e dmtype; +} DVP_Mem_Correlation_t; + +DVP_Mem_Correlation_t mem_correlation[] = { + {ALLOCATOR_MEMORY_TYPE_VIRTUAL, DVP_MTYPE_MPUCACHED_VIRTUAL}, +#if defined(DVP_USE_TILER) + {ALLOCATOR_MEMORY_TYPE_VIRTUAL, DVP_MTYPE_MPUCACHED_1DTILED}, +#endif +#if defined(DVP_USE_ION) || defined(DVP_USE_BO) + {ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED, DVP_MTYPE_MPUCACHED_1DTILED}, +#endif +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + {ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED, DVP_MTYPE_MPUNONCACHED_1DTILED}, + {ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED, DVP_MTYPE_MPUNONCACHED_2DTILED}, +#endif +#if defined(DVP_USE_GRALLOC) || defined(DVP_USE_BO) + {ALLOCATOR_MEMORY_TYPE_GFX_2D_UNCACHED, DVP_MTYPE_GRALLOC_2DTILED}, +#endif +#if defined(DVP_USE_SHARED_T) + {ALLOCATOR_MEMORY_TYPE_VIRTUAL_SHARED, DVP_MTYPE_MPUCACHED_VIRTUAL_SHARED}, +#endif +}; + +bool_e dvp_mem_type_cached(DVP_MemType_e memType) +{ + switch (memType) + { +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + case DVP_MTYPE_MPUCACHED_1DTILED: + return true_e; + case DVP_MTYPE_MPUNONCACHED_1DTILED: + case DVP_MTYPE_MPUNONCACHED_2DTILED: + return false_e; +#endif +#if defined(DVP_USE_TILER) + case DVP_MTYPE_DISPLAY_2DTILED: + return false_e; +#endif +#if defined(DVP_USE_GRALLOC) || defined(DVP_USE_BO) + case DVP_MTYPE_DISPLAY_2DTILED: + case DVP_MTYPE_GRALLOC_2DTILED: + return false_e; +#endif + default: + return true_e; + } +} + +allocator_memory_type_e dvp_mem_type_xlate(DVP_MemType_e memType) +{ + DVP_U32 t = 0; + for (t = 0; t < dimof(mem_correlation); t++) + { + if (memType == mem_correlation[t].dmtype) + return mem_correlation[t].amtype; + } + return ALLOCATOR_MEMORY_TYPE_VIRTUAL; +} + +void dvp_mem_deinit(DVP_Mem_t **pmem) +{ + allocator_deinit(pmem); +} + +DVP_Mem_t *dvp_mem_init() +{ + return allocator_init(); +} + +DVP_BOOL dvp_mem_flush(DVP_Handle handle, + DVP_MemType_e mtype, + DVP_S32 nptrs, + DVP_S32 ndims, + DVP_Dim_t *dims, + DVP_PTR *ptrs) +{ + DVP_t *dvp = (DVP_t *)handle; + DVP_S32 p = 0; + DVP_VALUE hdls[DVP_MAX_PLANES] = {0, 0, 0, 0}; + if (dvp != NULL && nptrs > 0 && ptrs != NULL) + { + for (p = 0; p < nptrs; p++) + { + hdls[p] = dvp_rpc_get_handle(dvp->rpc, ptrs[p]); + } + + if (allocator_flush(dvp->mem, dvp_mem_type_xlate(mtype), nptrs, ndims, dims, ptrs, hdls) == false_e) + return DVP_FALSE; + } + return DVP_TRUE; +} + +DVP_BOOL dvp_mem_invalidate(DVP_Handle handle, + DVP_MemType_e mtype, + DVP_S32 nptrs, + DVP_S32 ndims, + DVP_Dim_t *dims, + DVP_PTR *ptrs) +{ + DVP_t *dvp = (DVP_t *)handle; + DVP_S32 p = 0; + DVP_VALUE hdls[DVP_MAX_PLANES] = {0, 0, 0, 0}; + if (dvp != NULL && nptrs > 0 && ptrs != NULL) + { + for (p = 0; p < nptrs; p++) + { + hdls[p] = dvp_rpc_get_handle(dvp->rpc, ptrs[p]); + } + + if (allocator_invalidate(dvp->mem, dvp_mem_type_xlate(mtype), nptrs, ndims, dims, ptrs, hdls) == false_e) + return DVP_FALSE; + } + return DVP_TRUE; +} + +DVP_BOOL dvp_mem_free(DVP_Handle handle, + DVP_MemType_e mtype, + DVP_S32 nptrs, + DVP_S32 ndims, + DVP_Dim_t *dims, + DVP_PTR *ptrs) +{ + DVP_t *dvp = (DVP_t *)handle; + DVP_S32 n = 0, p = 0; + DVP_U32 size = 1; + // the handles will be filled-in from the dissociate + DVP_VALUE hdls[DVP_MAX_PLANES] = {0, 0, 0, 0}; + + if (dvp == NULL || nptrs <= 0 || ptrs == NULL || ndims <=0 || dims == NULL) + return DVP_FALSE; + + for (p = 0; p < nptrs; p++) { + + // calculate the size + size = 1; + for (n = 0; n < ndims; n++) { + size *= dims[p].dims[n]; + } + + // dissociate the memory with the remote cores + dvp_rpc_dissociate(dvp->rpc, dvp->mem, ptrs[p], &hdls[p], size, mtype); + } + + if (true_e == allocator_free(dvp->mem, dvp_mem_type_xlate(mtype), nptrs, ptrs, hdls)) + return DVP_TRUE; + else + return DVP_FALSE; +} + +DVP_BOOL dvp_mem_calloc(DVP_Handle handle, + DVP_MemType_e mtype, + DVP_S32 nptrs, + DVP_S32 ndims, + DVP_Dim_t *dims, + DVP_PTR *ptrs, + DVP_Dim_t *strides) +{ + DVP_t *dvp = (DVP_t *)handle; + DVP_Mem_t *mem = dvp->mem; + DVP_BOOL ret = DVP_TRUE; + DVP_U32 size; + DVP_S32 p; + // this is filled-in from the allocator and given to associate + DVP_VALUE hdls[DVP_MAX_PLANES] = {0, 0, 0, 0}; + + if (nptrs <= 0 || ndims <= 0 || dims == NULL || ptrs == NULL) + return DVP_FALSE; + + if (true_e == allocator_calloc(mem, dvp_mem_type_xlate(mtype), nptrs, ndims, dims, ptrs, hdls, strides)) + ret = DVP_TRUE; + else + ret = DVP_FALSE; + if (ret == DVP_TRUE) + { + for (p = 0; p < nptrs; p++) + { + // use the calculated size of this pointer (this accounts for strides) + size = strides[p].dims[ndims-1]; + + // associate the memory with the remote cores + dvp_rpc_associate(dvp->rpc, dvp->mem, ptrs[p], hdls[p], size, mtype); + } + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to allocate memory type %u!\n", mtype); + } + return ret; +} + +DVP_BOOL dvp_mem_share(DVP_Handle handle, + DVP_MemType_e mtype, + DVP_S32 nptrs, + DVP_PTR *ptrs, + DVP_S32 *fds) +{ + DVP_t *dvp = (DVP_t *)handle; + DVP_S32 p = 0; + DVP_VALUE hdls[DVP_MAX_PLANES] = {0, 0, 0, 0}; + if (dvp != NULL && nptrs > 0 && ptrs != NULL) + { + for (p = 0; p < nptrs; p++) + { + hdls[p] = dvp_rpc_get_handle(dvp->rpc, ptrs[p]); + } + if (allocator_share(dvp->mem, dvp_mem_type_xlate(mtype), nptrs, hdls, fds) == false_e) + return DVP_FALSE; + } + return DVP_TRUE; +} + +DVP_BOOL dvp_mem_import(DVP_Handle handle, + DVP_MemType_e mtype, + DVP_S32 nptrs, + DVP_S32 ndims, + DVP_Dim_t *dims, + DVP_PTR *ptrs, + DVP_Dim_t *strides, + DVP_S32 *fds, + DVP_VALUE *hdls) +{ + DVP_t *dvp = (DVP_t *)handle; + DVP_U32 size; + DVP_S32 p; + DVP_BOOL ret = DVP_FALSE; + if (dvp != NULL && nptrs > 0 && ptrs != NULL && ndims > 0 && dims != NULL) + { + if (allocator_import(dvp->mem, dvp_mem_type_xlate(mtype), nptrs, ndims, dims, ptrs, hdls, strides, fds)) { + ret = DVP_TRUE; + } + } + if (ret == DVP_TRUE && dvp->rpc != NULL) { + for (p = 0; p < nptrs; p++) + { + // use the calculated size of this pointer (this accounts for strides) + size = strides[p].dims[ndims-1]; + + // associate the memory with the remote cores + dvp_rpc_associate(dvp->rpc, dvp->mem, ptrs[p], hdls[p], size, mtype); + } + } + if (ret == DVP_FALSE) { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to import memory type %u!\n", mtype); + } + return ret; +} + +DVP_BOOL dvp_mem_free_import(DVP_Handle handle, + DVP_MemType_e mtype, + DVP_S32 ndims, + DVP_Dim_t *dims, + DVP_S32 nptrs, + DVP_PTR *ptrs, + DVP_VALUE *hdls) +{ + DVP_U32 size; + DVP_S32 n, p; + DVP_t *dvp = (DVP_t *)handle; + + if (dvp == NULL || nptrs <= 0 || ptrs == NULL || hdls == NULL || ndims <= 0 || dims == NULL) + return DVP_FALSE; + + if (dvp->rpc != NULL) { + for (p = 0; p < nptrs; p++) { + // calculate the size + size = 1; + for (n = 0; n < ndims; n++) { + size *= dims[p].dims[n]; + } + + // dissociate the memory with the remote cores + dvp_rpc_dissociate(dvp->rpc, dvp->mem, ptrs[p], &hdls[p], size, mtype); + } + } + if (true_e == allocator_free(dvp->mem, dvp_mem_type_xlate(mtype), nptrs, ptrs, hdls)) + return DVP_TRUE; + else + return DVP_FALSE; +} diff --git a/source/dvp/dvp_kgraph/dvp_rpc_bios.c b/source/dvp/dvp_kgraph/dvp_rpc_bios.c new file mode 100644 index 0000000..98376a3 --- /dev/null +++ b/source/dvp/dvp_kgraph/dvp_rpc_bios.c @@ -0,0 +1,161 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(DVP_USE_BIOSIPC) + +//****************************************************************************** +// INCLUDES +//****************************************************************************** + +#include + +#include +#include +// @NOTE we include dvp_rpc.h further down in the file... + +#include +#include + +//****************************************************************************** +// #DEFINES +//****************************************************************************** + +#define DVP_RPC_BLOCK_SIZE (64) +#define DVP_RPC_NUM_BLOCKS (64) + +#define PROC_VALID_ID(x) (-1 < (x) && (x) < PROC_END) + +//****************************************************************************** +// TYPEDEFS +//****************************************************************************** + +typedef struct _dvp_rpc_t { + DVP_Handle handle; /** This contains the pointer back the DVP_t. It MUST be the FIRST entry in the structure! */ + mutex_t lock; +} DVP_RPC_t; + +#define DVP_RPC_T // we're defining the RPC structure locally! +#include + +#define DVP_VALID_REMOTE_CORE(x) (DVP_CORE_MIN < (x) && (x) < DVP_CORE_REMOTE_MAX) + + +//****************************************************************************** +// LOCAL VARIABLES +//****************************************************************************** + + +//****************************************************************************** +// LOCAL FUNCTIONS +//****************************************************************************** + +DVP_RPC_t *dvp_rpc_init() +{ + // attach to all the cores... + // create a message q heap + // create the messageq +} + +void dvp_rpc_deinit(DVP_RPC_t **rpc) {} + +void dvp_rpc_restart_callback_register(DVP_RPC_t *rpc, DVP_RPC_Core_t *rpcc, dvp_rpc_restart_f func, void *cookie) {} + +DVP_PTR dvp_rpc_mem_xlate_fwrd(DVP_RPC_t *rpc, DVP_Core_e core, DVP_PTR localAddr, DVP_U32 localSize, DVP_MemType_e memType) +{ + return NULL; +} + +DVP_PTR dvp_rpc_mem_xlate_back(DVP_RPC_t *rpc, DVP_Core_e core, DVP_PTR remoteAddr, DVP_MemType_e memType) +{ + return NULL; +} + +void dvp_rpc_mem_remove(DVP_RPC_t *rpc, DVP_PTR localAddr, DVP_U32 localSize, DVP_MemType_e memType) +{ + ; +} + +DVP_RPC_Core_t *dvp_rpc_core_init(DVP_RPC_t *rpc, DVP_RPC_Interface_t *rpci) +{ + // connect to each remote core +} + +void dvp_rpc_core_deinit(DVP_RPC_t *rpc, DVP_RPC_Core_t **rpcc) +{ + // disconnect from each core +} + +DVP_BOOL dvp_rpc_dissociate(DVP_RPC_t *rpc, DVP_Mem_t *mem, DVP_PTR ptr, DVP_VALUE *pHandle, size_t size, DVP_MemType_e mtype) +{ + return DVP_FALSE; +} + +DVP_BOOL dvp_rpc_associate(DVP_RPC_t *rpc, DVP_Mem_t *mem, DVP_PTR ptr, DVP_VALUE handle, size_t size, DVP_MemType_e mtype) +{ + return DVP_FALSE; +} + +DVP_VALUE dvp_rpc_get_handle(DVP_RPC_t *rpc, DVP_PTR ptr) +{ + return 0; +} + +int dvp_rpc_remote_execute(DVP_RPC_t *rpc, + DVP_RPC_Core_t *rpcc, + int cliIndex, + DVP_RPC_Parameter_t *params, + DVP_U32 numParams, + DVP_RPC_Translation_t *trans) +{ + return 0; +} + +DVP_BOOL dvp_rpc_invalidate(DVP_RPC_t *rpc, DVP_Core_e core, DVP_PTR address, DVP_U32 size, DVP_MemType_e mtype) +{ + return DVP_FALSE; +} + +DVP_BOOL dvp_rpc_flush(DVP_RPC_t *rpc, DVP_Core_e core, DVP_PTR address, DVP_U32 size, DVP_MemType_e mtype) +{ + return DVP_FALSE; +} + +void dvp_rpc_prepare_image(DVP_RPC_t *rpc, DVP_Core_e core, DVP_Image_t *pImage, DVP_BOOL cacheOp, DVP_PTR base, DVP_RPC_Translation_t *trans) +{ + ; +} + +void dvp_rpc_return_image(DVP_RPC_t *rpc, DVP_Core_e core, DVP_Image_t *pImage, DVP_BOOL cacheOp) +{ + ; +} + +void dvp_rpc_prepare_buffer(DVP_RPC_t *rpc, DVP_Core_e core, DVP_Buffer_t *pBuffer, DVP_BOOL cacheOp, DVP_PTR base, DVP_RPC_Translation_t *trans) +{ + ; +} + +void dvp_rpc_return_buffer(DVP_RPC_t *rpc, DVP_Core_e core, DVP_Buffer_t *pBuffer, DVP_BOOL cacheOp) +{ + ; +} + +#endif + +//****************************************************************************** +// END +//****************************************************************************** + diff --git a/source/dvp/dvp_kgraph/dvp_rpc_omaprpc.c b/source/dvp/dvp_kgraph/dvp_rpc_omaprpc.c new file mode 100644 index 0000000..13e4514 --- /dev/null +++ b/source/dvp/dvp_kgraph/dvp_rpc_omaprpc.c @@ -0,0 +1,780 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(DVP_USE_OMAPRPC) + +//****************************************************************************** +// INCLUDES +//****************************************************************************** + +#include + +#include +#include +// @NOTE we include dvp_rpc.h further down in the file... + +#ifdef DVP_USE_GRALLOC +#include +#endif + +#include + +//****************************************************************************** +// #DEFINES +//****************************************************************************** + +#define DVP_RPC_BLOCK_SIZE (64) +#define DVP_RPC_NUM_BLOCKS (64) + +#define PROC_VALID_ID(x) (-1 < (x) && (x) < PROC_END) + +//****************************************************************************** +// TYPEDEFS +//****************************************************************************** + +#define DVP_CORE_REMOTE_MAX (DVP_CORE_CPU) + +typedef struct _dvp_memory_range_t { + btreelistnode_t node; + value_t base; + value_t end; +} DVP_Memory_Range_t; + +typedef struct _dvp_rpc_core_t DVP_RPC_Core_t; // forward definition + +typedef struct _dvp_rpc_t { + DVP_Handle handle; /** This contains the pointer back the DVP_t. It MUST be the FIRST entry in the structure! */ + mutex_t lock; + fph_t *hndl_hash; + DVP_RPC_Core_t *cores[DVP_CORE_REMOTE_MAX]; + btreelist_t *ranges; +} DVP_RPC_t; + +struct _dvp_rpc_core_t { + DVP_S32 coreEnum; + omaprpc_t *rpc; + void *callback; // will be later cast the proper type + void *cookie; +}; + +#define DVP_RPC_T // we're defining the RPC structure locally! +#include + +#define DVP_VALID_REMOTE_CORE(x) (DVP_CORE_MIN < (x) && (x) < DVP_CORE_REMOTE_MAX) + +typedef struct _dvp_core_to_name_t { + bool_e enabled; + DVP_Core_e core; + char *name; + char *server_name; + char *device_name; +} DVP_Core_Name_t; + +//****************************************************************************** +// LOCAL VARIABLES +//****************************************************************************** + +#if defined(BLAZE) || defined(SDP) || defined(BLAZE_TABLET) || defined(PANDA) +#define IS_TESLA_ENABLED true_e +#else //p920, GT_I9100G, PLAYBOOK, other platforms +#define IS_TESLA_ENABLED false_e +#endif + +#if defined(TARGET_DVP_OMAP4) +static DVP_Core_Name_t dvp_core_names[] = { + {IS_TESLA_ENABLED, DVP_CORE_DSP, "Tesla", "dvp_kgm_dsp", "/dev/dvp_kgm_dsp"}, + {true_e, DVP_CORE_SIMCOP, "AppM3", "dvp_kgm_simcop", "/dev/dvp_kgm_simcop"}, + {false_e, DVP_CORE_MCU0, "AppM3", "dvp_kgm_app", "/dev/dvp_kgm_app"}, + {false_e, DVP_CORE_MCU1, "SysM3", "dvp_kgm_sys", "/dev/dvp_kgm_sys"}, + {false_e, DVP_CORE_GPU, "SGX", "dvp_kgm_sgx", NULL}, + {false_e, DVP_CORE_EVE, "EVE", "dvp_kgm_eve", NULL}, + {true_e, DVP_CORE_CPU, "MPU", NULL, NULL}, +}; +#elif defined(TARGET_DVP_OMAP5) +static DVP_Core_Name_t dvp_core_names[] = { + {false_e, DVP_CORE_DSP, "Tesla", "dvp_kgm_dsp", "/dev/dvp_kgm_dsp"}, + {true_e, DVP_CORE_SIMCOP, "AppM4", "dvp_kgm_simcop", "/dev/dvp_kgm_simcop"}, + {false_e, DVP_CORE_MCU0, "AppM4", "dvp_kgm_app", "/dev/dvp_kgm_app"}, + {false_e, DVP_CORE_MCU1, "SysM4", "dvp_kgm_sys", "/dev/dvp_kgm_sys"}, + {false_e, DVP_CORE_GPU, "SGX", "dvp_kgm_sgx", NULL}, + {false_e, DVP_CORE_EVE, "EVE", "dvp_kgm_eve", NULL}, + {true_e, DVP_CORE_CPU, "MPU", NULL, NULL}, +}; +#elif defined(TARGET_DVP_OMAP6) +static DVP_Core_Name_t dvp_core_names[] = { + {true_e, DVP_CORE_DSP, "Tesla", "dvp_kgm_dsp", "/dev/dvp_kgm_dsp"}, + {true_e, DVP_CORE_SIMCOP, "AppM4", "dvp_kgm_simcop", "/dev/dvp_kgm_simcop"}, + {false_e, DVP_CORE_MCU0, "AppM4", "dvp_kgm_app", "/dev/dvp_kgm_app"}, + {false_e, DVP_CORE_MCU1, "SysM4", "dvp_kgm_sys", "/dev/dvp_kgm_sys"}, + {false_e, DVP_CORE_GPU, "SGX", "dvp_kgm_sgx", NULL}, + {false_e, DVP_CORE_EVE, "EVE", "dvp_kgm_eve", "/dev/omaprpc-eve"}, + {true_e, DVP_CORE_CPU, "MPU", NULL, NULL}, +}; +#endif // OMAP types + +static DVP_Perf_t rpc_perf; + +//****************************************************************************** +// LOCAL FUNCTIONS +//****************************************************************************** + +static bool_e dvp_rpc_core_is_enabled(DVP_Core_e core) +{ + DVP_U32 i = 0; + for (i = 0; i < DVP_CORE_MAX; i++) + if (core == dvp_core_names[i].core) + return dvp_core_names[i].enabled; + return false_e; +} + +/** This is a handy internal MACRO used to increment over all the cores which are + * valid AND enabled. This should be used STRICTLY as a FOR loop replacement! + */ +#define DVP_FOR_EACH_CORE(c) for (c = (DVP_CORE_MIN+1); c < DVP_CORE_REMOTE_MAX; c++) + +static int dvp_mem_range_sort(btreelistnode_t *node, btreelistnode_t *obj) +{ + DVP_Memory_Range_t *r = (DVP_Memory_Range_t *)node; + DVP_Memory_Range_t *s = (DVP_Memory_Range_t *)obj; + + if (s->end <= r->base) + return -1; + else if (r->end <= s->base) + return 1; + else // any overlap + return 0; +} + +static int dvp_mem_range_compare(btreelistnode_t *node, value_t value) +{ + DVP_Memory_Range_t *r = (DVP_Memory_Range_t *)node; + + if (r->base <= value && value < r->end) + return 0; + else if (value < r->base) + return -1; + else // if (value >= r->end) + return 1; +} + +static char *dvp_mem_range_print(btreelistnode_t *node) +{ + static char values[255]; + DVP_Memory_Range_t *r = (DVP_Memory_Range_t *)node; + sprintf(values, "base "FMT_VALUE_T" end "FMT_VALUE_T"", r->base, r->end); + return values; +} + +//****************************************************************************** +// GLOBAL FUNCTIONS +//****************************************************************************** + +void dvp_rpc_mem_remove(DVP_RPC_t *rpc, DVP_PTR localAddr, DVP_U32 localSize, DVP_MemType_e memType) +{ + rpc = rpc; + localAddr = localAddr; + localSize = localSize; + memType = memType; +} + +DVP_PTR dvp_rpc_mem_xlate_fwrd(DVP_RPC_t *rpc, DVP_Core_e core, DVP_PTR localAddr, DVP_U32 localSize, DVP_MemType_e memType) +{ + DVP_PTR remoteAddr = NULL; + rpc = rpc; // remove warning + core = core;// remove warning + localSize = localSize; // remove warning + memType = memType; // remove warning + // when RCM is off, everything is local (kernel does OMAPRPC translations) + remoteAddr = localAddr; + return remoteAddr; +} + +DVP_PTR dvp_rpc_mem_xlate_back(DVP_RPC_t *rpc, DVP_Core_e core, DVP_PTR remoteAddr, DVP_MemType_e memType) +{ + DVP_PTR localAddr = NULL; + rpc = rpc; // remove warning + core = core; // remove warning + memType = memType; // remove warning + // when RCM is off, everything is local (kernel does OMAPRPC translations) + localAddr = remoteAddr; + return localAddr; +} + +DVP_BOOL dvp_rpc_flush(DVP_RPC_t *rpc, DVP_Core_e core __attribute__((unused)), DVP_PTR address, DVP_U32 size, DVP_MemType_e mtype) +{ + DVP_BOOL ret = DVP_FALSE; + if (rpc) + { + DVP_PRINT(DVP_ZONE_RPC, "Flushing address:%p for %u bytes type:%d core:%d\n", address, size, mtype, core); + DVP_Dim_t dims[1] = {{{{1,size,1}}}}; + DVP_PTR ptrs[1] = {(DVP_PTR)address}; + core = DVP_CORE_MIN; + size = 0; + // 1 pointer, 2 dimensions (bpp and width so to speak) + ret = dvp_mem_flush(rpc->handle, mtype, dimof(ptrs), 2, dims, ptrs); + } + return ret; +} + +DVP_BOOL dvp_rpc_invalidate(DVP_RPC_t *rpc, DVP_Core_e core __attribute__((unused)), DVP_PTR address, DVP_U32 size, DVP_MemType_e mtype) +{ + DVP_BOOL ret = DVP_FALSE; + if (rpc) + { + DVP_PRINT(DVP_ZONE_RPC, "Invalidating address:%p for %u bytes type:%d core:%d\n", address, size, mtype, core); + DVP_Dim_t dims[1] = {{{{1,size,1}}}}; + DVP_PTR ptrs[1] = {(DVP_PTR)address}; + core = DVP_CORE_MIN; + size = 0; + ret = dvp_mem_invalidate(rpc->handle, mtype, dimof(ptrs), 2, dims, ptrs); + } + return ret; +} + +void dvp_rpc_prepare_image(DVP_RPC_t *rpc, DVP_Core_e core, DVP_Image_t *pImage, DVP_BOOL cacheOp, DVP_PTR base, DVP_RPC_Translation_t *trans) +{ + DVP_U32 p = 0; + DVP_BOOL cached = DVP_TRUE; + + // Remove warnings + base = base; + trans = trans; + + if (trans == NULL) + return; + +#if defined(DVP_USE_GRALLOC) || defined(DVP_USE_BO) + if (pImage->memType == DVP_MTYPE_DISPLAY_2DTILED) + cached = DVP_FALSE; +#endif +#if defined(DVP_USE_ION) || defined(DVP_USE_BO) + if (pImage->memType == DVP_MTYPE_MPUNONCACHED_1DTILED || + pImage->memType == DVP_MTYPE_MPUNONCACHED_2DTILED) + cached = DVP_FALSE; +#endif +#if defined(DVP_USE_GRALLOC) + if (pImage->memType == DVP_MTYPE_GRALLOC_2DTILED) + cached = DVP_FALSE; +#endif + for (p = 0; p < pImage->planes; p++) + { + DVP_U32 planeSize = DVP_Image_PlaneSize(pImage, p); + if (cached && cacheOp && !pImage->skipCacheOpFlush) { + DVP_COMPLAIN_IF_FALSE(dvp_rpc_flush(rpc, core, pImage->pBuffer[p], planeSize, pImage->memType)); + } + + { + ptr_t handle = NULL; + core = core; // @TODO put the desired core into the translation structure to speed up lookups + fph_get(rpc->hndl_hash, (ptr_t)pImage->pBuffer[p], &handle); + trans->translations[trans->numTranslations].cacheops = cacheOp; + trans->translations[trans->numTranslations].offset = ((DVP_U32)&pImage->pData[p] - (DVP_U32)base); + trans->translations[trans->numTranslations].base = (DVP_U32)pImage->pBuffer[p]; +#if defined(DVP_USE_GRALLOC) + if (pImage->memType == DVP_MTYPE_DISPLAY_2DTILED || + pImage->memType == DVP_MTYPE_GRALLOC_2DTILED) + { + // gralloc fd needs to be passed down + trans->translations[trans->numTranslations].reserved = (DVP_PTR)(((IMG_native_handle_t *)pImage->reserved)->fd[p]); + } + else +#elif defined(DVP_USE_BO) + if (pImage->memType == DVP_MTYPE_MPUCACHED_1DTILED || + pImage->memType == DVP_MTYPE_MPUNONCACHED_1DTILED || + pImage->memType == DVP_MTYPE_MPUNONCACHED_2DTILED || + pImage->memType == DVP_MTYPE_DISPLAY_2DTILED) + { + // give the driver the file descriptor of the DMA BUF (each plane has it's own fd). + trans->translations[trans->numTranslations].reserved = (DVP_PTR)(((alloc_omap_bo_t *)handle)->dmabuf_fd); + } + else +#endif + { + trans->translations[trans->numTranslations].reserved = handle; + } + DVP_PRINT(DVP_ZONE_RPC, "+[%u] TRANS BASE:%p OFF:0x%08x DATA BASE:%p DATA:%p RESV:%p\n", + trans->numTranslations, + base, + trans->translations[trans->numTranslations].offset, + (DVP_PTR)pImage->pBuffer[p], + (DVP_PTR)pImage->pData[p], + trans->translations[trans->numTranslations].reserved); + trans->numTranslations++; + } + } +} + +void dvp_rpc_return_image(DVP_RPC_t *rpc, DVP_Core_e core, DVP_Image_t *pImage, DVP_BOOL cacheOp) +{ + DVP_BOOL cached = DVP_TRUE; + DVP_U32 p = 0; + + #if defined(DVP_USE_GRALLOC) || defined(DVP_USE_BO) + if (pImage->memType == DVP_MTYPE_DISPLAY_2DTILED) + cached = DVP_FALSE; +#endif +#if defined(DVP_USE_ION) || defined(DVP_USE_BO) + if (pImage->memType == DVP_MTYPE_MPUNONCACHED_1DTILED || + pImage->memType == DVP_MTYPE_MPUNONCACHED_2DTILED) + cached = DVP_FALSE; +#endif +#if defined(DVP_USE_GRALLOC) + if (pImage->memType == DVP_MTYPE_GRALLOC_2DTILED) + cached = DVP_FALSE; +#endif + for (p = 0; p < pImage->planes; p++) + { + DVP_U32 planeSize = DVP_Image_PlaneSize(pImage, p); + pImage->pBuffer[p] = dvp_rpc_mem_xlate_back(rpc, core, pImage->pBuffer[p], pImage->memType); + if (cached && cacheOp && !pImage->skipCacheOpInval) { + DVP_COMPLAIN_IF_FALSE(dvp_rpc_invalidate(rpc, core, (DVP_PTR)pImage->pBuffer[p], planeSize, pImage->memType)); + } + } +} + +void dvp_rpc_prepare_buffer(DVP_RPC_t *rpc, DVP_Core_e core, DVP_Buffer_t *pBuffer, DVP_BOOL cacheOp, DVP_PTR base, DVP_RPC_Translation_t *trans) +{ + DVP_BOOL cached = DVP_TRUE; + + // Remove warnings + base = base; + trans = trans; + +#if defined(DVP_USE_ION) || defined(DVP_USE_BO) + if (pBuffer->memType == DVP_MTYPE_MPUNONCACHED_1DTILED) + cached = DVP_FALSE; +#endif + if (cached && cacheOp && !pBuffer->skipCacheOpFlush) { + DVP_COMPLAIN_IF_FALSE(dvp_rpc_flush(rpc, core, pBuffer->pData, pBuffer->numBytes, pBuffer->memType)); + } + + if (trans) + { + ptr_t handle = NULL; + core = core; // @TODO put core into translation structure + fph_get(rpc->hndl_hash, (ptr_t)pBuffer->pData, &handle); + trans->translations[trans->numTranslations].cacheops = cacheOp; + trans->translations[trans->numTranslations].offset = ((DVP_U32)&pBuffer->pData - (DVP_U32)base); + trans->translations[trans->numTranslations].base = (DVP_U32)pBuffer->pData; +#if defined(DVP_USE_BO) + trans->translations[trans->numTranslations].reserved = (DVP_PTR)(((alloc_omap_bo_t *)handle)->dmabuf_fd); +#else + trans->translations[trans->numTranslations].reserved = handle; +#endif + trans->numTranslations++; + } +} + +void dvp_rpc_return_buffer(DVP_RPC_t *rpc, DVP_Core_e core, DVP_Buffer_t *pBuffer, DVP_BOOL cacheOp) +{ + DVP_BOOL cached = DVP_TRUE; +#if defined(DVP_USE_ION) || defined(DVP_USE_BO) + if (pBuffer->memType == DVP_MTYPE_MPUNONCACHED_1DTILED) + cached = DVP_FALSE; +#endif + pBuffer->pData = dvp_rpc_mem_xlate_back(rpc, core, pBuffer->pData, pBuffer->memType); + if (cached && cacheOp && !pBuffer->skipCacheOpInval) { + DVP_COMPLAIN_IF_FALSE(dvp_rpc_invalidate(rpc, core, (DVP_PTR)pBuffer->pData, pBuffer->numBytes, pBuffer->memType)); + } +} + +DVP_VALUE dvp_rpc_get_handle(DVP_RPC_t *rpc, DVP_PTR ptr) +{ + DVP_VALUE handle = 0; + DVP_VALUE value = 0; + if (rpc != NULL && ptr != NULL) + { + // check the ranges first for the base pointer + DVP_Memory_Range_t *mrange = (DVP_Memory_Range_t *)btreelist_find(rpc->ranges, (value_t)ptr); + if (mrange) { + DVP_PRINT(DVP_ZONE_MEM, "PTR:%p has BASE:%p, replacing in query!\n", ptr, (ptr_t)mrange->base); + ptr = (DVP_PTR)mrange->base; + } + if (fph_get(rpc->hndl_hash, ptr, (ptr_t *)&handle)) + { + DVP_PRINT(DVP_ZONE_MEM, "PTR:%p => HDL:"FMT_VALUE_T"\n", ptr, handle); +#if defined(DVP_USE_BO) + value = ((alloc_omap_bo_t *)handle)->dmabuf_fd; +#elif defined(DVP_USE_ION) + value = handle; +#endif + } + else + { + DVP_PRINT(DVP_ZONE_WARNING, "PTR:%p was not in handle hash! (this may be ok)\n", ptr); + } + } + return value; + } + +DVP_BOOL dvp_rpc_dissociate(DVP_RPC_t *rpc, DVP_Mem_t *mem, DVP_PTR ptr, DVP_VALUE *pHandle, size_t size, DVP_MemType_e mtype) +{ + DVP_BOOL ret = DVP_TRUE; + + if (rpc == NULL || mem == NULL || ptr == NULL || size == 0) + return DVP_FALSE; + + switch (mtype) + { +#if defined(DVP_USE_ION) || defined(DVP_USE_BO) + case DVP_MTYPE_MPUCACHED_1DTILED: + case DVP_MTYPE_MPUNONCACHED_1DTILED: + case DVP_MTYPE_MPUNONCACHED_2DTILED: +#endif +#if defined(DVP_USE_GRALLOC) + case DVP_MTYPE_GRALLOC_2DTILED: + case DVP_MTYPE_DISPLAY_2DTILED: +#endif + case DVP_MTYPE_MPUCACHED_VIRTUAL_SHARED: + { + DVP_Memory_Range_t *mrange = NULL; + mutex_lock(&rpc->lock); + if (fph_get(rpc->hndl_hash, ptr, (ptr_t *)pHandle)) { + // pHandle is now set + DVP_Core_e core; + // clear out the handle + fph_set(rpc->hndl_hash, ptr, NULL); + // unregister from each core + if (mtype == DVP_MTYPE_MPUNONCACHED_1DTILED || + mtype == DVP_MTYPE_MPUNONCACHED_2DTILED || + mtype == DVP_MTYPE_MPUCACHED_1DTILED) + { +#if defined(SOSAL_USE_ION) && defined(DVP_USE_ION) && defined(OMAPRPC_USE_ION) + DVP_FOR_EACH_CORE(core) { + // if the core is enabled and actually is running + if (dvp_core_names[core].enabled && rpc->cores[core]) { + omaprpc_unregister(rpc->cores[core]->rpc, 0, ptr, (void **)pHandle); + } + } +#endif + } + // remove the range from the tree + mrange = (DVP_Memory_Range_t *)btreelist_remove(rpc->ranges, (value_t)ptr); + if (mrange) + free(mrange); + } + else + ret = DVP_FALSE; + mutex_unlock(&rpc->lock); + break; + } + case DVP_MTYPE_MPUCACHED_VIRTUAL: + default: + ret = DVP_FALSE; + break; + } + if (ret == DVP_TRUE) { + DVP_PRINT(DVP_ZONE_RPC, "Dissociated %p of "FMT_SIZE_T" bytes (hdl: "FMT_VALUE_T")\n", ptr, size, *pHandle); + } else { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to dissociate %p of "FMT_SIZE_T" bytes (hdl: "FMT_VALUE_T")\n", ptr, size, *pHandle); + } + return ret; +} + +DVP_BOOL dvp_rpc_associate(DVP_RPC_t *rpc, DVP_Mem_t *mem, DVP_PTR ptr, DVP_VALUE handle, size_t size, DVP_MemType_e mtype) +{ + DVP_BOOL ret = DVP_TRUE; + + if (rpc == NULL || mem == NULL || ptr == NULL || size == 0) + return DVP_FALSE; + + DVP_PRINT(DVP_ZONE_RPC, "Associating PTR:%p HDL:"FMT_VALUE_T" SIZE:%zu TYPE:%d\n", ptr, handle, size, mtype); + switch (mtype) + { +#if defined(DVP_USE_ION) || defined(DVP_USE_BO) + case DVP_MTYPE_MPUCACHED_1DTILED: // not supported on ICS + case DVP_MTYPE_MPUNONCACHED_1DTILED: + case DVP_MTYPE_MPUNONCACHED_2DTILED: +#endif +#if defined(DVP_USE_GRALLOC) + case DVP_MTYPE_GRALLOC_2DTILED: + case DVP_MTYPE_DISPLAY_2DTILED: // not supported on ICS +#endif + case DVP_MTYPE_MPUCACHED_VIRTUAL_SHARED: + { + DVP_Memory_Range_t *mrange = (DVP_Memory_Range_t *)calloc(1, sizeof(DVP_Memory_Range_t)); + if (mrange) + { + mrange->base = (uint32_t)ptr; + mrange->end = (uint32_t)ptr + (uint32_t)size; + } + mutex_lock(&rpc->lock); + btreelist_add(rpc->ranges, (btreelistnode_t *)mrange); + if (fph_set(rpc->hndl_hash, (ptr_t)ptr, (ptr_t)handle) == 0) + { + // failed + mrange = (DVP_Memory_Range_t *)btreelist_remove(rpc->ranges, (value_t)ptr); + free(mrange); + } + else if (mtype == DVP_MTYPE_MPUCACHED_1DTILED || + mtype == DVP_MTYPE_MPUNONCACHED_1DTILED || + mtype == DVP_MTYPE_MPUNONCACHED_2DTILED) + { +#if defined(SOSAL_USE_ION) && defined(DVP_USE_ION) && defined(OMAPRPC_USE_ION) + DVP_Core_e core; + DVP_FOR_EACH_CORE(core) { + if (dvp_core_names[core].enabled && rpc->cores[core]) { + int fd = allocator_get_device(mem, dvp_mem_type_xlate(mtype)); + omaprpc_register(rpc->cores[core]->rpc, fd, ptr, (void **)&handle); + } + } +#endif + } + mutex_unlock(&rpc->lock); + break; + } + case DVP_MTYPE_MPUCACHED_VIRTUAL: // not supported on ICS + default: // not supported + ret = DVP_FALSE; + break; + } + return ret; +} + +void dvp_rpc_deinit(DVP_RPC_t **rpc) +{ + if (rpc && *rpc) + { + btreelist_destroy((*rpc)->ranges); + fph_deinit((*rpc)->hndl_hash); + mutex_deinit(&(*rpc)->lock); + free(*rpc); + *rpc = NULL; + } +} + + +DVP_RPC_t *dvp_rpc_init() +{ + DVP_RPC_t *rpc = (DVP_RPC_t *)calloc(1,sizeof(DVP_RPC_t)); + if (rpc) + { + mutex_init(&rpc->lock); + rpc->hndl_hash = fph_init(DVP_RPC_NUM_BLOCKS, DVP_RPC_BLOCK_SIZE, NULL); + rpc->ranges = btreelist_create(dvp_mem_range_compare, dvp_mem_range_sort, dvp_mem_range_print); + } + DVP_Perf_Clear(&rpc_perf); + return rpc; +} + +void dvp_rpc_core_deinit(DVP_RPC_t *rpc, DVP_RPC_Core_t **rpcc) +{ + if (rpc && rpcc && *rpcc) + { + omaprpc_close(&(*rpcc)->rpc); + free(*rpcc); + *rpcc = NULL; + } +} + +static void dvp_rpc_restart_callback(omaprpc_t *rpc __attribute__((unused)), void *cookie) +{ + DVP_RPC_Core_t *rpcc = (DVP_RPC_Core_t *)cookie; + if (rpcc && rpcc->callback) + { + // this is typecast due to the way we define the DVP_RPC_Core_t structure. + dvp_rpc_restart_f callback = (dvp_rpc_restart_f)rpcc->callback; + + DVP_PRINT(DVP_ZONE_RPC, "RESTART Callback issued to %p\n", rpcc->callback); + callback(rpcc->cookie); + } +} + +void dvp_rpc_restart_callback_register(DVP_RPC_t *rpc, + DVP_RPC_Core_t *rpcc, + dvp_rpc_restart_f func, + void *cookie) +{ + if (rpc && rpcc && func) + { + rpcc->callback = (void *)func; + rpcc->cookie = cookie; + } +} + +DVP_RPC_Core_t *dvp_rpc_core_init(DVP_RPC_t *rpc, DVP_RPC_Interface_t *rpci) +{ + DVP_RPC_Core_t *rpcc = NULL; + int32_t status = 0; + + if (rpc == NULL || rpci == NULL) + return NULL; + + rpcc = (DVP_RPC_Core_t *)calloc(1,sizeof(DVP_RPC_Core_t)); + if (rpcc) + { + DVP_Core_e core = rpci->coreEnum; + rpcc->coreEnum = core; + if (DVP_VALID_REMOTE_CORE(core) && dvp_rpc_core_is_enabled(core)) + { + DVP_PRINT(DVP_ZONE_RPC, "DVP_RPC: Interfacing to CORE:%d\n",core); + rpcc->rpc = omaprpc_open(dvp_core_names[core].device_name, dvp_core_names[core].server_name, rpci->numRemoteFunctions); + if (rpcc->rpc == NULL) + { + status = -1; + DVP_PRINT(DVP_ZONE_RPC, "DVP_RPC: CORE:%u is disabled!\n", core); + dvp_core_names[core].enabled = false_e; + } + else + { + status = 0; + dvp_core_names[core].enabled = true_e; + rpc->cores[core] = rpcc; + omaprpc_restart_callback(rpcc->rpc, rpcc, dvp_rpc_restart_callback, DVP_MAX_RESTART_RETRY); + } + if (status < 0) + goto leave; + DVP_PRINT(DVP_ZONE_RPC, "Successfully installed DVP RPC for CORE %d!\n",core); + } + else + { + status = -1; // not a valid core + } + } +leave: + if (status < 0) // if ANY failure! + { + dvp_rpc_core_deinit(rpc, &rpcc); + } + return rpcc; +} + +int dvp_rpc_remote_execute(DVP_RPC_t *rpc, DVP_RPC_Core_t *rpcc, int cliIndex, DVP_RPC_Parameter_t *params, DVP_U32 numParams, DVP_RPC_Translation_t *trans) +{ + int ret = 0; + + if (rpc == NULL || rpcc == NULL) + return 0; + + // trans can be NULL if there is nothing to translate + // remove warnings + trans = trans; + + DVP_U32 numTranslations = 0; + DVP_U32 i, size = 0; + struct omaprpc_call_function_t *function = NULL; + struct omaprpc_function_return_t returned; + + if (numParams > OMAPRPC_MAX_PARAMETERS) + return -1; + + if (trans) + numTranslations = trans->numTranslations; + + DVP_PerformanceStart(&rpc_perf); + + // compute the size the structure plus the number of translations times the + // size of a translation. + size = sizeof(struct omaprpc_call_function_t); + size += (numTranslations * sizeof(struct omaprpc_param_translation_t)); + + DVP_PRINT(DVP_ZONE_RPC, "Allocating %u bytes for Function Call\n", size); + + // allocate the function structure + function = (struct omaprpc_call_function_t *)calloc(1, size); + if (function) + { + // transfer the parameter structures over to the OMAPRPC mechanisms + function->func_index = cliIndex; + function->num_params = numParams; + for (i = 0; i < numParams; i++) + { + DVP_PRINT(DVP_ZONE_RPC, "PARAM[%u] TYPE: %u DATA: 0x%x SIZE: %u RESV: %p\n", + i, params[i].type, *(DVP_U32 *)params[i].data, params[i].size, params[i].reserved); + function->params[i].size = params[i].size; + if (params[i].reserved) + { + DVP_Memory_Range_t *r = NULL; + function->params[i].type = OMAPRPC_PARAM_TYPE_PTR; + function->params[i].data = (uint32_t)*(DVP_PTR *)params[i].data; + function->params[i].base = (uint32_t)*(DVP_PTR *)params[i].data; // default to same value + r = (DVP_Memory_Range_t *)btreelist_find(rpc->ranges, *(value_t *)params[i].data); + if (r) + { + DVP_PRINT(DVP_ZONE_RPC, "Found Data %p base address %p\n", *(DVP_PTR *)params[i].data, (DVP_PTR)r->base); + function->params[i].base = r->base; + } + function->params[i].reserved = (uint32_t)params[i].reserved; + } + else + { + switch (params[i].size) + { + case sizeof(DVP_U08): + function->params[i].type = OMAPRPC_PARAM_TYPE_ATOMIC; + function->params[i].data = (uint32_t)*(DVP_U08 *)params[i].data; + break; + case sizeof(DVP_U16): + function->params[i].type = OMAPRPC_PARAM_TYPE_ATOMIC; + function->params[i].data = (uint32_t)*(DVP_U16 *)params[i].data; + break; + case sizeof(DVP_U32): + function->params[i].type = OMAPRPC_PARAM_TYPE_ATOMIC; + function->params[i].data = *(DVP_U32 *)params[i].data; + break; + default: + function->params[i].type = OMAPRPC_PARAM_TYPE_STRUCT; + function->params[i].data = 0; // this is not supported yet. + DVP_PRINT(DVP_ZONE_ERROR, "Inside an unsupported case!!\n"); + break; + } + } + } + if (trans && trans->numTranslations > 0) + { + function->num_translations = trans->numTranslations; + for (i = 0; i < trans->numTranslations; i++) + { + DVP_PTR ptr = *(DVP_PTR*)(function->params[trans->translations[i].index].data + trans->translations[i].offset); + ptr = ptr; // warnings + DVP_PRINT(DVP_ZONE_RPC, "TRANS[%04u] IDX:%u DATA:%p PTR:%p RESV:%p OFF:%u (0x%08x) \n", + i, trans->translations[i].index, + (DVP_PTR)function->params[trans->translations[i].index].data, + ptr, + trans->translations[i].reserved, + trans->translations[i].offset, + trans->translations[i].offset); + function->translations[i].index = trans->translations[i].index; + function->translations[i].offset = trans->translations[i].offset; + function->translations[i].base = trans->translations[i].base; + function->translations[i].cacheOps = trans->translations[i].cacheops; + function->translations[i].reserved = (uint32_t)trans->translations[i].reserved; // @TODO bit depth problem on 64 bit platform! + } + } +#if DVP_DEBUG == 1 + fflush(stdout); // make sure all the prints are flushed before we call the kernel, else we'll lose some debugging. +#endif + if (omaprpc_call(rpcc->rpc, function, &returned) == false_e) + { + DVP_PRINT(DVP_ZONE_ERROR, "OMAPRPC Call failed!\n"); + ret = -1; + } + else + ret = returned.status; + + free(function); + } + DVP_PerformanceStop(&rpc_perf); + DVP_PerformancePrint(&rpc_perf, "DVP RPC EXEC"); + return ret; + +} + +#endif + +//****************************************************************************** +// END +//****************************************************************************** diff --git a/source/dvp/dvp_kgraph/dvp_rpc_rcm.c b/source/dvp/dvp_kgraph/dvp_rpc_rcm.c new file mode 100644 index 0000000..3e4aeb7 --- /dev/null +++ b/source/dvp/dvp_kgraph/dvp_rpc_rcm.c @@ -0,0 +1,1090 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(DVP_USE_RCM) + +//****************************************************************************** +// INCLUDES +//****************************************************************************** + +#include + +#include +#include +// @NOTE we include dvp_rpc.h further down in the file... + +// RCM/Syslink Includes +#include +#include +#include +#include +#include + +#ifdef DVP_USE_TILER +#include +#include +#endif + +//****************************************************************************** +// #DEFINES +//****************************************************************************** + +#define DVP_RPC_BLOCK_SIZE (64) +#define DVP_RPC_NUM_BLOCKS (64) + +#define PROC_VALID_ID(x) (-1 < (x) && (x) < PROC_END) + +#define RCM_GOTO_IF_FAILED(s, statement, label) { \ + s = statement;\ + if (s < 0) { \ + printf(""#statement" failed (%d) at %s:%u\n", s,__FILE__, __LINE__);\ + goto label; \ + }\ +} + +#define RCM_COMPLAIN_IF_FAILED(s, statement) { \ + s = statement;\ + if (s < 0) { \ + printf(""#statement" failed (%d) at %s:%u\n", s, __FILE__, __LINE__);\ + }\ +} + +//****************************************************************************** +// TYPEDEFS +//****************************************************************************** + +#define DVP_MAX_SERVER_NAME (20) +typedef struct _dvp_proc_t { + UInt16 id; /**< Used to contain the actual ID of the core, use dvp_rpc_getid() for the functional id */ + DVP_U32 entry; + ProcMgr_Handle handle; + ProcMgr_AttachParams params; +} DVP_Proc_t; + +typedef struct _dvp_server_t { + char name[DVP_MAX_SERVER_NAME]; + RcmServer_Params params; + RcmServer_Handle handle; + struct _dvp_function_t *calls; + DVP_U32 numCalls; +} DVP_Server_t; + +typedef struct _dvp_client_t { + char name[DVP_MAX_SERVER_NAME]; + RcmClient_Params params; + RcmClient_Handle handle; + struct _dvp_function_t *calls; + DVP_U32 numCalls; +} DVP_Client_t; + +#define DVP_CORE_REMOTE_MAX (DVP_CORE_CPU) + +typedef struct _dvp_memory_range_t { + btreelistnode_t node; + value_t base; + value_t end; +} DVP_Memory_Range_t; + +typedef struct _dvp_rpc_core_t DVP_RPC_Core_t; // forward definition + +typedef struct _dvp_rpc_t { + DVP_Handle handle; /** This contains the pointer back the DVP_t. It MUST be the FIRST entry in the structure! */ + mutex_t lock; + Ipc_Config config; + DVP_Proc_t procs[DVP_CORE_REMOTE_MAX]; + fph_t *mpu2rpu_hash[DVP_CORE_REMOTE_MAX]; + fph_t *rpu2mpu_hash[DVP_CORE_REMOTE_MAX]; +#if defined(DVP_USE_TILER) + fph_t *tiler2rpu_hash[DVP_CORE_REMOTE_MAX]; + fph_t *rpu2tiler_hash[DVP_CORE_REMOTE_MAX]; + fph_t *tiler2mpu_hash; + fph_t *mpu2tiler_hash; +#endif +} DVP_RPC_t; + +struct _dvp_rpc_core_t { + DVP_S32 coreEnum; + DVP_Server_t server; + DVP_Client_t client; + void *callback; // will be later cast the proper type + void *cookie; +}; + +#define DVP_RPC_T // we're defining the RPC structure locally! +#include + +#define DVP_VALID_REMOTE_CORE(x) (DVP_CORE_MIN < (x) && (x) < DVP_CORE_REMOTE_MAX) + +typedef struct _dvp_core_to_name_t { + bool_e enabled; + DVP_Core_e core; + char *name; + char *server_name; + char *client_name; +} DVP_Core_Name_t; + +//****************************************************************************** +// LOCAL VARIABLES +//****************************************************************************** + +#if defined(BLAZE) || defined(SDP) || defined(BLAZE_TABLET) || defined(PANDA) +#define IS_TESLA_ENABLED true_e +#else //p920, GT_I9100G, PLAYBOOK, other platforms +#define IS_TESLA_ENABLED false_e +#endif + +#if defined(TARGET_DVP_OMAP4) +static DVP_Core_Name_t dvp_core_names[] = { + {IS_TESLA_ENABLED, DVP_CORE_DSP, "Tesla", "DVPSrv_ChironDSP", "DVPSrv_Tesla"}, + {true_e, DVP_CORE_SIMCOP, "AppM3", "DVPSrv_ChironSIMCOP", "DVPSrv_Ducati1"}, + {false_e, DVP_CORE_MCU0, "AppM3", "DVPSrv_ChironMCU0", "DVPSrv_Ducati2"}, + {false_e, DVP_CORE_MCU1, "SysM3", "DVPSrv_ChironMCU1", "DVPSrv_Ducati1"}, + {false_e, DVP_CORE_GPU, "SGX", "DVPSrv_ChironSGX", NULL}, + {false_e, DVP_CORE_EVE, "EVE", "DVPSrv_ChironEVE", NULL}, + {true_e, DVP_CORE_CPU, "MPU", NULL, NULL}, +}; +#endif // OMAP types + +static DVP_Perf_t rpc_perf; + +//****************************************************************************** +// LOCAL FUNCTIONS +//****************************************************************************** + +static ProcMgr_ProcId dvp_rpc_getid(DVP_Core_e core) +{ + switch (core) + { +#if defined(TARGET_DVP_OMAP4) + case DVP_CORE_DSP: + return PROC_TESLA; + case DVP_CORE_SIMCOP: + case DVP_CORE_MCU0: + case DVP_CORE_MCU1: + return PROC_SYSM3; +#endif + case DVP_CORE_CPU: + default: + return PROC_MPU; + } +} + +static DVP_Core_e dvp_rpc_next_core(DVP_Core_e core) +{ + if (!DVP_VALID_CORE(core)) + core = DVP_CORE_MIN; + do { + core += 1; + } while (core < DVP_CORE_MAX && dvp_core_names[core].enabled == false_e); + return core; +} + +static bool_e dvp_rpc_core_is_enabled(DVP_Core_e core) +{ + DVP_U32 i = 0; + for (i = 0; i < DVP_CORE_MAX; i++) + if (core == dvp_core_names[i].core) + return dvp_core_names[i].enabled; + return false_e; +} + +static int dvp_rpc_server_deinit(DVP_Server_t *s) +{ + Int status = 0; + RCM_COMPLAIN_IF_FAILED(status, RcmServer_delete(&s->handle)); + RcmServer_exit(); + return status; +} + +static int dvp_rpc_server_init(DVP_Server_t *s) +{ + DVP_U32 f = 0; + Int status = 0; + RcmServer_init(); + RCM_GOTO_IF_FAILED(status, RcmServer_Params_init(&s->params),leave); + RCM_GOTO_IF_FAILED(status, RcmServer_create(s->name, &s->params, &s->handle),leave); + for (f = 0; f < s->numCalls; f++) { + RCM_GOTO_IF_FAILED(status, RcmServer_addSymbol(s->handle, s->calls[f].name, (RcmServer_MsgFxn)s->calls[f].function, &s->calls[f].index),leave); + DVP_PRINT(DVP_ZONE_RPC, "%s[%u] %s\n", s->name, s->calls[f].index, s->calls[f].name); + } + RcmServer_start(s->handle); +leave: + //if (status < 0) + // dvp_rpc_server_deinit(s); + return status; +} + +static int dvp_rpc_client_deinit(DVP_Client_t *c) +{ + Int status = 0; + RCM_COMPLAIN_IF_FAILED(status, RcmClient_delete(&c->handle)); + RcmClient_exit(); + return status; +} + +static int dvp_rpc_client_init(DVP_Client_t *c) +{ + DVP_U32 i = 0; + Int status = 0; + RcmClient_init(); + RCM_GOTO_IF_FAILED(status, RcmClient_Params_init(&c->params),leave); + c->params.heapId = 1; /// @todo Determine which heap is this exactly. + DVP_PRINT(DVP_ZONE_RPC, "Attempting to connect to remote server %s\n", c->name); + RCM_GOTO_IF_FAILED(status, RcmClient_create(c->name, &c->params, &c->handle),leave); + DVP_PRINT(DVP_ZONE_RPC, "Connected to remote server %s\n", c->name); + DVP_PRINT(DVP_ZONE_RPC, "Attempting to get the indexes of %u functions!\n", c->numCalls); + for (i = 0; i < c->numCalls; i++) + { + RCM_GOTO_IF_FAILED(status, RcmClient_getSymbolIndex(c->handle, c->calls[i].name, &c->calls[i].index), leave); + DVP_PRINT(DVP_ZONE_RPC, "REMOTE %s::%s[%u]\n",c->name, c->calls[i].name, c->calls[i].index); + } +leave: + //if (status < 0) + // dvp_rpc_client_deinit(c); + return status; +} + + +/** This is a handy internal MACRO used to increment over all the cores which are + * valid AND enabled. This should be used STRICTLY as a FOR loop replacement! + */ +#define DVP_FOR_EACH_CORE(c) for (c = dvp_rpc_next_core(DVP_CORE_MIN); c < DVP_CORE_REMOTE_MAX; c = dvp_rpc_next_core(c)) + +//****************************************************************************** +// GLOBAL FUNCTIONS +//****************************************************************************** + +void dvp_rpc_mem_remove(DVP_RPC_t *rpc, DVP_PTR localAddr, DVP_U32 localSize, DVP_MemType_e memType) +{ + DVP_PTR remoteAddr = NULL; + DVP_Core_e core; + mutex_lock(&rpc->lock); + if (memType == DVP_MTYPE_MPUCACHED_VIRTUAL) + { +#if defined(DVP_USE_TILER) + DVP_PTR tilerAddr = NULL; + + if (fph_get(rpc->mpu2tiler_hash, localAddr, &tilerAddr)) + { + DVP_FOR_EACH_CORE(core) + { + if (fph_get(rpc->tiler2rpu_hash[core], tilerAddr, &remoteAddr)) { +#if defined(__QNX__) + ProcMgr_AddrInfo info; + memset(&info, 0, sizeof(info)); + info.addr[ProcMgr_AddrType_SlaveVirt] = (UInt32)remoteAddr; + info.isCached = TRUE; + info.size = localSize; + ProcMgr_unmap(rpc->procs[core].handle, ProcMgr_MapType_Tiler, &info, ProcMgr_AddrType_SlaveVirt); +#else + ProcMgr_unmap(rpc->procs[core].handle, (UInt32)remoteAddr, dvp_rpc_getid(core)); +#endif + } + + fph_clr(rpc->tiler2rpu_hash[core], tilerAddr); + fph_clr(rpc->rpu2tiler_hash[core], remoteAddr); + } + MemMgr_UnMap(tilerAddr); + fph_clr(rpc->tiler2mpu_hash, tilerAddr); + fph_clr(rpc->mpu2tiler_hash, localAddr); + } +#endif + } + else + { + DVP_FOR_EACH_CORE(core) + { + // get the remote address + if (fph_get(rpc->mpu2rpu_hash[core], localAddr, &remoteAddr)) + { + int status = 0; + DVP_PRINT(DVP_ZONE_MEM, "DVP RPC MEM: Found %p as %p on core %d, removing!\n", localAddr, remoteAddr, core); +#if !defined(__QNX__) + // unmap that address + if (localSize != 0) + status = ProcMgr_unmap(rpc->procs[core].handle, (UInt32)remoteAddr, dvp_rpc_getid(core)); +#else + if (localSize != 0) { + ProcMgr_AddrInfo info; + memset(&info, 0, sizeof(info)); + info.addr[ProcMgr_AddrType_SlaveVirt] = (UInt32)remoteAddr; + info.isCached = TRUE; + info.size = localSize; + status = ProcMgr_unmap(rpc->procs[core].handle, ProcMgr_MapType_Tiler, &info, ProcMgr_AddrType_SlaveVirt); + } +#endif + DVP_PRINT(DVP_ZONE_MEM, "Unmap returned %d\n", status); + // remove the local->remote hash + fph_clr(rpc->mpu2rpu_hash[core], localAddr); + // remove the remote->local hash + fph_clr(rpc->rpu2mpu_hash[core], remoteAddr); + + DVP_PRINT(DVP_ZONE_MEM, "DVP RPC MEM: Removed %p from all hashes and cores!\n", localAddr); + } + } + } + mutex_unlock(&rpc->lock); +} + +DVP_PTR dvp_rpc_mem_xlate_fwrd(DVP_RPC_t *rpc, DVP_Core_e core, DVP_PTR localAddr, DVP_U32 localSize, DVP_MemType_e memType) +{ + DVP_PTR remoteAddr = NULL; + DVP_BOOL unwind = DVP_FALSE; + ProcMgr_MapType maptype = 0; + + mutex_lock(&rpc->lock); + switch (memType) + { +#if defined(DVP_USE_TILER) + case DVP_MTYPE_MPUCACHED_1DTILED: + case DVP_MTYPE_MPUNONCACHED_1DTILED: + case DVP_MTYPE_MPUNONCACHED_2DTILED: + case DVP_MTYPE_DISPLAY_2DTILED: + maptype = ProcMgr_MapType_Tiler; + break; +#endif + case DVP_MTYPE_MPUCACHED_VIRTUAL: + default: +#if defined(DVP_USE_TILER) +#if defined(__QNX__) + maptype = ProcMgr_MapType_Tiler; + memType = DVP_MTYPE_MPUCACHED_1DTILED; +#else + maptype = ProcMgr_MapType_Virt; +#endif +#endif + break; + } + + if (dvp_rpc_core_is_enabled(core)) + { +#if defined(DVP_USE_TILER) + if (memType == DVP_MTYPE_MPUCACHED_1DTILED) + { + DVP_PTR tilerAddr = NULL; + //DVP_PRINT(DVP_ZONE_MEM, "1D TILER CACHED XLate!\n"); + if (fph_get(rpc->mpu2tiler_hash, localAddr, &tilerAddr) == 0) + { + // not mapped already + DVP_Core_e newCore; + MemAllocBlock block; + memset(&block, 0, sizeof(block)); + + DVP_PRINT(DVP_ZONE_MEM, "1D TILER CACHED Mapping PTR:%p SIZE:%u\n",localAddr,localSize); + + // map to TILER, remember address + block.ptr = localAddr; + block.dim.len = localSize + (DVP_PAGE_SIZE - (localSize % DVP_PAGE_SIZE)); + block.stride = 0; + block.pixelFormat = PIXEL_FMT_PAGE; /// @todo Revert this to the proper format as in the dvp_mem.c + DVP_PRINT(DVP_ZONE_MEM, "1D TILER PTR:%p LEN:%u STR:%u FMT:%d\n", + block.ptr, block.dim.len, + block.stride, block.pixelFormat); + tilerAddr = MemMgr_Map(&block, 1); + if (tilerAddr != NULL) + { + DVP_PRINT(DVP_ZONE_MEM, "Mapped to TILER = {p=%p,l=%u,s=%u,f=%u}\n",block.ptr, block.dim.len,block.stride,block.pixelFormat); + DVP_PRINT(DVP_ZONE_MEM, "LVA %p => TVA %p (SSPTR %p)\n",localAddr, tilerAddr, (DVP_PTR)block.reserved); + fph_set(rpc->mpu2tiler_hash, localAddr, tilerAddr); + // @TOOD Unwind mechanics for TILER mapping + fph_set(rpc->tiler2mpu_hash, tilerAddr, localAddr); + // map the TILER addr to each RPU, remember addresses + DVP_FOR_EACH_CORE(newCore) + { + DVP_S32 status = 0; + DVP_U32 addr; + + SyslinkMemUtils_MpuAddrToMap mpuVirtAddr; + + mpuVirtAddr.mpuAddr = (UInt32)tilerAddr; + mpuVirtAddr.size = localSize; + + status = SysLinkMemUtils_map(&mpuVirtAddr, + 1, + &addr, + maptype, + newCore); + if (status >= 0) + { + DVP_PRINT(DVP_ZONE_MEM, "TVA %p => RVA[%u] %p\n",tilerAddr, newCore, (DVP_PTR)addr); + // remember the remote address + if (fph_set(rpc->tiler2rpu_hash[newCore], tilerAddr, (ptr_t)addr)) + { + if (core == newCore) + remoteAddr = (DVP_PTR)addr; + + if (fph_set(rpc->rpu2tiler_hash[newCore], (ptr_t)addr, tilerAddr) == 0) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Failed to remember RVA %p to TVA %p in Hash!\n", remoteAddr, tilerAddr); + unwind = DVP_TRUE; + } + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Failed to remember TVA %p to RVA %p in Hash!\n", tilerAddr, remoteAddr); + unwind = DVP_TRUE; + } + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Failed to map LVA %p => TVA %p to RVA!\n", localAddr, tilerAddr); + unwind = DVP_TRUE; + } + } + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Failed to map 1D CACHED %p to TILER!\n", localAddr); + unwind = DVP_TRUE; + } + + } + else + { + DVP_PRINT(DVP_ZONE_RPC, "Found LVA:%p => TVA:%p in hash!\n", localAddr, tilerAddr); + + // found it in the MPU->TILER so we've mapped it already. + if (DVP_VALID_REMOTE_CORE(core) && dvp_rpc_core_is_enabled(core)) + { + // now look it up in the TILER->RPU and return that + if (fph_get(rpc->tiler2rpu_hash[core], tilerAddr, &remoteAddr) == 0) + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Failed to find TVA: %p in TILER to REMOTE CORE:%d hash!\n", tilerAddr, core); + } + else + { + DVP_PRINT(DVP_ZONE_RPC, "Found TVA:%p => RVA:%p in hash!\n", tilerAddr, remoteAddr); + } + } + + if (core == DVP_CORE_CPU) + { + // the tiler addr is the remote addr` + remoteAddr = tilerAddr; + } + } + } + else // 1d,2d uncached, virtual + { + DVP_Core_e mapCore = core; + if (core == DVP_CORE_CPU) + { + // we're using the DVP_CORE_CPU as a way to prime the hashes with + // pre-translated values... change to the first enabled remote + // core + mapCore = dvp_rpc_next_core(DVP_CORE_MIN); + + // there will be no translation, so just return the local pointer. + remoteAddr = localAddr; + } + + if (DVP_VALID_REMOTE_CORE(mapCore) && dvp_rpc_core_is_enabled(mapCore)) + { + if (fph_get(rpc->mpu2rpu_hash[mapCore], localAddr, &remoteAddr) == 0) + { + DVP_U32 addr; + DVP_Core_e newCore; + DVP_FOR_EACH_CORE(newCore) + { + DVP_S32 status = 0; + addr = 0; + SyslinkMemUtils_MpuAddrToMap mpuVirtAddr; + + DVP_PRINT(DVP_ZONE_MEM, "Mapping PTR:%p SIZE:%d CORE:%d\n", localAddr, localSize, newCore); + + mpuVirtAddr.mpuAddr = (UInt32)localAddr; + mpuVirtAddr.size = localSize; + + status = SysLinkMemUtils_map(&mpuVirtAddr, + 1, + &addr, + maptype, + newCore); + if (addr != 0) + { + // install the pointer in the forward hash + if (fph_set(rpc->mpu2rpu_hash[newCore], localAddr, (ptr_t)addr)) + { + // success! now remember the address if this is core + // we're interested in + if (core == newCore) + remoteAddr = (DVP_PTR)addr; + + // install the pointer in the backward hash + if (fph_set(rpc->rpu2mpu_hash[newCore], (ptr_t)addr, localAddr)) + { + // success! the pointer is in both hashes. + DVP_PRINT(DVP_ZONE_MEM, "LVA %p => RVA[%u] %p\n", localAddr, newCore, (DVP_PTR)addr); + } + else // failed to remeber the backward translation + { + DVP_PRINT(DVP_ZONE_WARNING, "WARNING! Address %p was not remembered in the Backward Fast Pointer Hash\n", (DVP_PTR)addr); + // we must unwind previous mapping + unwind = DVP_TRUE; + } + } + else // failed to remember the forward translation + { + DVP_PRINT(DVP_ZONE_WARNING, "WARNING! Address %p was not remembered in the Foward Fast Pointer Hash!\n", localAddr); + // we must unwind previous mapping + unwind = DVP_TRUE; + } + } + else // failed to map + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR! Failed to map local address %p to core %u (id:%d) (Status=%08x)\n", localAddr, newCore, dvp_rpc_getid(mapCore), status); + // we must unwind previous mapping + unwind = DVP_TRUE; + } + } + } + else + { + DVP_PRINT(DVP_ZONE_MEM, "Found LVA:%p => RVA:%p in hash!\n", localAddr, remoteAddr); + } + } + else + { + DVP_PRINT(DVP_ZONE_WARNING, "No remote cores are enabled. No hash priming was done. Not an error.\n"); + } + } +#endif // TILER enabled + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: INVALID CORE %d\n", core); + } + if (unwind == DVP_TRUE) + { + dvp_rpc_mem_remove(rpc, localAddr, localSize, memType); + remoteAddr = NULL; + } + mutex_unlock(&rpc->lock); + return remoteAddr; +} + +DVP_PTR dvp_rpc_mem_xlate_back(DVP_RPC_t *rpc, DVP_Core_e core, DVP_PTR remoteAddr, DVP_MemType_e memType) +{ + DVP_PTR localAddr = NULL; + mutex_lock(&rpc->lock); + if (DVP_VALID_REMOTE_CORE(core) && dvp_rpc_core_is_enabled(core)) + { +#if defined(DVP_USE_TILER) +#if defined(__QNX__) + if(memType == DVP_MTYPE_MPUCACHED_VIRTUAL) + memType = DVP_MTYPE_MPUCACHED_1DTILED; +#endif + if (memType == DVP_MTYPE_MPUCACHED_1DTILED) + { + DVP_PTR tilerAddr; + fph_get(rpc->rpu2tiler_hash[core], remoteAddr, &tilerAddr); + DVP_PRINT(DVP_ZONE_MEM, "TVA %p <= RVA[%u] %p\n", tilerAddr, core, remoteAddr); + fph_get(rpc->tiler2mpu_hash, tilerAddr, &localAddr); + DVP_PRINT(DVP_ZONE_MEM, "LVA %p <= TVA %p\n", localAddr, tilerAddr); + } + else +#endif + { + fph_get(rpc->rpu2mpu_hash[core], remoteAddr, &localAddr); + DVP_PRINT(DVP_ZONE_MEM, "LVA %p <= RVA[%u] %p\n", localAddr, core, remoteAddr); + } + } + mutex_unlock(&rpc->lock); + return localAddr; +} + + +DVP_BOOL dvp_rpc_flush(DVP_RPC_t *rpc, DVP_Core_e core, DVP_PTR address, DVP_U32 size, DVP_MemType_e mtype) +{ + DVP_BOOL ret = DVP_FALSE; + if (rpc) + { + DVP_PRINT(DVP_ZONE_RPC, "Flushing address:%p for %u bytes type:%d core:%d\n", address, size, mtype, core); + if ((DVP_VALID_REMOTE_CORE(core) && dvp_rpc_core_is_enabled(core)) || core == DVP_CORE_CPU) + { + Int status = 0; + DVP_PRINT(DVP_ZONE_RPC, "FLUSH CORE:%d PTR:%p SIZE:%u\n", core, address, size); + status = ProcMgr_flushMemory(address, size, dvp_rpc_getid(core)); + if (status < 0) { + DVP_PRINT(DVP_ZONE_ERROR, "DVP RPC: Failed to flush address %p on core %d\n", address, core); + } + else + ret = DVP_TRUE; + } + } + return ret; +} + +DVP_BOOL dvp_rpc_invalidate(DVP_RPC_t *rpc, DVP_Core_e core, DVP_PTR address, DVP_U32 size, DVP_MemType_e mtype) +{ + DVP_BOOL ret = DVP_FALSE; + if (rpc) + { + DVP_PRINT(DVP_ZONE_RPC, "Invalidating address:%p for %u bytes type:%d core:%d\n", address, size, mtype, core); + if ((DVP_VALID_REMOTE_CORE(core) && dvp_rpc_core_is_enabled(core)) || core == DVP_CORE_CPU) + { + Int status = 0; + DVP_PRINT(DVP_ZONE_RPC, "INVALIDATE CORE:%d PTR:%p SIZE:%u\n", core, address, size); + status = ProcMgr_invalidateMemory(address, size, dvp_rpc_getid(core)); + if (status < 0) { + DVP_PRINT(DVP_ZONE_ERROR, "DVP RPC: Failed to invalidate address %p on core %d\n", address, core); + } + else + ret = DVP_TRUE; + } + } + return ret; +} + +void dvp_rpc_prepare_image(DVP_RPC_t *rpc, DVP_Core_e core, DVP_Image_t *pImage, DVP_BOOL cacheOp, DVP_PTR base, DVP_RPC_Translation_t *trans) +{ + DVP_U32 p = 0; + DVP_BOOL cached = DVP_TRUE; + + // Remove warnings + base = base; + trans = trans; + +#if defined(DVP_USE_TILER) + if (pImage->memType == DVP_MTYPE_DISPLAY_2DTILED) + cached = DVP_FALSE; +#endif +#if defined(DVP_USE_TILER) + if (pImage->memType == DVP_MTYPE_MPUNONCACHED_1DTILED || + pImage->memType == DVP_MTYPE_MPUNONCACHED_2DTILED) + cached = DVP_FALSE; +#endif + + for (p = 0; p < pImage->planes; p++) + { + DVP_U32 planeSize = DVP_Image_PlaneSize(pImage, p); + if (cached && cacheOp && !pImage->skipCacheOpFlush) { + DVP_COMPLAIN_IF_FALSE(dvp_rpc_flush(rpc, core, pImage->pBuffer[p], planeSize, pImage->memType)); + } + // @NOTE could the output buffers be accidently written back from the cache during operations? + pImage->pBuffer[p] = dvp_rpc_mem_xlate_fwrd(rpc, core, pImage->pBuffer[p], planeSize, pImage->memType); + // recalculate the new pData based on the starts and strides + pImage->pData[p] = &pImage->pBuffer[p][(pImage->y_start * pImage->y_stride)+(pImage->x_start * pImage->x_stride)]; + } +} + +void dvp_rpc_return_image(DVP_RPC_t *rpc, DVP_Core_e core, DVP_Image_t *pImage, DVP_BOOL cacheOp) +{ + DVP_BOOL cached = DVP_TRUE; + DVP_U32 p = 0; + + #if defined(DVP_USE_TILER) + if (pImage->memType == DVP_MTYPE_DISPLAY_2DTILED) + cached = DVP_FALSE; +#endif +#if defined(DVP_USE_TILER) + if (pImage->memType == DVP_MTYPE_MPUNONCACHED_1DTILED || + pImage->memType == DVP_MTYPE_MPUNONCACHED_2DTILED) + cached = DVP_FALSE; +#endif + for (p = 0; p < pImage->planes; p++) + { + DVP_U32 planeSize = DVP_Image_PlaneSize(pImage, p); + pImage->pBuffer[p] = dvp_rpc_mem_xlate_back(rpc, core, pImage->pBuffer[p], pImage->memType); + if (cached && cacheOp && !pImage->skipCacheOpInval) { + DVP_COMPLAIN_IF_FALSE(dvp_rpc_invalidate(rpc, core, (DVP_PTR)pImage->pBuffer[p], planeSize, pImage->memType)); + } + // recalculate the pData pointer + pImage->pData[p] = &pImage->pBuffer[p][(pImage->y_start * pImage->y_stride) + (pImage->x_start * pImage->x_stride)]; + } +} + +void dvp_rpc_prepare_buffer(DVP_RPC_t *rpc, DVP_Core_e core, DVP_Buffer_t *pBuffer, DVP_BOOL cacheOp, DVP_PTR base, DVP_RPC_Translation_t *trans) +{ + DVP_BOOL cached = DVP_TRUE; + + // Remove warnings + base = base; + trans = trans; + +#if defined(DVP_USE_TILER) + if (pBuffer->memType == DVP_MTYPE_MPUNONCACHED_1DTILED) + cached = DVP_FALSE; +#endif + if (cached && cacheOp && !pBuffer->skipCacheOpFlush) { + DVP_COMPLAIN_IF_FALSE(dvp_rpc_flush(rpc, core, pBuffer->pData, pBuffer->numBytes, pBuffer->memType)); + } + // @NOTE could the output buffers be accidently written back from the cache during operations? + pBuffer->pData = dvp_rpc_mem_xlate_fwrd(rpc, core, pBuffer->pData, pBuffer->numBytes, pBuffer->memType); +} + +void dvp_rpc_return_buffer(DVP_RPC_t *rpc, DVP_Core_e core, DVP_Buffer_t *pBuffer, DVP_BOOL cacheOp) +{ + DVP_BOOL cached = DVP_TRUE; +#if defined(DVP_USE_TILER) + if (pBuffer->memType == DVP_MTYPE_MPUNONCACHED_1DTILED) + cached = DVP_FALSE; +#endif + pBuffer->pData = dvp_rpc_mem_xlate_back(rpc, core, pBuffer->pData, pBuffer->memType); + if (cached && cacheOp && !pBuffer->skipCacheOpInval) { + DVP_COMPLAIN_IF_FALSE(dvp_rpc_invalidate(rpc, core, (DVP_PTR)pBuffer->pData, pBuffer->numBytes, pBuffer->memType)); + } +} + +DVP_VALUE dvp_rpc_get_handle(DVP_RPC_t *rpc, DVP_PTR ptr) +{ + return 0; +} + +DVP_BOOL dvp_rpc_dissociate(DVP_RPC_t *rpc, DVP_Mem_t *mem, DVP_PTR ptr, DVP_VALUE *pHandle, size_t size, DVP_MemType_e mtype) +{ + DVP_BOOL ret = DVP_TRUE; + + if (rpc == NULL || mem == NULL || ptr == NULL || size == 0) + return DVP_FALSE; + + switch (mtype) + { +#if defined(DVP_USE_TILER) + case DVP_MTYPE_MPUCACHED_1DTILED: + case DVP_MTYPE_MPUNONCACHED_1DTILED: + case DVP_MTYPE_MPUNONCACHED_2DTILED: + case DVP_MTYPE_DISPLAY_2DTILED: +#endif + case DVP_MTYPE_MPUCACHED_VIRTUAL: + default: + dvp_rpc_mem_remove(rpc, ptr, size, mtype); + break; + } + if (ret == DVP_TRUE) { + DVP_PRINT(DVP_ZONE_RPC, "Dissociated %p of "FMT_SIZE_T" bytes (hdl: "FMT_VALUE_T")\n", ptr, size, *pHandle); + } else { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to dissociate %p of "FMT_SIZE_T" bytes (hdl: "FMT_VALUE_T")\n", ptr, size, *pHandle); + } + return ret; +} + +DVP_BOOL dvp_rpc_associate(DVP_RPC_t *rpc, DVP_Mem_t *mem, DVP_PTR ptr, DVP_VALUE handle, size_t size, DVP_MemType_e mtype) +{ + DVP_BOOL ret = DVP_TRUE; + + if (rpc == NULL || mem == NULL || ptr == NULL || size == 0) + return DVP_FALSE; + + DVP_PRINT(DVP_ZONE_RPC, "Associating PTR:%p HDL:"FMT_VALUE_T" SIZE:%zu TYPE:%d\n", ptr, handle, size, mtype); + switch (mtype) + { +#if defined(DVP_USE_TILER) + case DVP_MTYPE_MPUCACHED_1DTILED: + case DVP_MTYPE_MPUNONCACHED_1DTILED: + case DVP_MTYPE_MPUNONCACHED_2DTILED: + case DVP_MTYPE_DISPLAY_2DTILED: +#endif + case DVP_MTYPE_MPUCACHED_VIRTUAL: + default: + dvp_rpc_mem_xlate_fwrd(rpc, DVP_CORE_CPU, ptr, size, mtype); + break; + } + return ret; +} + +void dvp_rpc_deinit(DVP_RPC_t **rpc) +{ + if (rpc && *rpc) + { + Int status; + DVP_Core_e core = 0; + DVP_FOR_EACH_CORE(core) + { + fph_deinit((*rpc)->mpu2rpu_hash[core]); + fph_deinit((*rpc)->rpu2mpu_hash[core]); +#if defined(DVP_USE_TILER) + fph_deinit((*rpc)->tiler2rpu_hash[core]); + fph_deinit((*rpc)->rpu2tiler_hash[core]); +#endif + RCM_COMPLAIN_IF_FAILED(status, ProcMgr_detach((*rpc)->procs[core].handle)); + RCM_COMPLAIN_IF_FAILED(status, ProcMgr_close(&(*rpc)->procs[core].handle)); + } +#if defined(DVP_USE_TILER) + fph_deinit((*rpc)->tiler2mpu_hash); + fph_deinit((*rpc)->mpu2tiler_hash); +#endif + RCM_COMPLAIN_IF_FAILED(status, Ipc_destroy()); + mutex_deinit(&(*rpc)->lock); + free(*rpc); + *rpc = NULL; + } +} + + +DVP_RPC_t *dvp_rpc_init() +{ + DVP_RPC_t *rpc = (DVP_RPC_t *)calloc(1,sizeof(DVP_RPC_t)); + if (rpc) + { + DVP_Core_e core = 0; + Int status = 0; + Ipc_getConfig(&rpc->config); + status = Ipc_setup(&rpc->config); + if (status < 0) + { + uint32_t c; + DVP_PRINT(DVP_ZONE_ERROR, "Failed to initialize IPC mechanism, no RPC possible\n"); + // disable all cores + for (c = 0; c < dimof(dvp_core_names); c++) + dvp_core_names[c].enabled = false_e; + free(rpc); + rpc = NULL; + } + else + { + mutex_init(&rpc->lock); +#if defined(DVP_USE_TILER) + rpc->mpu2tiler_hash = fph_init(DVP_RPC_NUM_BLOCKS, DVP_RPC_BLOCK_SIZE, NULL); + rpc->tiler2mpu_hash = fph_init(DVP_RPC_NUM_BLOCKS, DVP_RPC_BLOCK_SIZE, NULL); +#endif + DVP_FOR_EACH_CORE(core) + { + DVP_PRINT(DVP_ZONE_RPC, "Core [%u] = %s\n", core, rpc->config.multiProcConfig.nameList[core]); + rpc->procs[core].id = MultiProc_getId(dvp_core_names[core].name); + status = ProcMgr_open(&rpc->procs[core].handle, rpc->procs[core].id); + if (status > 0) + { + ProcMgr_getAttachParams(rpc->procs[core].handle, &rpc->procs[core].params); + status = ProcMgr_attach(rpc->procs[core].handle, &rpc->procs[core].params); + if (status < 0) + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to attach to Core[%u] %s, disabling\n", core, rpc->config.multiProcConfig.nameList[core]); + dvp_core_names[core].enabled = false_e; + } + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "Failed to open Core[%u] %s, disabling\n", core, rpc->config.multiProcConfig.nameList[core]); + dvp_core_names[core].enabled = false_e; + } + if (dvp_core_names[core].enabled == true_e) + { + // we only allocate hashes for cores which are enabled. + rpc->mpu2rpu_hash[core] = fph_init(DVP_RPC_NUM_BLOCKS, DVP_RPC_BLOCK_SIZE, NULL); + rpc->rpu2mpu_hash[core] = fph_init(DVP_RPC_NUM_BLOCKS, DVP_RPC_BLOCK_SIZE, NULL); +#if defined(DVP_USE_TILER) + rpc->tiler2rpu_hash[core] = fph_init(DVP_RPC_NUM_BLOCKS, DVP_RPC_BLOCK_SIZE, NULL); + rpc->rpu2tiler_hash[core] = fph_init(DVP_RPC_NUM_BLOCKS, DVP_RPC_BLOCK_SIZE, NULL); +#endif + } + } // for each core + } + } + DVP_Perf_Clear(&rpc_perf); + return rpc; +} + +void dvp_rpc_core_deinit(DVP_RPC_t *rpc, DVP_RPC_Core_t **rpcc) +{ + if (rpc && rpcc && *rpcc) + { + DVP_Core_e core = (*rpcc)->coreEnum; + if (DVP_VALID_REMOTE_CORE(core) && dvp_rpc_core_is_enabled(core)) + { + dvp_core_names[core].enabled = false_e; + dvp_rpc_client_deinit(&(*rpcc)->client); + dvp_rpc_server_deinit(&(*rpcc)->server); + } + free(*rpcc); + *rpcc = NULL; + } +} + +void dvp_rpc_restart_callback_register(DVP_RPC_t *rpc, + DVP_RPC_Core_t *rpcc, + dvp_rpc_restart_f func, + void *cookie) +{ + if (rpc && rpcc && func) + { + rpcc->callback = (void *)func; + rpcc->cookie = cookie; + } +} + +DVP_RPC_Core_t *dvp_rpc_core_init(DVP_RPC_t *rpc, DVP_RPC_Interface_t *rpci) +{ + DVP_RPC_Core_t *rpcc = NULL; + int32_t status = 0; + + if (rpc == NULL || rpci == NULL) + return NULL; + + rpcc = (DVP_RPC_Core_t *)calloc(1,sizeof(DVP_RPC_Core_t)); + if (rpcc) + { + DVP_Core_e core = rpci->coreEnum; + rpcc->coreEnum = core; + if (DVP_VALID_REMOTE_CORE(core) && dvp_rpc_core_is_enabled(core)) + { + DVP_PRINT(DVP_ZONE_RPC, "DVP_RPC: Interfacing to CORE:%d\n",core); + // register the RcmServer + strncpy(rpcc->server.name, dvp_core_names[core].server_name, DVP_MAX_SERVER_NAME); + rpcc->server.calls = rpci->localFunctions; + rpcc->server.numCalls = rpci->numLocalFunctions; + RCM_GOTO_IF_FAILED(status, dvp_rpc_server_init(&rpcc->server), leave); + + // register the RcmClient + strncpy(rpcc->client.name, dvp_core_names[core].client_name, DVP_MAX_SERVER_NAME); + rpcc->client.calls = rpci->remoteFunctions; + rpcc->client.numCalls = rpci->numRemoteFunctions; + RCM_GOTO_IF_FAILED(status, dvp_rpc_client_init(&rpcc->client), leave); + if (status < 0) + goto leave; + DVP_PRINT(DVP_ZONE_RPC, "Successfully installed DVP RPC for CORE %d!\n",core); + } + else + { + status = -1; // not a valid core + } + } +leave: + if (status < 0) // if ANY failure! + { + dvp_rpc_core_deinit(rpc, &rpcc); + } + return rpcc; +} + +int dvp_rpc_remote_execute(DVP_RPC_t *rpc, DVP_RPC_Core_t *rpcc, int cliIndex, DVP_RPC_Parameter_t *params, DVP_U32 numParams, DVP_RPC_Translation_t *trans) +{ + int ret = 0; + + if (rpc == NULL || rpcc == NULL) + return 0; + + // trans can be NULL if there is nothing to translate + // remove warnings + trans = trans; + + RcmClient_Message *pPacket = NULL; + RcmClient_Message *pResponse = NULL; + Int status = 0; + DVP_U32 msgSize = 0; + UInt8 *pMsg = NULL; + DVP_U32 i = 0; + + // calculate the message size + for (i = 0; i < numParams; i++) + msgSize += params[i].size; + + DVP_PRINT(DVP_ZONE_RPC, "RPC: Sending %u pararms, %u bytes\n", numParams, msgSize); + + // allocate the packet + status = RcmClient_alloc(rpcc->client.handle, msgSize, &pPacket); + if (status >= 0) + { + // set the packet values + pPacket->fxnIdx = rpcc->client.calls[cliIndex].index; + + // assign the msg pointer + pMsg = (UInt8 *)&pPacket->data[0]; + + // marshall the parameters + for (i = 0; i < numParams; i++) + { + if (params[i].type == DVP_RPC_READ_ONLY || + params[i].type == DVP_RPC_READ_AND_WRITE) + { + memcpy(pMsg, params[i].data, params[i].size); + pMsg += params[i].size; + } + } + + DVP_PRINT(DVP_ZONE_RPC, "DVP_RPC: Calling %s::%s[%u] with %u params\n", rpcc->client.name, rpcc->client.calls[cliIndex].name, rpcc->client.calls[cliIndex].index, numParams); + for (i = 0; i < numParams; i++) + { + DVP_PRINT(DVP_ZONE_RPC, "DVP_RPC:\t[%u] TYPE:%04x SIZE:%u PTR:%p DATA:0x%x\n", i, params[i].type, params[i].size, params[i].data, *(DVP_U32 *)params[i].data); + } + +#if (DVP_DEBUG == 1) + // flush out the PRINTF's before we may crash the system + fflush(stdout); +#endif + + // call the remote function! + status = RcmClient_exec(rpcc->client.handle, pPacket, &pResponse); + DVP_PRINT(DVP_ZONE_RPC, "RcmClient_exec returned 0x%08x (result = 0x%08x)\n", status, pPacket->result); + if (status >= 0) + { + // if successful, reset the pMsg to the response packet + pMsg = (UInt8 *)&pResponse->data[0]; + + for (i = 0; i < numParams; i++) + { + if (params[i].type == DVP_RPC_WRITE_ONLY || + params[i].type == DVP_RPC_READ_AND_WRITE) + { + DVP_PRINT(DVP_ZONE_RPC, "Write back %p => %p for %u bytes\n", pMsg, params[i].data, params[i].size); + memcpy(params[i].data, pMsg, params[i].size); + switch (params[i].size) + { + case 1: + { + UInt8 *pData = (UInt8 *)params[i].data; + DVP_PRINT(DVP_ZONE_RPC, "\t[%u] = 0x%02x\n", i, *pData); + break; + } + case 2: + { + UInt16 *pData = (UInt16 *)params[i].data; + DVP_PRINT(DVP_ZONE_RPC, "\t[%u] = 0x%04x\n", i, *pData); + break; + } + case 4: + { + DVP_U32 *pData = (DVP_U32 *)params[i].data; + DVP_PRINT(DVP_ZONE_RPC, "\t[%u] = 0x%08x\n", i, *pData); + break; + } + default: + { + UInt8 *pData = (UInt8 *)params[i].data; + DVP_U32 j = params[i].size; + DVP_PRINT(DVP_ZONE_RPC, "\t[%u] = ",i); + for (j = 0; j < params[i].size; j++) { + DVP_PRINT(DVP_ZONE_RPC, " 0x%02x", *pData); + } + DVP_PRINT(DVP_ZONE_RPC, "\n"); + break; + } + } + pMsg += params[i].size; + } + } + // remember the remote result! + status = pPacket->result; + RcmClient_free(rpcc->client.handle, pResponse); + pResponse = NULL; + + DVP_PRINT(DVP_ZONE_RPC, "Remote Call Successful! (Ret=0x%08x:%d)\n", status, status); + } + else + { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: RPC Failed to call remote function!\n"); + RcmClient_free(rpcc->client.handle, pPacket); + } + pPacket = NULL; + } + return status; +} + +#endif + +//****************************************************************************** +// END +//****************************************************************************** diff --git a/source/dvp/dvp_kgraph/dvp_rpc_stub.c b/source/dvp/dvp_kgraph/dvp_rpc_stub.c new file mode 100644 index 0000000..e15324a --- /dev/null +++ b/source/dvp/dvp_kgraph/dvp_rpc_stub.c @@ -0,0 +1,212 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(DVP_USE_IPC) + +//****************************************************************************** +// INCLUDES +//****************************************************************************** + +#include + +#include +#include +// @NOTE we include dvp_rpc.h further down in the file... + +//****************************************************************************** +// #DEFINES +//****************************************************************************** + +//****************************************************************************** +// TYPEDEFS +//****************************************************************************** + +typedef struct _dvp_rpc_core_t DVP_RPC_Core_t; + +typedef struct _dvp_rpc_t { + DVP_Handle handle; /** This contains the pointer back the DVP_t. It MUST be the FIRST entry in the structure! */ + mutex_t lock; + DVP_RPC_Core_t *cores[DVP_CORE_MAX]; +} DVP_RPC_t; + +struct _dvp_rpc_core_t { + DVP_S32 coreEnum; + void *callback; // will be later cast the proper type + void *cookie; +}; + +#define DVP_RPC_T // we're defining the RPC structure locally! +#include + +//****************************************************************************** +// LOCAL VARIABLES +//****************************************************************************** + + +//****************************************************************************** +// LOCAL FUNCTIONS +//****************************************************************************** + +DVP_RPC_t *dvp_rpc_init() +{ + return (DVP_RPC_t *)calloc(1, sizeof(DVP_RPC_t)); +} + +void dvp_rpc_deinit(DVP_RPC_t **rpc) +{ + free(*rpc); + *rpc = NULL; +} + +void dvp_rpc_restart_callback_register(DVP_RPC_t *rpc, + DVP_RPC_Core_t *rpcc, + dvp_rpc_restart_f func, + void *cookie) +{ + ; // do nothing +} + +DVP_PTR dvp_rpc_mem_xlate_fwrd(DVP_RPC_t *rpc, + DVP_Core_e core, + DVP_PTR localAddr, + DVP_U32 localSize, + DVP_MemType_e memType) +{ + return NULL; +} + +DVP_PTR dvp_rpc_mem_xlate_back(DVP_RPC_t *rpc, + DVP_Core_e core, + DVP_PTR remoteAddr, + DVP_MemType_e memType) +{ + return NULL; +} + +void dvp_rpc_mem_remove(DVP_RPC_t *rpc, + DVP_PTR localAddr, + DVP_U32 localSize, + DVP_MemType_e memType) +{ + ; // do nothing +} + +DVP_RPC_Core_t *dvp_rpc_core_init(DVP_RPC_t *rpc, DVP_RPC_Interface_t *rpci) +{ + return (DVP_RPC_Core_t *)calloc(1, sizeof(DVP_RPC_Core_t)); +} + +void dvp_rpc_core_deinit(DVP_RPC_t *rpc, DVP_RPC_Core_t **rpcc) +{ + free(*rpcc); + *rpcc = NULL; +} + +DVP_BOOL dvp_rpc_dissociate(DVP_RPC_t *rpc, + DVP_Mem_t *mem, + DVP_PTR ptr, + DVP_VALUE *pHandle, + size_t size, + DVP_MemType_e mtype) +{ + return DVP_FALSE; +} + +DVP_BOOL dvp_rpc_associate(DVP_RPC_t *rpc, + DVP_Mem_t *mem, + DVP_PTR ptr, + DVP_VALUE handle, + size_t size, + DVP_MemType_e mtype) +{ + return DVP_FALSE; +} + +DVP_VALUE dvp_rpc_get_handle(DVP_RPC_t *rpc, DVP_PTR ptr) +{ + return 0; +} + +int dvp_rpc_remote_execute(DVP_RPC_t *rpc, + DVP_RPC_Core_t *rpcc, + int cliIndex, + DVP_RPC_Parameter_t *params, + DVP_U32 numParams, + DVP_RPC_Translation_t *trans) +{ + return 0; +} + +DVP_BOOL dvp_rpc_invalidate(DVP_RPC_t *rpc, + DVP_Core_e core, + DVP_PTR address, + DVP_U32 size, + DVP_MemType_e mtype) +{ + return DVP_FALSE; +} + +DVP_BOOL dvp_rpc_flush(DVP_RPC_t *rpc, + DVP_Core_e core, + DVP_PTR address, + DVP_U32 size, + DVP_MemType_e mtype) +{ + return DVP_FALSE; +} + +void dvp_rpc_prepare_image(DVP_RPC_t *rpc, + DVP_Core_e core, + DVP_Image_t *pImage, + DVP_BOOL cacheOp, + DVP_PTR base, + DVP_RPC_Translation_t *trans) +{ + ; // do nothing +} + +void dvp_rpc_return_image(DVP_RPC_t *rpc, + DVP_Core_e core, + DVP_Image_t *pImage, + DVP_BOOL cacheOp) +{ + ; // do nothing +} + +void dvp_rpc_prepare_buffer(DVP_RPC_t *rpc, + DVP_Core_e core, + DVP_Buffer_t *pBuffer, + DVP_BOOL cacheOp, + DVP_PTR base, + DVP_RPC_Translation_t *trans) +{ + ; // do nothing +} + +void dvp_rpc_return_buffer(DVP_RPC_t *rpc, + DVP_Core_e core, + DVP_Buffer_t *pBuffer, + DVP_BOOL cacheOp) +{ + ; // do nothing +} + +#endif + +//****************************************************************************** +// END +//****************************************************************************** + diff --git a/source/dvp/dvp_kgraph/include/dvp_kgb.h b/source/dvp/dvp_kgraph/include/dvp_kgb.h new file mode 100644 index 0000000..6d7e548 --- /dev/null +++ b/source/dvp/dvp_kgraph/include/dvp_kgb.h @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief The DVP Kernel Graph Boss. + * \defgroup group_dvp_kgb DVP Kernel Graph Boss API. + * \brief The API related the Kernel Graph Boss. + */ + +#ifndef _DVP_KGB_H_ +#define _DVP_KGB_H_ + +// external +#include +#include + +// internal +#include +#include +#include + +#if defined(DVP_USE_ION) +#include +#if defined(ANDROID) +#include +#endif +#endif + +#ifdef DVP_USE_GRALLOC +#include +#endif + +/*! \brief The magic number used to determine if the load table has been initialized. + * \ingroup group_dvp_kgb + */ +#define DVP_LOAD_TABLE_NAME (0xDEADFACE) + +/*! \brief The flag to indicate the the KGMs should be initialized. + * \ingroup group_dvp_kgb + */ +#define DVP_KGB_INIT_KGMS (1 << 0) + +/*! \brief The flags to indicate that the Memory system should be initialized. + * \ingroup group_dvp_kgb + */ +#define DVP_KGB_INIT_MEM_MGR (1 << 1) + +/*! \brief The set of all flags. + * \ingroup group_dvp_kgb + */ +#define DVP_KGB_INIT_ALL (DVP_KGB_INIT_KGMS | DVP_KGB_INIT_MEM_MGR) + +/*! \brief The core load structure. + * \ingroup group_dvp_kgb + */ +typedef struct _dvp_core_load_t { + DVP_S32 maximumLoad; + DVP_S32 currentLoad; +} DVP_Core_Load_t; + +/*! \brief The system load structure. + * \ingroup group_dvp_kgb + */ +typedef struct _dvp_load_t { + bool_e initialized; + semaphore_t sem; + DVP_Core_Load_t cores[DVP_CORE_MAX]; +} DVP_Load_t; + +/*! \brief The DVP Kernel Graph Lock. + * \ingroup group_dvp_kgb + */ +typedef struct _dvp_graph_lock_t { + bool_e m_enabled; + mutex_t m_lock; + event_t m_wait; + uint32_t m_count; +} DVP_GraphLock_t; + +/*! \brief The internal top level context structure for DVP. + * \ingroup group_dvp_kgb + */ +typedef struct _dvp_t { + DVP_GraphManager_t *managers; + DVP_U32 numMgrs; + mutex_t mgrLock; + shared_t *shared_memory; + DVP_Load_t *loads; + DVP_RPC_t *rpc; + DVP_Mem_t *mem; + DVP_GraphLock_t graphLock; +} DVP_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \brief This function initializes the graph boss. + * \return DVP_t * + * \ingroup group_dvp_kgb + */ +DVP_t *DVP_KernelGraphBossInit(); + +/*! + * \brief This function deinitializes the graph boss. + * \param dvp The pointer to the DVP_t context. + * \ingroup group_dvp_kgb + */ +void DVP_KernelGraphBossDeinit(DVP_t *dvp); + +/*! + * \brief This function process a single section of the graph in either a synchronous or asychronous mode. + * \param dvp + * \param section + * \param sync + * \ingroup group_dvp_kgb + */ +DVP_U32 DVP_KernelGraphBoss(DVP_t *dvp, DVP_KernelGraphSection_t *section, DVP_BOOL sync); + +/*! + * \brief This function allows the caller to limit max load of a requested core in the shared load table. + * \param dvp + * \param core + * \param limit + * \ingroup group_dvp_kgb + */ +void DVP_SetMaxLoad(DVP_t *dvp, DVP_Core_e core, DVP_U32 limit); + +/** + * This function allows the caller to retrieve the max load of the requested core from the shared load table. + * \param dvp The handle to the dvp instance. + * \param core The core being queried. + * \param pMaxLoad The maximum load reported from the manager. + * \ingroup group_dvp_kgb + */ +DVP_U32 DVP_GetMaxLoad(DVP_t *dvp, DVP_Core_e core, DVP_U32 *pMaxLoad); + +/** + * \brief Queries an individual core in DVP. + * \param dvp The pointer to the DVP_t context. + * \param core The core to query. + * \param info A pointer to a preallocated structure which will contain the core + * info. + * \ingroup group_dvp_kgb + */ +void DVP_QueryCore(DVP_t *dvp, DVP_Core_e core, DVP_CoreInfo_t *info); + +/*! + * \brief Queries the boss to determine if the specified core supports this kernel. + * \param dvp The pointer to the DVP_t context. + * \param kernel The kenel enum to search for. + * \param core The core to search. + * \retval DVP_TRUE The core supports the kernel + * \retval DVP_FALSE The core does not support the kernel. + * \ingroup group_dvp_kgb + */ +DVP_BOOL DVP_QueryCoreForKernel(DVP_t *dvp, DVP_KernelNode_e kernel, DVP_Core_e core); + +/*! This function initializes the memory system. + * \ingroup group_dvp_kgb + */ +DVP_Mem_t *dvp_mem_init(); + +/*! This function disables the memory system. + * \ingroup group_dvp_kgb + */ +void dvp_mem_deinit(DVP_Mem_t **pmem); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/source/dvp/dvp_kgraph/include/dvp_kgm.h b/source/dvp/dvp_kgraph/include/dvp_kgm.h new file mode 100644 index 0000000..bb18696 --- /dev/null +++ b/source/dvp/dvp_kgraph/include/dvp_kgm.h @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _DVP_KGM_H_ +#define _DVP_KGM_H_ + +/*! + * \file + * \brief An internal header file which defines the DVP Kernel Graph Manager interface. + * \author Erik Rainey + * \defgroup group_dvp_kgm DVP Kernel Graph Manager API + */ + +#include + +// external +#include +// internal +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*! \brief The function pointer to the KGM initialization function + * \ingroup group_dvp_kgm + */ +typedef DVP_BOOL (*DVP_GraphManagerInit_f)(DVP_RPC_t *rpc, DVP_RPC_Core_t *pCore); + +/*! The function pointer to the KGM deinitialization function + * \ingroup group_dvp_kgm + */ +typedef DVP_BOOL (*DVP_GraphManagerDeinit_f)(void); + +/*! \brief This function pointer is called when the remote endpoint unexpectedly restarts. + * \ingroup group_dvp_kgm + */ +typedef void (*DVP_GraphManagerRestart_f)(void *arg); + +/*! \brief The function pointer to the function which processes the subarray of kernel nodes. + * \ingroup group_dvp_kgm + */ +typedef DVP_U32 (*DVP_GraphManager_f)(DVP_KernelNode_t *pSubNodes, DVP_U32 startNode, DVP_U32 numNodes, DVP_BOOL sync); + +/*! \brief The function pointer to the function which returns the pointer the list of support kernels. + * \ingroup group_dvp_kgm + */ +typedef DVP_U32 (*DVP_GetSupportedKernels_f)(DVP_CoreFunction_t **pFuncs); + +/*! \brief The function pointer to the function which returns the list of remote functions that the local cores will call. + * \ingroup group_dvp_kgm + */ +typedef DVP_U32 (*DVP_GetSupportedRemoteCalls_f)(DVP_Function_t **pRemote, DVP_U32 *pNum); + +/*! \brief The function pointer to the function which returns the list of local functions that remote cores and call + * \ingroup group_dvp_kgm + */ +typedef DVP_U32 (*DVP_GetSupportedLocalCalls_f)(DVP_Function_t **pLocal, DVP_U32 *pNum); + +/*! \brief The function pointer to the function which returns the enumeration of the supported core that this object manages. + * \ingroup group_dvp_kgm + */ +typedef DVP_Core_e (*DVP_GetSupportedRemoteCore_f)(void); + +/*! \brief The function pointer to the function which returns the maximum load of the remote core + * \ingroup group_dvp_kgm + */ +typedef DVP_U32 (*DVP_GetMaximumLoad_f)(void); + +/*! + * \brief This is the interface structure to a DVP Kernel Graph Manager. + * \ingroup group_dvp_kgm + */ +typedef struct _dvp_graph_manager_funcs_t { + DVP_GraphManagerInit_f init; + DVP_GraphManager_f manager; + DVP_GetSupportedKernels_f getKernels; + DVP_GetSupportedLocalCalls_f getLocal; + DVP_GetSupportedRemoteCalls_f getRemote; + DVP_GetSupportedRemoteCore_f getCore; + DVP_GetMaximumLoad_f getLoad; + DVP_GraphManagerDeinit_f deinit; + DVP_GraphManagerRestart_f restart; +} DVP_GraphManager_Calls_t; + +/*! \brief This indicates that the manager's priority is invalid and will not be used. + * \ingroup group_dvp_kgm + */ +#define DVP_PRIORITY_NONE (0) + +/*! \brief This is used to move the priority from the higher to lower priority + * \ingroup group_dvp_kgm + */ +#define DVP_PRIORITY_INC (1) + +/*! \brief This indicates the highest priority + * \ingroup group_dvp_kgm + */ +#define DVP_PRIORITY_HIGHEST (1) + +/*! \brief This indicates the base priority for user supplied managers. + * \ingroup group_dvp_kgm + */ +#define DVP_PRIORITY_USER_BASE (1000) + +/*! \brief This indicates the lowest priority. + * \ingroup group_dvp_kgm + */ +#define DVP_PRIORITY_LOWEST (0xFFFFFFFE) + +/*! \brief This indicates the maximum value a priority field can logically have. + * \ingroup group_dvp_kgm + */ +#define DVP_PRIORITY_MAX (0xFFFFFFFF) + +/*! \brief The DVP Kernel Graph Manager data structure. + * \ingroup group_dvp_kgm + */ +typedef struct _dvp_graph_manager_t { + /*! \brief This indicates whether the manager is enabled or not. */ + bool_e enabled; + /*! \brief The short name of the kernel graph manager */ + char name[10]; + /*! \brief The file name of the loaded module */ + char dlname[MAX_PATH]; + /*! \brief The handle to the laoded module */ + module_t handle; + /*! \brief Function interface to the KGM. */ + DVP_GraphManager_Calls_t calls; + /*! \brief The pointer to the list of supported kernels by this manager */ + DVP_CoreFunction_t *kernels; + /*! \brief The number of supported kernels by this manager */ + DVP_U32 numSupportedKernels; + /*! \brief The poitner to the remote procedure call core data structure */ + DVP_RPC_Core_t *rpcc; + /*! \brief The pointer to the remote procedure call interface */ + DVP_RPC_Interface_t rpci; + /*! \brief The priority of the KGM. 0 is invalid, 1 is Highest, 2 is next highest, etc. See DVP_PRIORITY_XXX macros. */ + DVP_U32 priority; +} DVP_GraphManager_t; + +/*! \brief These are used as indexes into the Remote DVP KGM. + * \ingroup group_dvp_kgm + */ +typedef enum _dvp_kgm_function_e { + DVP_KGM_REMOTE_INIT = 0, /*!< \brief The index to the remote initialization function */ + DVP_KGM_REMOTE_DEINIT, /*!< \brief The index to the remote deinitialization function */ + DVP_KGM_REMOTE_EXEC, /*!< \brief The index to the remote execution function */ +} DVP_KGM_Remote_Function_e; + +/*!< \brief This is used internally to implement a per-core thread model. + * \ingroup group_dvp_kgm + */ +typedef struct _dvp_kgm_thread_t { + DVP_KernelNode_t *pSubNodes; /*!< \brief The pointer to the node array to execute */ + DVP_U32 startNode; /*!< \brief The index of the node in DVP_KGM_Thread_t::pSubNodes to start execution from */ + DVP_U32 numNodes; /*!< \brief The number of nodes to execute on DVP_KGM_Thread_t::pSubNodes starting at DVP_KGM_Thread_t::startNode */ + DVP_U32 numNodesExecuted; /*!< \brief The number of nodes actually executed. */ +} DVP_KGM_Thread_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/dvp/dvp_kgraph/include/dvp_kmdl.h b/source/dvp/dvp_kgraph/include/dvp_kmdl.h new file mode 100644 index 0000000..f732c43 --- /dev/null +++ b/source/dvp/dvp_kgraph/include/dvp_kmdl.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief The DVP Kernel Graph Manager Dynamic Loader. + * \defgroup group_dvp_kmdl DVP Kernel Graph Manager Dynamic Loader API. + */ + +#ifndef _DVP_KGMDL_H_ +#define _DVP_KGMDL_H_ + +#include + +/*! \brief This function loads a manager from the information inside the + * manager structure. + * \param [in] pManager The pointer the manager data structure. + * \ingroup group_dvp_kmdl + */ +DVP_U32 DVP_KernelGraphManagerLoad(DVP_GraphManager_t *pManager); + +/*! \brief This function unloads a manager from the information inside the + * manager structure. + * \param [in] pManager The pointer the manager data structure. + * \ingroup group_dvp_kmdl + */ +DVP_U32 DVP_KernelGraphManagerUnload(DVP_GraphManager_t *pManager); + +#endif diff --git a/source/dvp/dvp_kgraph/include/dvp_mem_int.h b/source/dvp/dvp_kgraph/include/dvp_mem_int.h new file mode 100644 index 0000000..c97949c --- /dev/null +++ b/source/dvp/dvp_kgraph/include/dvp_mem_int.h @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief The DVP Internal Memory API. + * \author Erik Rainey + * \defgroup group_dvp_mem DVP Internal Memory API. + */ + +#ifndef _DVP_MEM_INT_H_ +#define _DVP_MEM_INT_H_ + +#include +#include + +/*! \brief Recasting the SOSAL allocator type as a DVP_Mem_t. + * \ingroup group_dvp_mem + */ +typedef allocator_t DVP_Mem_t; + +/*! \brief Recasting the SOSAL allocator dimensionality type as DVP_Dim_t. + * \ingroup group_dvp_mem + */ +typedef allocator_dimensions_t DVP_Dim_t; + +/*! \brief This function initializes the DVP memory system. + * \ingroup group_dvp_mem + */ +DVP_Mem_t *dvp_mem_init(); + +/*! \brief This function disables the memory system + * \param [in] pmem The pointer to the pointer to the DVP Memory system. This will be + * set to NULL during this call. + * \ingroup group_dvp_mem + */ +void dvp_mem_deinit(DVP_Mem_t **pmem); + +/*! \brief Frees a multidimensional, multipointer buffer. + * \param [in] handle The handle to the DVP context. + * \param [in] mtype The memory type required. + * \param [in] nptrs The number of pointers in the ptrs array. + * \param [in] ndims The number of dimensions in the dims descriptor. + * \param [in] dims The pointer to the dimensionality descriptor. + * \param [in] ptrs The pointer to the array of pointers to free. + * \ingroup group_dvp_mem + */ +DVP_BOOL dvp_mem_free(DVP_Handle handle, + DVP_MemType_e mtype, + DVP_S32 nptrs, + DVP_S32 ndims, + DVP_Dim_t *dims, + DVP_PTR *ptrs); + + +/*! + * \brief Allocates a multidimensional, multipointer buffer. +Usage: For a linear buffer: + dvp_mem_calloc(t, 1, 2, {{elemSize, numElems}}, {ptrs}, {handles}, {strides}); + +Usage: For a 3 plane image of 320x240 of 1 bpp each (like RGBp): + dvp_mem_calloc(t, 3, 3, {{1,320,240}, + {1,320,240}, + {1,320,240}}, {ptrs}, {handles}, {strides}); + Returns: + {ptrs} = {%p, %p, %p} + {handles} = {%p, %p, %p} + {strides} = {{1,320,0},{1,320,0},{1,320,0}} if 1D, {{1,STRIDE,0},{1,STRIDE,0},{1,STRIDE,0}} if 2D +Usage: For a 3 plane image of 320x240 of 1 bpp for the first plane, but 1/2 planes following (like YUV420): + dvp_mem_calloc(t, 3, 3, {{1,320,240}, + {1,160,120}, + {1,160,120}}, {NULL, NULL, NULL}, {handles}, {strides}); + Returns: + {ptrs} = {%p, %p, %p} + {handles} = {%p, %p, %p} + {strides} = {{1,320,0},{1,320,0},{1,320,0}} if 1D, {{1,STRIDE,0},{1,STRIDE,0},{1,STRIDE,0}} if 2D +Usage: For a 2 plane image of 320x240 of 1 bpp then 160x120 of 2 bpp (like NV12) + dvp_mem_calloc(t, 2, 3, {{1,320,240}, + {2,160,120}}, {NULL, NULL}, {handles}, {strides}); + + Returns: + {ptrs} = {%p, %p} + {handles} = {%p, %p} + {strides} = {{1,320,0},{2,320,0}} if 1D, {{1,STRIDE,0},{2,(other)STRIDE,0}} if 2D +Generically: + dvp_mem_calloc(type, planes, numDim, {{bpp, width, height},...}, {ptrs}, {handles}, {strides}); + * \param [in] handle The handle to the DVP context. + * \param [in] mtype The memory type requested. + * \param [in] nptrs The number of pointers in ptrs array. + * \param [in] ndims The number of valid dimensions in the dims structure. + * \param [in] dims The dimensionality structure array. + * \param [out] ptrs The array of pointers. + * \param [out] strides The array of stride values per pointer. + * \ingroup group_dvp_mem + */ +DVP_BOOL dvp_mem_calloc(DVP_Handle handle, + DVP_MemType_e mtype, + DVP_S32 nptrs, + DVP_S32 ndims, + DVP_Dim_t *dims, + DVP_PTR *ptrs, + DVP_Dim_t *strides); + +/*! \brief This function marks the buffer to be flushed. + * \param [in] handle The handle to the DVP context. + * \param [in] mtype The memory type required. + * \param [in] nptrs The number of pointers in the ptr array. + * \param [in] ndims The number of dimensional structures in dims. + * \param [in] dims The array of dimensionality structures. + * \param [in] ptrs The array of pointers. + * \ingroup group_dvp_mem + */ +DVP_BOOL dvp_mem_flush(DVP_Handle handle, + DVP_MemType_e mtype, + DVP_S32 nptrs, + DVP_S32 ndims, + DVP_Dim_t *dims, + DVP_PTR *ptrs); + +/*! \brief This function marks the buffer to be invalidated. + * \param [in] handle The handle to the DVP context. + * \param [in] mtype The memory type required. + * \param [in] nptrs The number of pointers in the ptr array. + * \param [in] ndims The number of dimensional structures in dims. + * \param [in] dims The array of dimensionality structures. + * \param [in] ptrs The array of pointers. + * \ingroup group_dvp_mem + */ +DVP_BOOL dvp_mem_invalidate(DVP_Handle handle, + DVP_MemType_e mtype, + DVP_S32 nptrs, + DVP_S32 ndims, + DVP_Dim_t *dims, + DVP_PTR *ptrs); + +/*! \brief Generates a handle from an existing buffer to be shared with another process. + * \param [in] handle The handle to the DVP context. + * \param [in] mtype The memory type requested. + * \param [in] nptrs The number of pointers in the ptrs array. + * \param [in] ptrs The array of pointers. + * \param [out] fds The array to place the shared descriptors. + * \ingroup group_dvp_mem + */ +DVP_BOOL dvp_mem_share(DVP_Handle handle, + DVP_MemType_e mtype, + DVP_S32 nptrs, + DVP_PTR *ptrs, + DVP_S32 *fds); + +/*! \brief Imports a buffer from another process. + * \param [in] handle The handle to the DVP context. + * \param [in] mtype The memory type requested. + * \param [in] ndims The number of dimensions in + * \param [in] dims The array of dimensionality structures. + * \param [in] nptrs The number of pointers in ptrs. + * \param [out] ptrs The array of pointers. + * \param [out] strides The array of stride value per pointer. + * \param [in] fds The array of shared descriptors. + * \param [out] hdls The array of handles to each allocated pointer. + * \ingroup group_dvp_mem + */ +DVP_BOOL dvp_mem_import(DVP_Handle handle, + DVP_MemType_e mtype, + DVP_S32 nptrs, + DVP_S32 ndims, + DVP_Dim_t *dims, + DVP_PTR *ptrs, + DVP_Dim_t *strides, + DVP_S32 *fds, + DVP_VALUE *hdls); + +/*! \brief Frees an imported buffer from another process. + * \param [in] handle The handle to the DVP context. + * \param [in] mtype The memory type requested. + * \param [in] ndims The number of dimensionality structures in dims. + * \param [in] dims The array of dimensionality structures. + * \param [in] nptrs The number of pointers in ptrs. + * \param [out] ptrs The array of pointers. + * \param [in] hdls The array of handles for each pointer. + * \ingroup group_dvp_mem + */ +DVP_BOOL dvp_mem_free_import(DVP_Handle handle, + DVP_MemType_e mtype, + DVP_S32 ndims, + DVP_Dim_t *dims, + DVP_S32 nptrs, + DVP_PTR *ptrs, + DVP_VALUE *hdls); + +/*! \brief An internal function to return the device descriptor of the memory device. + * \param [in] handle The handle to the DVP context. + * \return Returns zero when this feature is unsupported. + * \ingroup group_dvp_mem + */ +int dvp_mem_get_device(DVP_Handle handle); + +/*! \brief Converts a DVP memory type to an allocator memory type. + * \param [in] memType The DVP memory type. + * \ingroup group_dvp_mem + */ +allocator_memory_type_e dvp_mem_type_xlate(DVP_MemType_e memType); + +/*! \brief Determines if the memory type is cached. + * \param [in] memType The DVP memory type. + * \ingroup group_dvp_mem + */ +bool_e dvp_mem_type_cached(DVP_MemType_e memType); + +#endif + diff --git a/source/dvp/dvp_kgraph/include/dvp_rpc.h b/source/dvp/dvp_kgraph/include/dvp_rpc.h new file mode 100644 index 0000000..9024caa --- /dev/null +++ b/source/dvp/dvp_kgraph/include/dvp_rpc.h @@ -0,0 +1,399 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use This file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief The DVP RPC layer. + * \defgroup group_dvp_rpc DVP Remote Procedure Calls API. + */ + +#ifndef _DVP_RPC_H_ +#define _DVP_RPC_H_ + +#include +#include + +/*! \brief Defines an warning logging mechanism for RPC calls. + * \ingroup group_dvp_rpc + */ +#define RPC_COMPLAIN_IF_FAILED(ret, statement) { \ + ret = statement;\ + if (ret < 0) { \ + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: "#statement" returned %d\n", ret);\ + }\ +} + +#ifndef DVP_RPC_T +/*! \brief This forward declaration is to prevent needless #includes + * The DVP_RPC library has it's own internal definitions of these which pulls in + * the definitions of foreign libraries which we're trying to not have + * clients of this file have to include or add to their include paths. + * \ingroup group_dvp_rpc + */ +typedef struct _dvp_rpc_t { + DVP_Handle handle; /*!< back reference to top level structure. */ +} DVP_RPC_t; +typedef DVP_U32 DVP_RPC_Core_t; +#endif + +/*! \brief The maximum name length of a remote function + * \ingroup group_dvp_rpc + */ +#define DVP_RPC_MAX_FUNC_NAME_LEN (80) + +/*! \brief A pointer type to a remote dvp function */ +typedef unsigned int (*DVP_Function_f)(unsigned int, unsigned int *); + +/*! \brief Defines a DVP function and it's attributes + * \ingroup group_dvp_rpc + */ +typedef struct _dvp_function_t { + /*! The name of the function */ + char name[DVP_RPC_MAX_FUNC_NAME_LEN]; + /*! The pointer to the function */ + DVP_Function_f function; + /*! The index to the function in a table */ + DVP_U32 index; +} DVP_Function_t; + +/*! \brief Defines the DVP RPC interface for KGMs. + * \ingroup group_dvp_rpc + */ +typedef struct _dvp_rpc_interface_t { + /*! These are the calls into the library from the remote core */ + DVP_Function_t *localFunctions; + /*! The number of local functions */ + DVP_U32 numLocalFunctions; + /*! These are the calls from the library into the remote core */ + DVP_Function_t *remoteFunctions; + /*! The number of remote functions */ + DVP_U32 numRemoteFunctions; + /*! The core which the KGM interacts with */ + DVP_Core_e coreEnum; +} DVP_RPC_Interface_t; + +/*! \brief Defines the direction a parameter can go + * \ingroup group_dvp_rpc + */ +typedef enum _dvp_rpc_parameter_e { + DVP_RPC_READ_ONLY, /*!< This indicates MPU to RPU only */ + DVP_RPC_WRITE_ONLY, /*!< This indicates RPU to MPU only */ + DVP_RPC_READ_AND_WRITE, /*!< This indicates both MPU to RPU and RPU + back to MPU */ +} DVP_RPC_Parameter_e; + +/*! \brief Defines a pointer translation structure + * \ingroup group_dvp_rpc + */ +typedef struct _dvp_rpc_ptr_translation_t { + DVP_U32 index; + DVP_U32 offset; + DVP_U32 base; + DVP_BOOL cacheops; + DVP_PTR reserved; +} DVP_RPC_PointerTranslation_t; + +/*! \brief Defines a maximum number of pointer translations + * \ingroup group_dvp_rpc + */ +#define DVP_MAX_TRANSLATIONS (1024) + +/*! \brief Define the number of times DVP will retry a restart before giving up. + * \ingroup group_dvp_rpc + */ +#define DVP_MAX_RESTART_RETRY (100) + +/*! \brief This structure maintains the list of translations for a call. + * \ingroup group_dvp_rpc + */ +typedef struct _dvp_rpc_translation_t { + DVP_U32 numTranslations; + DVP_RPC_PointerTranslation_t translations[DVP_MAX_TRANSLATIONS]; +} DVP_RPC_Translation_t; + +/*! \brief This structure describes a parameter which will be passed over RPC. + * \ingroup group_dvp_rpc + */ +typedef struct _dvp_rpc_parameter_t { + DVP_RPC_Parameter_e type; /*!< The type or direction of the + parameter. */ + DVP_U32 size; /*!< The size of the data pointed to. */ + DVP_PTR data; /*!< The data pointer to send */ + DVP_PTR reserved; /*!< In ANDROID this should be used to + hold the handle to the memory */ +} DVP_RPC_Parameter_t; + +/*! \brief The callback type for unexpected restarts on the remote endpoint. + * \param [in] cookie The user private pointer. + * \ingroup group_dvp_rpc + */ +typedef void (*dvp_rpc_restart_f)(void *cookie); + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \brief This function initializes the IPC/Syslink layers for all remote cores + * \ingroup group_dvp_rpc + */ +DVP_RPC_t *dvp_rpc_init(); + +/*! + * \brief This function deinitializes the IPC/Syslink layers for all remote + * cores + * \param [in] rpc The pointer to the pointer to the RPC context. This will be + * set to NULL + * during this function. + * \ingroup group_dvp_rpc + */ +void dvp_rpc_deinit(DVP_RPC_t **rpc); + +/*! + * \brief This function registers a client's restart callback. + * \param [in] rpc The pointer to the RPC context. + * \param [in] rpcc The pointer to the RPC Core context. + * \param [in] func The function to call after an unexpected restart of the + * remote endpoint. + * \param [in] cookie The user private data to pass to the function. + */ +void dvp_rpc_restart_callback_register(DVP_RPC_t *rpc, + DVP_RPC_Core_t *rpcc, + dvp_rpc_restart_f func, + void *cookie); + +/*! + * \brief This function translates a local virtual address into a remote + * virtual address. If the buffer has not been mapped it will map it unto all + * the remote cores. If the buffer has been mapped before it will quickly + * lookup the remote address and return it. + * \param rpc The pointer to the RPC context. + * \param core The remote core to get the virtual address for. + * \param localAddr The local virtual address. + * \param localSize The size of the memory area to map. + * \param memType The type of memory this is allocated from. + * \return Returns the virtual address on the remote core. + * \ingroup group_dvp_rpc + */ +DVP_PTR dvp_rpc_mem_xlate_fwrd(DVP_RPC_t *rpc, + DVP_Core_e core, + DVP_PTR localAddr, + DVP_U32 localSize, + DVP_MemType_e memType); + +/*! + * \brief This function translates a remote virtual address into a local + * virtual address. + * \param rpc The pointer to the RPC context. + * \param core The remote core to get the virtual address for. + * \param remoteAddr The remote irtual address. + * \param memType The type of memory this is allocated from. + * \return Returns the virtual address on the local core. + * \ingroup group_dvp_rpc + */ +DVP_PTR dvp_rpc_mem_xlate_back(DVP_RPC_t *rpc, + DVP_Core_e core, + DVP_PTR remoteAddr, + DVP_MemType_e memType); + +/*! + * \brief This function removes the local pointer from all remote translation + * hashes. + * \param [in] rpc The pointer to the RPC context. + * \param [in] localAddr + * \param [in] localSize + * \param [in] memType + * \ingroup group_dvp_rpc + */ +void dvp_rpc_mem_remove(DVP_RPC_t *rpc, + DVP_PTR localAddr, + DVP_U32 localSize, + DVP_MemType_e memType); + +/*! + * \brief This function initializes the interfaces for a particular remote + * core (remote calls and local callbacks). + * \param [in] rpc The pointer to the RPC context. + * \param [in] rpci + * \ingroup group_dvp_rpc + */ +DVP_RPC_Core_t *dvp_rpc_core_init(DVP_RPC_t *rpc, DVP_RPC_Interface_t *rpci); + +/*! + * \brief This function deinitializes the interface to the remote core. + * \param [in] rpc The pointer to the RPC context. + * \param [in] rpcc + * \ingroup group_dvp_rpc + */ +void dvp_rpc_core_deinit(DVP_RPC_t *rpc, DVP_RPC_Core_t **rpcc); + +/*! + * \brief This function removes the association of the pointer to the remote + * cores. + * \param [in] rpc The pointer to the RPC context. + * \param [in] mem + * \param [in] ptr + * \param [in] pHandle + * \param [in] size + * \param [in] mtype + * \ingroup group_dvp_rpc + */ +DVP_BOOL dvp_rpc_dissociate(DVP_RPC_t *rpc, + DVP_Mem_t *mem, + DVP_PTR ptr, + DVP_VALUE *pHandle, + size_t size, + DVP_MemType_e mtype); + +/*! + * \brief This function associates the pointer with it's handle and the + * remote cores. + * \param [in] rpc The pointer to the RPC context. + * \param [in] mem + * \param [in] ptr + * \param [in] handle + * \param [in] size + * \param [in] mtype + * \ingroup group_dvp_rpc + */ +DVP_BOOL dvp_rpc_associate(DVP_RPC_t *rpc, + DVP_Mem_t *mem, + DVP_PTR ptr, + DVP_VALUE handle, + size_t size, + DVP_MemType_e mtype); + +/*! + * \brief Retrieves the interal handle of the memory pointer. + * \param [in] rpc The pointer to the RPC context. + * \param [in] ptr + * \ingroup group_dvp_rpc + */ +DVP_VALUE dvp_rpc_get_handle(DVP_RPC_t *rpc, DVP_PTR ptr); + +/*! + * \brief This function allows remote execution of code. + * \param [in] rpc The pointer to the RPC context. + * \param [in] rpcc + * \param [in] cliIndex + * \param [in] params + * \param [in] numParams + * \param [in] trans + * \ingroup group_dvp_rpc + */ +int dvp_rpc_remote_execute(DVP_RPC_t *rpc, + DVP_RPC_Core_t *rpcc, + int cliIndex, + DVP_RPC_Parameter_t *params, + DVP_U32 numParams, + DVP_RPC_Translation_t *trans); + +/*! \brief This function invalidates memory from the cache. + * \param [in] rpc The pointer to the RPC context. + * \param [in] core + * \param [in] address + * \param [in] size + * \param [in] mtype + * \ingroup group_dvp_rpc + */ +DVP_BOOL dvp_rpc_invalidate(DVP_RPC_t *rpc, + DVP_Core_e core, + DVP_PTR address, + DVP_U32 size, + DVP_MemType_e mtype); + +/*! \brief This function flushes data back to RAM from the cache. + * \param [in] rpc The pointer to the RPC context. + * \param [in] core + * \param [in] address + * \param [in] size + * \param [in] mtype + * \ingroup group_dvp_rpc + */ +DVP_BOOL dvp_rpc_flush(DVP_RPC_t *rpc, + DVP_Core_e core, + DVP_PTR address, + DVP_U32 size, + DVP_MemType_e mtype); + +/*! + * \brief This function does an optional flush then a foward translation on + * each plane pointer. + * \param [in] rpc The pointer to the RPC context. + * \param [in] core + * \param [in] pImage + * \param [in] cacheOp + * \param [in] base + * \param [in] trans + * \ingroup group_dvp_rpc + */ +void dvp_rpc_prepare_image(DVP_RPC_t *rpc, + DVP_Core_e core, + DVP_Image_t *pImage, + DVP_BOOL cacheOp, + DVP_PTR base, + DVP_RPC_Translation_t *trans); + +/*! + * \brief This function does a backward translation on each plane pointer as + * well as an optional invalidate. + * \param [in] rpc The pointer to the RPC context. + * \param [in] core + * \param [in] pImage + * \param [in] cacheOps + * \ingroup group_dvp_rpc + */ +void dvp_rpc_return_image(DVP_RPC_t *rpc, + DVP_Core_e core, + DVP_Image_t *pImage, + DVP_BOOL cacheOp); + +/*! + * \brief This function does an optional flush then a foward translation on + * each plane pointer. + * \param [in] rpc The pointer to the RPC context. + * \param [in] core + * \param [in] pBuffer + * \param [in] cacheOp + * \param [in] base + * \param [in] trans + * \ingroup group_dvp_rpc + */ +void dvp_rpc_prepare_buffer(DVP_RPC_t *rpc, + DVP_Core_e core, + DVP_Buffer_t *pBuffer, + DVP_BOOL cacheOp, + DVP_PTR base, + DVP_RPC_Translation_t *trans); + +/*! + * \brief This function does a backward translation on each plane pointer + * as well as an optional invalidate. + * \param [in] rpc The pointer to the RPC context. + * \param [in] core + * \param [in] pBuffer + * \param [in] cacheOp + * \ingroup group_dvp_rpc + */ +void dvp_rpc_return_buffer(DVP_RPC_t *rpc, + DVP_Core_e core, + DVP_Buffer_t *pBuffer, + DVP_BOOL cacheOp); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/dvp/dvp_test/Android.mk b/source/dvp/dvp_test/Android.mk new file mode 100644 index 0000000..f6c7a13 --- /dev/null +++ b/source/dvp/dvp_test/Android.mk @@ -0,0 +1,104 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CPPFLAGS := $(DVP_DEBUGGING) $(DVP_CPPFLAGS) $(DVP_FEATURES) +LOCAL_SRC_FILES := dvp_test.cpp TestVisionEngine.cpp +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_STATIC_LIBRARIES := libVisionEngine +LOCAL_SHARED_LIBRARIES := libdvp libcutils libOMX_Core libbinder libutils libgui libmedia libhardware libui +LOCAL_MODULE := dvp_test +include $(BUILD_EXECUTABLE) + +ifneq (,$(findstring dsplib,$(VISION_LIBRARIES))) +# A simple unit test for DVP +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(DVP_DEBUGGING) $(DVP_CFLAGS) $(DVP_FEATURES) +LOCAL_SRC_FILES := dvp_dsplib.c +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_STATIC_LIBRARIES := +LOCAL_SHARED_LIBRARIES := libdvp libcutils libbinder +LOCAL_MODULE := dvp_dsplib +include $(BUILD_EXECUTABLE) +endif + +# A simple unit test for DVP +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(DVP_DEBUGGING) $(DVP_CFLAGS) $(DVP_FEATURES) +LOCAL_SRC_FILES := dvp_simple.c +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_STATIC_LIBRARIES := +LOCAL_SHARED_LIBRARIES := libdvp libcutils libbinder +LOCAL_MODULE := dvp_simple +include $(BUILD_EXECUTABLE) + +# A query utility for DVP +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(DVP_DEBUGGING) $(DVP_CFLAGS) $(DVP_FEATURES) +LOCAL_SRC_FILES := dvp_info.c +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_STATIC_LIBRARIES := +LOCAL_SHARED_LIBRARIES := libdvp libcutils libbinder +LOCAL_MODULE := dvp_info +include $(BUILD_EXECUTABLE) + +# A DVP memory share/import unit test +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CPPFLAGS := $(DVP_DEBUGGING) $(DVP_CPPFLAGS) $(DVP_FEATURES) +LOCAL_SRC_FILES := dvp_share.cpp +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_SHARED_LIBRARIES := libdvp libutils libcutils libbinder +LOCAL_MODULE := dvp_share +include $(BUILD_EXECUTABLE) + +# A DVP crash recovery unit test +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(DVP_DEBUGGING) $(DVP_CFLAGS) $(DVP_FEATURES) +LOCAL_SRC_FILES := dvp_crash_test.c +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_SHARED_LIBRARIES := libdvp libutils libcutils libbinder +LOCAL_MODULE := dvp_crash_test +include $(BUILD_EXECUTABLE) + +# A framework unit test for DVP +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(DVP_DEBUGGING) $(DVP_CFLAGS) $(DVP_FEATURES) +LOCAL_SRC_FILES := dvp_unittest.c +LOCAL_C_INCLUDES += $(DVP_INCLUDES) +LOCAL_STATIC_LIBRARIES := +LOCAL_SHARED_LIBRARIES := libdvp libcutils libbinder +LOCAL_MODULE := dvp_unittest +include $(BUILD_EXECUTABLE) \ No newline at end of file diff --git a/source/dvp/dvp_test/TestVisionEngine.cpp b/source/dvp/dvp_test/TestVisionEngine.cpp new file mode 100644 index 0000000..3e82049 --- /dev/null +++ b/source/dvp/dvp_test/TestVisionEngine.cpp @@ -0,0 +1,5869 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(DVP_USE_VLIB) +#include +#endif + +#if defined(DVP_USE_IMGLIB) +#include +#endif + +#if defined(DVP_USE_RVM) +#include +#endif + +#if defined(DVP_USE_TISMO) +#include +#endif + +#if defined(DVP_USE_VRUN) +#include +#endif + +#if defined(DVP_USE_ORB) +#include +#include +#endif + +#if defined(DVP_USE_DSPLIB) +#include +#define TEST_DSPLIB +#include +#endif + +#if defined(DVP_USE_YUV) +#include +#endif + +#include + +#if (defined(WIN32) && !defined(CYGWIN)) || defined(__QNX__) || defined(SYSBIOS) +#ifndef M_PI +#define M_PI 3.14159265358979323846 /**< Pi */ +#endif +#endif + +TestVisionEngine::TestVisionEngine(uint32_t width, uint32_t height, uint32_t fps, fourcc_t color, char *camName, uint32_t numFrames, int32_t graph, DVP_Core_e affinity) + : VisionEngine(width, height, fps, color, camName, numFrames) +{ + m_graphtype = (TI_GraphType_e)graph; + m_display_enabled = false_e; + m_imgdbg_enabled = true_e; + m_testcore = affinity; + +#if defined(DVP_USE_IPC) + DVP_PRINT(DVP_ZONE_ENGINE, "Using IPC!\n"); +#endif + +#if defined(DVP_USE_RCM) + DVP_PRINT(DVP_ZONE_ENGINE, "Using RCM!\n"); +#endif + +#if defined(DVP_USE_OMAPRPC) + DVP_PRINT(DVP_ZONE_ENGINE, "Using OMAPRPC!\n"); +#endif + +#if defined(DVP_USE_TILER) + DVP_PRINT(DVP_ZONE_ENGINE, "Using TILER!\n"); +#endif + +#if defined(DVP_USE_ION) + DVP_PRINT(DVP_ZONE_ENGINE, "Using ION!\n"); +#endif + +#if defined(DVP_USE_GRALLOC) + DVP_PRINT(DVP_ZONE_ENGINE, "Using GRALLOC!\n"); +#endif + +#if defined(DVP_USE_BO) + DVP_PRINT(DVP_ZONE_ENGINE, "Using OMAP BO!\n"); +#endif + + DVP_PRINT(DVP_ZONE_ENGINE, "Using path to im files: %s\n", m_imgdbg_path); +} + +TestVisionEngine::~TestVisionEngine() +{ + // do nothing +} + +status_e TestVisionEngine::PostProcessImage(VisionCamFrame* pFrame, uint32_t numSections) +{ + pFrame = pFrame; + numSections = numSections; + return STATUS_SUCCESS; +} + +status_e TestVisionEngine::GraphSetup() +{ + status_e status = STATUS_INVALID_PARAMETER; + m_hDVP = DVP_KernelGraph_Init(); + DVP_PRINT(DVP_ZONE_ENGINE, "DVP Handle = %p, about to setup graph %d\n", (void*)m_hDVP, m_graphtype); + if (m_hDVP) + { + AllocateGraphs(1); + + switch (m_graphtype) + { + case TI_GRAPH_TYPE_EDGE: + status = EdgeGraphSetup(); + break; + case TI_GRAPH_TYPE_RVM: + status = Test_RVM(); + break; + case TI_GRAPH_TYPE_TEST1: + status = Test_MorphGraphSetup(); + break; + case TI_GRAPH_TYPE_TEST2: + status = Test_NonmaxImgconvGraphSetup(); + break; + case TI_GRAPH_TYPE_TEST3: + status = Test_CannyGraphSetup(); + break; + case TI_GRAPH_TYPE_TEST4: + status = Test_MiscGraphSetup(); + break; + case TI_GRAPH_TYPE_TEST5: + status = Test_SimcopGraphSetup(); + break; + case TI_GRAPH_TYPE_TEST6: + m_testcore = DVP_CORE_DSP; + status = Test_SimcopGraphSetup(); + break; + case TI_GRAPH_TYPE_TEST7: + m_testcore = DVP_CORE_CPU; + status = Test_SimcopGraphSetup(); + break; + case TI_GRAPH_TYPE_TEST8: + status = Test_HistGraphSetup(); + break; + case TI_GRAPH_TYPE_TEST9: + status = Test_NV12GraphSetup(); + break; + case TI_GRAPH_TYPE_TEST10: + status = Test_UYVYScalingGraph(); + break; + case TI_GRAPH_TYPE_TEST11: + status = Test_Rotate(); + break; + case TI_GRAPH_TYPE_DISPARITY: + status = Test_Disparity(); + break; + case TI_GRAPH_TYPE_TISMO: + status = Test_Tismo(); + break; + case TI_GRAPH_TYPE_IMGLIB: + status = Test_Imglib(); + break; + case TI_GRAPH_TYPE_LDC: + status = Test_Ldc(); + break; + case TI_GRAPH_TYPE_AR: + status = Test_AR(); + break; + case TI_GRAPH_TYPE_BOUNDARY: + status = Test_Boundary(); + break; + case TI_GRAPH_TYPE_HARRIS: + status = Test_HarrisCorner(); + break; + case TI_GRAPH_TYPE_ORBHARRIS: + status = Test_ORBnHarris(); + break; + case TI_GRAPH_TYPE_TESLA: + status = Test_TeslaGraphSetup(); + break; + case TI_GRAPH_TYPE_IMGLIB_TESLA: + m_testcore = DVP_CORE_DSP; + status = Test_Imglib(); + break; + case TI_GRAPH_TYPE_DSPLIB_TESLA: + m_testcore = DVP_CORE_DSP; + status = Test_DSPLIB(); + break; + case TI_GRAPH_TYPE_VLIB_CPU: + m_testcore = DVP_CORE_CPU; + status = Test_TeslaGraphSetup(); + break; + case TI_GRAPH_TYPE_IMGLIB_CPU: + m_testcore = DVP_CORE_CPU; + status = Test_Imglib(); + break; + + /* VENDOR Custom Test Graphs can be added here */ + + + /* End of VENDOR Custom Test Graphs */ + + default: + DVP_PRINT(DVP_ZONE_ERROR, "Invalid Graph Type\n"); + break; + } + } + DVP_PRINT(DVP_ZONE_ENGINE, "GraphSetup status is %d\n", status); + return status; +} + +status_e TestVisionEngine::Test_DSPLIB() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_DSPLIB) + DVP_U32 elemSize = sizeof(DVP_U16); + DVP_U32 numElems = 128; + DVP_U08 noNodes = 0; + + DVP_PRINT(DVP_ZONE_ERROR, "Test_DSPLIB: begins\n"); + + + if (m_hDVP) + { + if ( AllocateImageStructs(3)) + { + DVP_Image_Init(&m_images[0], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[1], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[2], 3, 3, FOURCC_Y800); + if(!DVP_Image_Alloc(m_hDVP, &m_images[0], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[1], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[2], DVP_MTYPE_DEFAULT)) + return STATUS_NOT_ENOUGH_MEMORY; + } + if ( AllocateBufferStructs(123)) + { + DVP_Buffer_Init(&m_buffers[0], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[1], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[2], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[3], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[4], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[5], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[6], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[7], elemSize, (numElems)>>1); + DVP_Buffer_Init(&m_buffers[8], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[9], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[10], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[11], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[12], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[13], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[14], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[15], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[16], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[17], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[18], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[19], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[20], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[21], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[22], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[23], elemSize,sizeof(FFT_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[24], elemSize, sizeof(FFT_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[25], elemSize,sizeof(FFT_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[26], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[27], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[28], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[29], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[30], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[31], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[32], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[33], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[34], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[35], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[36], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[37], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[38], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[39], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[40], elemSize, numElems); + + DVP_Buffer_Init(&m_buffers[41], elemSize, sizeof(FIR_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[42], elemSize, sizeof(FIR_h)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[43], elemSize, sizeof(FIR_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[44], elemSize, sizeof(FIR_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[45], elemSize, sizeof(FIR_h)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[46], elemSize, sizeof(FIR_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[47], elemSize, sizeof(FIR_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[48], elemSize, sizeof(FIR_h)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[49], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[50], elemSize, sizeof(FIR_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[51], elemSize, sizeof(FIR_h)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[52], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[53], elemSize, sizeof(FIR_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[54], elemSize, sizeof(FIR_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[55], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[56], elemSize, sizeof(FIR_Rx)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[57], elemSize, sizeof(FIR_Rh)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[58], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[59], elemSize, sizeof(FIR_Rx)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[60], elemSize, sizeof(FIR_Rh)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[61], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[62], elemSize, sizeof(FIR_Rx)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[63], elemSize, sizeof(FIR_Rh)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[64], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[65], elemSize, sizeof(FIR_xS)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[66], elemSize, sizeof(FIR_hs)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[67], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[68], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[69], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[70], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[71], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[72], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[73], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[74], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[75], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[76], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[77], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[78], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[79], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[80], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[81], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[82], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[83], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[84], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[85], elemSize, sizeof(x_IIR)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[86], elemSize, sizeof(k_IIR)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[87], elemSize, sizeof(b_c_IIR)/sizeof(DVP_U16));; + DVP_Buffer_Init(&m_buffers[88], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[89], elemSize, sizeof(ptr_Coefs)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[90], elemSize, (N_IIRSS + PAD_IIRSS)); + DVP_Buffer_Init(&m_buffers[91], elemSize, 256); + DVP_Buffer_Init(&m_buffers[92], elemSize, 256); + DVP_Buffer_Init(&m_buffers[93], elemSize, 256); + DVP_Buffer_Init(&m_buffers[94], elemSize, 256); + DVP_Buffer_Init(&m_buffers[95], elemSize, 256); + DVP_Buffer_Init(&m_buffers[96], elemSize, 256); + DVP_Buffer_Init(&m_buffers[97], elemSize, 256); + DVP_Buffer_Init(&m_buffers[98], elemSize, 256); + DVP_Buffer_Init(&m_buffers[99], elemSize, sizeof(buffer_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[100], elemSize, sizeof(buffer_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[101], elemSize, sizeof(buffer_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[102], elemSize, 256*9); + DVP_Buffer_Init(&m_buffers[103], elemSize, 9); + DVP_Buffer_Init(&m_buffers[104], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[105], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[106], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[107], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[108], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[109], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[110], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[111], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[112], elemSize, sizeof(FIR_x)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[113], elemSize, sizeof(a_W_VEC)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[114], elemSize, sizeof(a_W_VEC)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[115], elemSize, sizeof(a_W_VEC)/sizeof(DVP_U16)); + DVP_Buffer_Init(&m_buffers[116], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[117], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[118], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[119], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[120], elemSize, numElems); + DVP_Buffer_Init(&m_buffers[121], elemSize, 256); + DVP_Buffer_Init(&m_buffers[122], elemSize, 256); + + DVP_PRINT(DVP_ZONE_ERROR, "Test_DSPLIB: End of Buffer Init\n"); + + if ( !DVP_Buffer_Alloc(m_hDVP, &m_buffers[0], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[1], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[2], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[3], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[4], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[5], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[6], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[7], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[8], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[9], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[10], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[11], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[12], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[13], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[14], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[15], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[16], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[17], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[18], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[19], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[20], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[21], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[22], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[23], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[24], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[25], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[26], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[27], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[28], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[29], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[30], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[31], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[32], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[33], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[34], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[35], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[36], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[37], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[38], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[39], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[40], DVP_MTYPE_DEFAULT) || + + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[41], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[42], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[43], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[44], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[45], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[46], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[47], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[48], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[49], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[50], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[51], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[52], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[53], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[54], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[55], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[56], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[57], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[58], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[59], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[60], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[61], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[62], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[63], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[64], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[65], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[66], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[67], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[68], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[69], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[70], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[71], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[72], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[73], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[74], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[75], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[76], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[77], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[78], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[79], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[80], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[81], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[82], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[83], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[84], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[85], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[86], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[87], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[88], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[89], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[90], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[91], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[92], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[93], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[94], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[95], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[96], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[97], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[98], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[99], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[100], DVP_MTYPE_DEFAULT)|| + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[101], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[102], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[103], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[104], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[105], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[106], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[107], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[108], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[109], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[110], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[111], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[112], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[113], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[114], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[115], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[116], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[117], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[118], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[119], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[120], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[121], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[122], DVP_MTYPE_DEFAULT)) + { + return STATUS_NOT_ENOUGH_MEMORY; + } + DVP_PRINT(DVP_ZONE_ERROR, "Test_DSPLIB: End of Buffer Alloc\n"); + + } +#ifdef TEST_DSPLIB + memcpy(m_buffers[0].pData,buffer_x,sizeof(buffer_x)); + memcpy(m_buffers[1].pData,buffer_x,sizeof(buffer_y)); + memcpy(m_buffers[3].pData,buffer_x,sizeof(buffer_x)); + memcpy(m_buffers[4].pData,buffer_x,sizeof(buffer_y)); + memcpy(m_buffers[8].pData,buffer_x,sizeof(buffer_x)); + memcpy(m_buffers[9].pData,buffer_x,sizeof(buffer_y)); + memcpy(m_buffers[11].pData,buffer_x,sizeof(buffer_x)); + memcpy(m_buffers[13].pData,buffer_x,sizeof(buffer_x)); + memcpy(m_buffers[15].pData,buffer_x,sizeof(buffer_x)); + memcpy(m_buffers[17].pData,buffer_x,sizeof(buffer_x)); + memcpy(m_buffers[18].pData,buffer_x,sizeof(buffer_y)); + memcpy(m_buffers[20].pData,buffer_x,sizeof(buffer_x)); + memcpy(m_buffers[21].pData,buffer_x,sizeof(buffer_y)); + memcpy(m_buffers[23].pData,FFT_x,sizeof(FFT_x)); + memcpy(m_buffers[24].pData,FFT_x,sizeof(FFT_x)); + memcpy(m_buffers[26].pData,buffer_x,sizeof(buffer_x)); + memcpy(m_buffers[27].pData,buffer_x,sizeof(buffer_y)); + memcpy(m_buffers[29].pData,buffer_x,sizeof(buffer_x)); + memcpy(m_buffers[30].pData,buffer_x,sizeof(buffer_y)); + memcpy(m_buffers[32].pData,buffer_x,sizeof(buffer_x)); + memcpy(m_buffers[33].pData,buffer_x,sizeof(buffer_y)); + memcpy(m_buffers[35].pData,buffer_x,sizeof(buffer_x)); + memcpy(m_buffers[36].pData,buffer_x,sizeof(buffer_y)); + memcpy(m_buffers[38].pData,buffer_x,sizeof(buffer_x)); + memcpy(m_buffers[39].pData,buffer_x,sizeof(buffer_y)); + + memcpy(m_buffers[41].pData,FIR_x,sizeof(FIR_x)); + memcpy(m_buffers[42].pData,FIR_h,sizeof(FIR_h)); + memcpy(m_buffers[44].pData,FIR_x,sizeof(FIR_x)); + memcpy(m_buffers[45].pData,FIR_h,sizeof(FIR_h)); + memcpy(m_buffers[47].pData,FIR_x,sizeof(FIR_x)); + memcpy(m_buffers[48].pData,FIR_h,sizeof(FIR_h)); + memcpy(m_buffers[50].pData,FIR_x,sizeof(FIR_x)); + memcpy(m_buffers[51].pData,FIR_h,sizeof(FIR_h)); + memcpy(m_buffers[53].pData,FIR_x,sizeof(FIR_x)); + memcpy(m_buffers[54].pData,FIR_x,sizeof(FIR_x)); + + memcpy(m_buffers[56].pData,FIR_Rx,sizeof(FIR_Rx)); + memcpy(m_buffers[57].pData,FIR_Rh,sizeof(FIR_Rh)); + memcpy(m_buffers[59].pData,FIR_Rx,sizeof(FIR_Rx)); + memcpy(m_buffers[60].pData,FIR_Rh,sizeof(FIR_Rh)); + memcpy(m_buffers[62].pData,FIR_Rx,sizeof(FIR_Rx)); + memcpy(m_buffers[63].pData,FIR_Rh,sizeof(FIR_Rh)); + + memcpy(m_buffers[65].pData,FIR_xS,sizeof(FIR_xS)); + memcpy(m_buffers[66].pData,FIR_hs,sizeof(FIR_hs)); + + memcpy(m_buffers[68].pData,IFFT_x,sizeof(IFFT_x)); + memcpy(m_buffers[69].pData,IFFT_x,sizeof(IFFT_x)); + memcpy(m_buffers[71].pData,IFFT_x,sizeof(IFFT_x)); + memcpy(m_buffers[72].pData,IFFT_x,sizeof(IFFT_x)); + memcpy(m_buffers[74].pData,IFFT_x,sizeof(IFFT_x)); + memcpy(m_buffers[75].pData,IFFT_x,sizeof(IFFT_x)); + memcpy(m_buffers[77].pData,IFFT_x,sizeof(IFFT_x)); + memcpy(m_buffers[78].pData,IFFT_x,sizeof(IFFT_x)); + + memcpy(m_buffers[85].pData,x_IIR,sizeof(x_IIR)); + memcpy(m_buffers[86].pData,k_IIR,sizeof(k_IIR)); + memcpy(m_buffers[87].pData,b_c_IIR,sizeof(b_c_IIR)); + memcpy(m_buffers[89].pData,ptr_Coefs,sizeof(ptr_Coefs)); + + memcpy(m_buffers[91].pData,MAT_x,sizeof(MAT_x)); + memcpy(m_buffers[92].pData,MAT_y,sizeof(MAT_y)); + memcpy(m_buffers[94].pData,MAT_x,sizeof(MAT_x)); + memcpy(m_buffers[95].pData,MAT_y,sizeof(MAT_y)); + memcpy(m_buffers[97].pData,MAT_x,sizeof(MAT_x)); + memcpy(m_buffers[99].pData,buffer_x,sizeof(buffer_x)); + memcpy(m_buffers[100].pData,buffer_x,sizeof(buffer_x)); + memcpy(m_buffers[101].pData,buffer_x,sizeof(buffer_x)); + memcpy(m_buffers[102].pData,GSP0_TABLE,sizeof(GSP0_TABLE)); + memcpy(m_buffers[103].pData,errCoefs,sizeof(errCoefs)); + memcpy(m_buffers[112].pData,FIR_x,sizeof(FIR_x)); + memcpy(m_buffers[113].pData,a_W_VEC,sizeof(a_W_VEC)); + memcpy(m_buffers[114].pData,a_W_VEC,sizeof(a_W_VEC)); + + memcpy(m_buffers[121].pData,MAT_x,sizeof(MAT_x)/sizeof(DVP_U16)); + + + DVP_PRINT(DVP_ZONE_ERROR, "Test_DSPLIB: End of Memcopy\n"); + +#endif + + if (AllocateNodes(17) && AllocateSections(&m_graphs[0], 1)) + { +#if defined(DVP_USE_IMGLIB) + m_pNodes[noNodes].header.kernel = DVP_KN_IMG_CONV_3x3; + dvp_knode_to(&m_pNodes[noNodes], DVP_ImageConvolution_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[noNodes], DVP_ImageConvolution_t)->output = m_images[1]; + dvp_knode_to(&m_pNodes[noNodes], DVP_ImageConvolution_t)->mask = m_images[2]; + dvp_knode_to(&m_pNodes[noNodes], DVP_ImageConvolution_t)->shiftMask = 6; + noNodes++; +#endif +#if 0 + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_ADD16; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[0]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input1 = m_buffers[1]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[2]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_ADD32; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[3]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input1 = m_buffers[4]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[5]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_AUTOCORR16; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[6]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[7]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_BITEXP32; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[8]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_BLKESWAP16; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[9]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[10]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_BLKESWAP32; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[11]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[12]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_BLKESWAP64; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[13]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[14]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_BLKMOVE; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[15]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[16]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_DOTPRODSQR; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[17]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input1 = m_buffers[18]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[19]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = 2;//Needs attn + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_DOTPROD; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[20]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input1 = m_buffers[21]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[22]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_FFT_16x16; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[23]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[24]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[25]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_FFT_16x16R; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[26]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[27]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[28]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = 2; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val2 = 2; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val3 = 8; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_FFT_16x16_IMRE; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[29]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[30]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[31]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_FFT_16x32; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[32]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[33]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[34]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_FFT_32x32; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[35]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[36]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[37]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_FFT_32x32s; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[38]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[39]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[40]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_CPLX; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[41]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[42]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[43]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = sizeof(FIR_h)>>1; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val2 = sizeof(FIR_x)>>1; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_HM4x4; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[44]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[45]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[46]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = sizeof(FIR_h)>>1; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val2 = sizeof(FIR_x)>>1; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_GEN; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[47]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[48]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[49]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_HM17_RA8x8; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[50]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[51]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[52]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_LMS2; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[53]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[54]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[55]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = 0x1000; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val2 = 0x0; // Return value + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_R4; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[56]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[57]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[58]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_R8; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[59]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[60]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[61]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_HM16_RM8A8x8; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[62]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[63]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[64]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_SYM; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[65]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[66]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[67]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = 0; + noNodes++; //25 +#endif + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_IFFT_16x16; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[68]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[69]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[70]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = (sizeof(IFFT_x)/sizeof(DVP_U16))>>1; // Size of coefficient array = 2*nx + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_IFFT_16x16_IMRE; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[71]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[72]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[73]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = (sizeof(IFFT_x)/sizeof(DVP_U16))>>1; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_IFFT_16x32; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[74]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[75]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[76]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = (sizeof(IFFT_x)/sizeof(DVP_U16))>>1; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_IFFT_32x32; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[77]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[78]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[79]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = (sizeof(IFFT_x)/sizeof(DVP_U16))>>1; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_IIR; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[80]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input1 = m_buffers[81]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[82]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[83]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output1 = m_buffers[84]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = numElems; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_IIR_LAT; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[85]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input1 = m_buffers[86]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[87]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[88]; + noNodes++;//3 //31 + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_IIR_SS; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = 0; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[89]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input1 = m_buffers[90]; + noNodes++; + + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_MUL; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSP_MatMul)->input0 = m_buffers[91]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSP_MatMul)->input1 = m_buffers[92]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSP_MatMul)->output0 = m_buffers[93]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSP_MatMul)->r1 = 16; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSP_MatMul)->c1 = 16; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSP_MatMul)->r2 = 16; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSP_MatMul)->c2 = 16; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSP_MatMul)->qs = 1; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_MUL_CPLX; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSP_MatMul)->input0 = m_buffers[94]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSP_MatMul)->input1 = m_buffers[95]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSP_MatMul)->output0 = m_buffers[96]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSP_MatMul)->r1 = 16; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSP_MatMul)->c1 = 16; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSP_MatMul)->r2 = 16; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSP_MatMul)->c2 = 16; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSP_MatMul)->qs = 1; + noNodes++; + + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_W_VEC; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[113]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input1 = m_buffers[114]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[115]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = 16384; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_MAXVAL; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[99]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_MINVAL; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[100]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_MAXIDX; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[101]; + noNodes++; + + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_MINERROR; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[102]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input1 = m_buffers[103]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_MUL32; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[104]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input1 = m_buffers[105]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[106]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = numElems; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_NEG32; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[107]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[108]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = numElems; + noNodes++; + +#if 0 + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_RECIP16; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[109]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->twoway = m_buffers[110]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[111]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = numElems; + noNodes++; + + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_VECSUMSQ; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[112]; + noNodes++; + + m_pNodes[noNodes].header.kernel = DVP_KN_DSP_MAT_TRANS; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->input0 = m_buffers[121]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->output0 = m_buffers[122]; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val1 = 16; + dvp_knode_to(&m_pNodes[noNodes], DVP_DSPFunc)->val2 = 16; + noNodes++; +#endif + + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + + } + + + if(m_testcore != DVP_CORE_MIN) + { + for(uint32_t testnode=0; testnodeinput = m_images[0]; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[4]; + + m_pNodes[1].header.kernel = DVP_KN_SCHARR_8; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = m_images[4]; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->output = m_images[5]; + + m_pNodes[2].header.kernel = DVP_KN_ERODE_CROSS; + dvp_knode_to(&m_pNodes[2], DVP_Morphology_t)->input = m_images[5]; + dvp_knode_to(&m_pNodes[2], DVP_Morphology_t)->output = m_images[6]; + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + status = CameraInit(this, m_images[0].color); + if (status == STATUS_SUCCESS) + { + if (m_imgdbg_enabled && AllocateImageDebug(3)) + { + ImageDebug_Init(&m_imgdbg[0], &m_images[4], m_imgdbg_path, "01_luma"); + ImageDebug_Init(&m_imgdbg[1], &m_images[5], m_imgdbg_path, "02_edge"); + ImageDebug_Init(&m_imgdbg[2], &m_images[6], m_imgdbg_path, "03_erode"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + DVP_PRINT(DVP_ZONE_ENGINE, "About to process %u frames!\n",m_numFrames); + } + else + return STATUS_NOT_ENOUGH_MEMORY; + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} + +#if 0 // depreciated ... to be removed +status_e TestVisionEngine::SVGA_RVM_GraphSetup() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_RVM) + DVP_Bounds_t bound = {NULL, 0, 0}; + DVP_U32 width = (DVP_U32)(m_width / 2.5); + DVP_U32 height = (DVP_U32)(m_height / 3.75); + + if (m_hDVP) + { + if (AllocateImageStructs(12)) + { + DVP_Image_Init(&m_images[0], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[1], width, height, FOURCC_UYVY); + DVP_Image_Init(&m_images[2], width, height, FOURCC_YV24); + DVP_Image_Init(&m_images[3], width, height, FOURCC_Y800); + DVP_Image_Init(&m_images[4], width, height, FOURCC_RGBP); + DVP_Image_Init(&m_images[5], width, height, FOURCC_Y800); + DVP_Image_Init(&m_images[6], width, height, FOURCC_Y800); + DVP_Image_Init(&m_images[7], width, height, FOURCC_Y800); + DVP_Image_Init(&m_images[8], width, height, FOURCC_Y800); + DVP_Image_Init(&m_images[9], width/2, height/2+m_height/8+m_height/64, FOURCC_Y800); + DVP_Image_Init(&m_images[10],(width-4)/2, (height-3)/2, FOURCC_Y800); + DVP_Image_Init(&m_images[11],(width-4)/2, (height-4)/2, FOURCC_Y800); + if (!DVP_Image_Alloc(m_hDVP, &m_images[0], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[1], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[2], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[3], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[4], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[5], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[6], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[7], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[8], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[9], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[10], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[11], DVP_MTYPE_DEFAULT)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + if (AllocateNodes(10) && AllocateSections(&m_graphs[0], 1)) + { + // initialize the data in the nodes... + m_pNodes[0].header.kernel = DVP_KN_RVM_SUNEX_UYVY; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[1]; + + m_pNodes[1].header.kernel = DVP_KN_UYVY_TO_YUV444p; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->output = m_images[2]; + + m_pNodes[2].header.kernel = DVP_KN_XYXY_TO_Y800; + dvp_knode_to(&m_pNodes[2], DVP_Transform_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[2], DVP_Transform_t)->output = m_images[3]; + + m_pNodes[3].header.kernel = DVP_KN_UYVY_TO_RGBp; + dvp_knode_to(&m_pNodes[3], DVP_Transform_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[3], DVP_Transform_t)->output = m_images[4]; + + m_pNodes[4].header.kernel = DVP_KN_IIR_HORZ; + dvp_knode_to(&m_pNodes[4], DVP_IIR_t)->input = m_images[3]; + dvp_knode_to(&m_pNodes[4], DVP_IIR_t)->output = m_images[6]; + dvp_knode_to(&m_pNodes[4], DVP_IIR_t)->weight = 2000; + dvp_knode_to(&m_pNodes[4], DVP_IIR_t)->bounds[0] = bound; + dvp_knode_to(&m_pNodes[4], DVP_IIR_t)->bounds[1] = bound; + dvp_knode_to(&m_pNodes[4], DVP_IIR_t)->scratch = m_images[5]; + + m_pNodes[5].header.kernel = DVP_KN_IIR_VERT; + dvp_knode_to(&m_pNodes[5], DVP_IIR_t)->input = m_images[3]; + dvp_knode_to(&m_pNodes[5], DVP_IIR_t)->output = m_images[7]; + dvp_knode_to(&m_pNodes[5], DVP_IIR_t)->weight = 2000; + dvp_knode_to(&m_pNodes[5], DVP_IIR_t)->bounds[0] = bound; + dvp_knode_to(&m_pNodes[5], DVP_IIR_t)->bounds[1] = bound; + dvp_knode_to(&m_pNodes[5], DVP_IIR_t)->scratch = m_images[5]; + + m_pNodes[6].header.kernel = DVP_KN_SCHARR_8; + dvp_knode_to(&m_pNodes[6], DVP_Transform_t)->input = m_images[3]; + dvp_knode_to(&m_pNodes[6], DVP_Transform_t)->output = m_images[8]; + + m_pNodes[7].header.kernel = DVP_KN_VLIB_IMAGE_PYRAMID_8; + dvp_knode_to(&m_pNodes[7], DVP_Transform_t)->input = m_images[3]; + dvp_knode_to(&m_pNodes[7], DVP_Transform_t)->output = m_images[9]; + + m_pNodes[8].header.kernel = DVP_KN_VLIB_GRADIENT_V5x5_PYRAMID_8; + dvp_knode_to(&m_pNodes[8], DVP_Gradient_t)->input = m_images[3]; + dvp_knode_to(&m_pNodes[8], DVP_Gradient_t)->output = m_images[10]; + dvp_knode_to(&m_pNodes[8], DVP_Gradient_t)->scratch = m_images[5]; + + m_pNodes[9].header.kernel = DVP_KN_VLIB_GRADIENT_H5x5_PYRAMID_8; + dvp_knode_to(&m_pNodes[9], DVP_Gradient_t)->input = m_images[3]; + dvp_knode_to(&m_pNodes[9], DVP_Gradient_t)->output = m_images[11]; + dvp_knode_to(&m_pNodes[9], DVP_Gradient_t)->scratch = m_images[5]; + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + else + status = STATUS_NO_RESOURCES; + + status = CameraInit(this, m_images[0].color); + if (status == STATUS_SUCCESS) + { + if (m_imgdbg_enabled && AllocateImageDebug(10)) + { + ImageDebug_Init(&m_imgdbg[0], &m_images[1], m_imgdbg_path, "00_rvm"); + ImageDebug_Init(&m_imgdbg[1], &m_images[2], m_imgdbg_path, "01_YUV444"); + ImageDebug_Init(&m_imgdbg[2], &m_images[3], m_imgdbg_path, "02_luma"); + ImageDebug_Init(&m_imgdbg[3], &m_images[4], m_imgdbg_path, "03_RGBpl"); + ImageDebug_Init(&m_imgdbg[4], &m_images[6], m_imgdbg_path, "04_IIRH"); + ImageDebug_Init(&m_imgdbg[5], &m_images[7], m_imgdbg_path, "05_IIRV"); + ImageDebug_Init(&m_imgdbg[6], &m_images[8], m_imgdbg_path, "06_edge"); + ImageDebug_Init(&m_imgdbg[7], &m_images[9], m_imgdbg_path, "07_imgpyramid"); + ImageDebug_Init(&m_imgdbg[8], &m_images[10], m_imgdbg_path, "08_gradv"); + ImageDebug_Init(&m_imgdbg[9], &m_images[11], m_imgdbg_path, "09_gradh"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + DVP_PRINT(DVP_ZONE_ENGINE, "About to process %u frames!\n",m_numFrames); + } + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} +#endif + +status_e TestVisionEngine::Test_MiscGraphSetup() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_VLIB) + DVP_Bounds_t bound = {NULL, 0, 0}; + DVP_MemType_e dispType = DVP_MTYPE_DEFAULT; + + if (m_hDVP) + { + if (AllocateImageStructs(11)) + { + DVP_Image_Init(&m_images[0], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[1], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[2], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[3], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[4], m_width, m_height, FOURCC_YV24); + DVP_Image_Init(&m_images[5], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[6], m_width, m_height, FOURCC_RGBP); + DVP_Image_Init(&m_images[7], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[8], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[9], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[10], m_width, m_height, FOURCC_IYUV); + m_camIdx = m_dispIdx = 0; + m_camMin = m_dispMin = 0; + m_camMax = m_dispMax = 4; + if (m_display_enabled) + { + DisplayCreate(m_width, m_height, m_width, m_height, m_width, m_height, 0, 0); + for (m_dispIdx = m_dispMin; m_dispIdx < m_dispMax; m_dispIdx++) + DisplayAllocate(&m_images[m_dispIdx]); + dispType = (DVP_MemType_e)m_images[m_dispMin].memType; + } +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + else { + dispType = DVP_MTYPE_MPUNONCACHED_2DTILED; + } +#endif + if (!DVP_Image_Alloc(m_hDVP, &m_images[0], dispType) || + !DVP_Image_Alloc(m_hDVP, &m_images[1], dispType) || + !DVP_Image_Alloc(m_hDVP, &m_images[2], dispType) || + !DVP_Image_Alloc(m_hDVP, &m_images[3], dispType) || + !DVP_Image_Alloc(m_hDVP, &m_images[4], DVP_MTYPE_DEFAULT) || +#if defined(DVP_USE_ION) || defined(DVP_USE_TILER) || defined(DVP_USE_BO) + !DVP_Image_Alloc(m_hDVP, &m_images[5], DVP_MTYPE_MPUNONCACHED_2DTILED) || +#else + !DVP_Image_Alloc(m_hDVP, &m_images[5], DVP_MTYPE_DEFAULT) || +#endif + !DVP_Image_Alloc(m_hDVP, &m_images[6], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[7], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[8], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[9], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[10], DVP_MTYPE_DEFAULT)) + return STATUS_NOT_ENOUGH_MEMORY; + // set cache op hints if any of these buffers will not be used on + // the local host for processing (by default the hints always + // indicate to do the operations). + +// m_images[0].skipCacheOpFlush = DVP_TRUE; +// m_images[5].skipCacheOpInval = DVP_TRUE; +// m_images[6].skipCacheOpInval = DVP_TRUE; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + if (AllocateNodes(6) && AllocateSections(&m_graphs[0], 1)) + { + // initialize the data in the nodes... + m_pNodes[0].header.kernel = DVP_KN_UYVY_TO_YUV444p; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = m_images[m_camIdx]; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[4]; + //m_pNodes[0].header.affinity = DVP_CORE_CPU; + + m_pNodes[1].header.kernel = DVP_KN_XYXY_TO_Y800; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = m_images[m_camIdx]; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->output = m_images[5]; + m_pNodes[1].header.affinity = DVP_CORE_DSP; + // m_pNodes[1].header.affinity = DVP_CORE_CPU; + + m_pNodes[2].header.kernel = DVP_KN_UYVY_TO_RGBp; + dvp_knode_to(&m_pNodes[2], DVP_Transform_t)->input = m_images[m_camIdx]; + dvp_knode_to(&m_pNodes[2], DVP_Transform_t)->output = m_images[6]; + //m_pNodes[2].header.affinity = DVP_CORE_CPU; + + m_pNodes[3].header.kernel = DVP_KN_IIR_HORZ; + dvp_knode_to(&m_pNodes[3], DVP_IIR_t)->input = m_images[5]; + dvp_knode_to(&m_pNodes[3], DVP_IIR_t)->output = m_images[7]; + dvp_knode_to(&m_pNodes[3], DVP_IIR_t)->weight = 2000; + dvp_knode_to(&m_pNodes[3], DVP_IIR_t)->bounds[0] = bound; + dvp_knode_to(&m_pNodes[3], DVP_IIR_t)->bounds[1] = bound; + dvp_knode_to(&m_pNodes[3], DVP_IIR_t)->scratch = m_images[8]; + //m_pNodes[3].header.affinity = DVP_CORE_CPU; + + m_pNodes[4].header.kernel = DVP_KN_IIR_VERT; + dvp_knode_to(&m_pNodes[4], DVP_IIR_t)->input = m_images[5]; + dvp_knode_to(&m_pNodes[4], DVP_IIR_t)->output = m_images[9]; + dvp_knode_to(&m_pNodes[4], DVP_IIR_t)->weight = 2000; + dvp_knode_to(&m_pNodes[4], DVP_IIR_t)->bounds[0] = bound; + dvp_knode_to(&m_pNodes[4], DVP_IIR_t)->bounds[1] = bound; + dvp_knode_to(&m_pNodes[4], DVP_IIR_t)->scratch = m_images[8]; + //m_pNodes[4].header.affinity = DVP_CORE_CPU; + + m_pNodes[5].header.kernel = DVP_KN_UYVY_TO_YUV420p; + dvp_knode_to(&m_pNodes[5], DVP_Transform_t)->input = m_images[m_camIdx]; + dvp_knode_to(&m_pNodes[5], DVP_Transform_t)->output = m_images[10]; + //m_pNodes[5].header.affinity = DVP_CORE_CPU; + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + status = CameraInit(this, m_images[0].color); + if (status == STATUS_SUCCESS) + { + if (m_imgdbg_enabled && AllocateImageDebug(6)) + { + ImageDebug_Init(&m_imgdbg[0], &m_images[4], m_imgdbg_path, "00_YUV444"); + ImageDebug_Init(&m_imgdbg[1], &m_images[5], m_imgdbg_path, "01_luma"); + ImageDebug_Init(&m_imgdbg[2], &m_images[6], m_imgdbg_path, "02_RGBpl"); + ImageDebug_Init(&m_imgdbg[3], &m_images[7], m_imgdbg_path, "03_IIRH"); + ImageDebug_Init(&m_imgdbg[4], &m_images[9], m_imgdbg_path, "04_IIRV"); + ImageDebug_Init(&m_imgdbg[5], &m_images[10], m_imgdbg_path, "05_YUV420"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + DVP_PRINT(DVP_ZONE_ENGINE, "About to process %u frames!\n",m_numFrames); + } + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} + +status_e TestVisionEngine::Test_MorphGraphSetup() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_VLIB) + DVP_S08 maskOnes[3][3] = {{1,1,1},{1,1,1},{1,1,1}}; + DVP_MemType_e camType = DVP_MTYPE_DEFAULT; + DVP_MemType_e opType = DVP_MTYPE_DEFAULT; + DVP_MemType_e smallType = DVP_MTYPE_MPUCACHED_VIRTUAL; + +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + camType = DVP_MTYPE_MPUNONCACHED_2DTILED; + opType = DVP_MTYPE_MPUNONCACHED_1DTILED; + smallType = DVP_MTYPE_MPUNONCACHED_1DTILED; +#endif + + if (m_hDVP) + { + if (AllocateImageStructs(10)) + { + DVP_Image_Init(&m_images[0], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[1], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[2], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[3], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[4], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[5], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[6], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[7], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[8], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[9], 3, 3, FOURCC_Y800); + if (!DVP_Image_Alloc(m_hDVP, &m_images[0], camType) || + !DVP_Image_Alloc(m_hDVP, &m_images[1], opType) || // DEFAULT is 1DTILED when using TILER + !DVP_Image_Alloc(m_hDVP, &m_images[2], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[3], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[4], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[5], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[6], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[7], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[8], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[9], smallType)) // Mask can be in virtual space since it is copied + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + if (AllocateNodes(8) && AllocateSections(&m_graphs[0], 1)) + { + // initialize the data in the nodes... + m_pNodes[0].header.kernel = DVP_KN_XYXY_TO_Y800; // Get Luma first + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[1]; + //m_pNodes[0].header.affinity = DVP_CORE_CPU; + + m_pNodes[1].header.kernel = DVP_KN_THRESHOLD; // Then threshold for binary image functions + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = m_images[1]; // Using Luma from Luma Extract function + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->output = m_images[2]; // Thresholded output + //m_pNodes[1].header.affinity = DVP_CORE_CPU; + + m_pNodes[2].header.kernel = DVP_KN_ERODE_CROSS; + dvp_knode_to(&m_pNodes[2], DVP_Morphology_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[2], DVP_Morphology_t)->output = m_images[3]; + //m_pNodes[2].header.affinity = DVP_CORE_CPU; + + m_pNodes[3].header.kernel = DVP_KN_ERODE_SQUARE; + dvp_knode_to(&m_pNodes[3], DVP_Morphology_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[3], DVP_Morphology_t)->output = m_images[4]; + //m_pNodes[3].header.affinity = DVP_CORE_CPU; + + m_pNodes[4].header.kernel = DVP_KN_ERODE_MASK; + dvp_knode_to(&m_pNodes[4], DVP_Morphology_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[4], DVP_Morphology_t)->output = m_images[5]; + dvp_knode_to(&m_pNodes[4], DVP_Morphology_t)->mask = m_images[9]; + //m_pNodes[4].header.affinity = DVP_CORE_CPU; + + m_pNodes[5].header.kernel = DVP_KN_DILATE_CROSS; + dvp_knode_to(&m_pNodes[5], DVP_Morphology_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[5], DVP_Morphology_t)->output = m_images[6]; + //m_pNodes[5].header.affinity = DVP_CORE_CPU; + + m_pNodes[6].header.kernel = DVP_KN_DILATE_SQUARE; + dvp_knode_to(&m_pNodes[6], DVP_Morphology_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[6], DVP_Morphology_t)->output = m_images[7]; + //m_pNodes[6].header.affinity = DVP_CORE_CPU; + + m_pNodes[7].header.kernel = DVP_KN_DILATE_MASK; + dvp_knode_to(&m_pNodes[7], DVP_Morphology_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[7], DVP_Morphology_t)->output = m_images[8]; + dvp_knode_to(&m_pNodes[7], DVP_Morphology_t)->mask = m_images[9]; + //m_pNodes[7].header.affinity = DVP_CORE_CPU; + + DVP_Image_Fill(&m_images[9], (DVP_S08 *)maskOnes, 3*3*sizeof(DVP_S08)); // Setting the mask to be a square (all 1s) + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + status = CameraInit(this, m_images[0].color); + if (status == STATUS_SUCCESS) + { + if (m_imgdbg_enabled && AllocateImageDebug(9)) + { + ImageDebug_Init(&m_imgdbg[0], &m_images[0], m_imgdbg_path, "00_input"); + ImageDebug_Init(&m_imgdbg[1], &m_images[1], m_imgdbg_path, "01_luma"); + ImageDebug_Init(&m_imgdbg[2], &m_images[2], m_imgdbg_path, "02_bitimgThresh"); + ImageDebug_Init(&m_imgdbg[3], &m_images[3], m_imgdbg_path, "03_bitimgErodeX"); + ImageDebug_Init(&m_imgdbg[4], &m_images[4], m_imgdbg_path, "04_bitimgErodeSq"); + ImageDebug_Init(&m_imgdbg[5], &m_images[5], m_imgdbg_path, "05_bitimgErodeMsk"); + ImageDebug_Init(&m_imgdbg[6], &m_images[6], m_imgdbg_path, "06_bitimgDilateX"); + ImageDebug_Init(&m_imgdbg[7], &m_images[7], m_imgdbg_path, "07_bitimgDilateSq"); + ImageDebug_Init(&m_imgdbg[8], &m_images[8], m_imgdbg_path, "08_bitimgDilateMsk"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + DVP_PRINT(DVP_ZONE_ENGINE, "About to process %u frames!\n",m_numFrames); + } + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} + +status_e TestVisionEngine::Test_NonmaxImgconvGraphSetup() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_VLIB) && defined(DVP_USE_IMGLIB) + DVP_MemType_e camType = DVP_MTYPE_DEFAULT; + DVP_MemType_e opType = DVP_MTYPE_DEFAULT; + DVP_MemType_e smallType = DVP_MTYPE_MPUCACHED_VIRTUAL; + +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + camType = DVP_MTYPE_MPUNONCACHED_2DTILED; + opType = DVP_MTYPE_MPUNONCACHED_1DTILED; + smallType = DVP_MTYPE_MPUNONCACHED_1DTILED; +#endif + + DVP_S08 maskBlurNeg3x3[3][3] = {{-5, 20, 17} , + {19, -28, 13} , + {-22, 9, 33}}; + DVP_S08 maskBlur7x7[7][7] = {{5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5}}; + if (m_hDVP) + { + if (AllocateImageStructs(12)) + { + DVP_Image_Init(&m_images[0], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[1], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[2], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[3], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[4], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[5], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[6], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[7], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[8], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[9], 3, 3, FOURCC_Y800); + DVP_Image_Init(&m_images[10], 5, 5, FOURCC_Y800); + DVP_Image_Init(&m_images[11], 7, 7, FOURCC_Y800); + if (!DVP_Image_Alloc(m_hDVP, &m_images[0], camType) || + !DVP_Image_Alloc(m_hDVP, &m_images[1], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[2], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[3], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[4], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[5], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[6], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[7], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[8], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[9], smallType) || // Mask can be in virtual space since it is copied + !DVP_Image_Alloc(m_hDVP, &m_images[10], smallType) || // Mask can be in virtual space since it is copied + !DVP_Image_Alloc(m_hDVP, &m_images[11], smallType)) // Mask can be in virtual space since it is copied + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + if (AllocateNodes(8) && AllocateSections(&m_graphs[0], 1)) + { + // initialize the data in the nodes... + m_pNodes[0].header.kernel = DVP_KN_XYXY_TO_Y800; // Get Luma first + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[1]; + //m_pNodes[0].header.affinity = DVP_CORE_CPU; + + m_pNodes[1].header.kernel = DVP_KN_XSTRIDE_CONVERT; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->output = m_images[2]; + //m_pNodes[1].header.affinity = DVP_CORE_CPU; + + m_pNodes[2].header.kernel = DVP_KN_VLIB_NONMAXSUPPRESS_3x3_S16; + dvp_knode_to(&m_pNodes[2], DVP_Threshold_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[2], DVP_Threshold_t)->output = m_images[3]; + dvp_knode_to(&m_pNodes[2], DVP_Threshold_t)->thresh = 100; + if (dvp_knode_to(&m_pNodes[2], DVP_Threshold_t)->input.width > 992) + m_pNodes[2].header.affinity = DVP_CORE_CPU; + + m_pNodes[3].header.kernel = DVP_KN_VLIB_NONMAXSUPPRESS_5x5_S16; + dvp_knode_to(&m_pNodes[3], DVP_Threshold_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[3], DVP_Threshold_t)->output = m_images[4]; + dvp_knode_to(&m_pNodes[3], DVP_Threshold_t)->thresh = 100; + if (dvp_knode_to(&m_pNodes[3], DVP_Threshold_t)->input.width > 992) + m_pNodes[3].header.affinity = DVP_CORE_CPU; + + m_pNodes[4].header.kernel = DVP_KN_VLIB_NONMAXSUPPRESS_7x7_S16; + dvp_knode_to(&m_pNodes[4], DVP_Threshold_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[4], DVP_Threshold_t)->output = m_images[5]; + dvp_knode_to(&m_pNodes[4], DVP_Threshold_t)->thresh = 100; + if(dvp_knode_to(&m_pNodes[4], DVP_Threshold_t)->input.width > 768) + m_pNodes[4].header.affinity = DVP_CORE_CPU; + + m_pNodes[5].header.kernel = DVP_KN_IMG_CONV_3x3; + dvp_knode_to(&m_pNodes[5], DVP_ImageConvolution_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[5], DVP_ImageConvolution_t)->output = m_images[6]; + dvp_knode_to(&m_pNodes[5], DVP_ImageConvolution_t)->mask = m_images[9]; + dvp_knode_to(&m_pNodes[5], DVP_ImageConvolution_t)->shiftMask = 6; + //m_pNodes[5].header.affinity = DVP_CORE_CPU; + + m_pNodes[6].header.kernel = DVP_KN_IMG_CONV_5x5; + dvp_knode_to(&m_pNodes[6], DVP_ImageConvolution_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[6], DVP_ImageConvolution_t)->output = m_images[7]; + dvp_knode_to(&m_pNodes[6], DVP_ImageConvolution_t)->mask = m_images[10]; + dvp_knode_to(&m_pNodes[6], DVP_ImageConvolution_t)->shiftMask = 7; + //m_pNodes[6].header.affinity = DVP_CORE_CPU; + + m_pNodes[7].header.kernel = DVP_KN_IMG_CONV_7x7; + dvp_knode_to(&m_pNodes[7], DVP_ImageConvolution_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[7], DVP_ImageConvolution_t)->output = m_images[8]; + dvp_knode_to(&m_pNodes[7], DVP_ImageConvolution_t)->mask = m_images[11]; + dvp_knode_to(&m_pNodes[7], DVP_ImageConvolution_t)->shiftMask = 8; + //m_pNodes[7].header.affinity = DVP_CORE_CPU; + + DVP_Image_Fill(&m_images[9], (DVP_S08*)maskBlurNeg3x3, 3*3*sizeof(DVP_S08)); + DVP_Image_Fill(&m_images[10], (DVP_S08*)maskBlur7x7, 5*5*sizeof(DVP_S08)); + DVP_Image_Fill(&m_images[11], (DVP_S08*)maskBlur7x7, 7*7*sizeof(DVP_S08)); + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + + } + status = CameraInit(this, m_images[0].color); + if (status == STATUS_SUCCESS) + { + if (m_imgdbg_enabled && AllocateImageDebug(9)) + { + ImageDebug_Init(&m_imgdbg[0], &m_images[0], m_imgdbg_path, "00_input"); + ImageDebug_Init(&m_imgdbg[1], &m_images[1], m_imgdbg_path, "01_luma"); + ImageDebug_Init(&m_imgdbg[2], &m_images[2], m_imgdbg_path, "02_16bitStride"); + ImageDebug_Init(&m_imgdbg[3], &m_images[3], m_imgdbg_path, "03_nonma3"); + ImageDebug_Init(&m_imgdbg[4], &m_images[4], m_imgdbg_path, "04_nonma5"); + ImageDebug_Init(&m_imgdbg[5], &m_images[5], m_imgdbg_path, "05_nonma7"); + ImageDebug_Init(&m_imgdbg[6], &m_images[6], m_imgdbg_path, "06_imgconv3"); + ImageDebug_Init(&m_imgdbg[7], &m_images[7], m_imgdbg_path, "07_imgconv5"); + ImageDebug_Init(&m_imgdbg[8], &m_images[8], m_imgdbg_path, "08_imgconv7"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + DVP_PRINT(DVP_ZONE_ENGINE, "About to process %u frames!\n",m_numFrames); + } + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} + +status_e TestVisionEngine::Test_CannyGraphSetup() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_VLIB) && defined(DVP_USE_IMGLIB) + DVP_MemType_e camType = DVP_MTYPE_DEFAULT; + DVP_MemType_e opType = DVP_MTYPE_DEFAULT; + DVP_MemType_e smallType = DVP_MTYPE_MPUCACHED_VIRTUAL; + +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + camType = DVP_MTYPE_MPUNONCACHED_2DTILED; + opType = DVP_MTYPE_MPUNONCACHED_1DTILED; + smallType = DVP_MTYPE_MPUNONCACHED_1DTILED; +#endif + + // 3x3 Gaussian kernel with SQ0.8 coefficients + const DVP_S08 gaussian_7x7[49] = + { + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 16, 32, 16, 0, 0, + 0, 0, 32, 64, 32, 0, 0, + 0, 0, 16, 32, 16, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 + }; + + if (m_hDVP) + { + if (AllocateImageStructs(12)) + { + DVP_Image_Init(&m_images[0], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[1], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[2], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[3], 7, 7, FOURCC_Y800); + DVP_Image_Init(&m_images[4], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[5], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[6], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[7], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[8], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[9], m_width, m_height, FOURCC_RGBA); + DVP_Image_Init(&m_images[10], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[11], m_width, m_height, FOURCC_Y800); + if (!DVP_Image_Alloc(m_hDVP, &m_images[0], camType) || + !DVP_Image_Alloc(m_hDVP, &m_images[1], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[2], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[3], smallType) || // Mask can be in virtual space since it is copied + !DVP_Image_Alloc(m_hDVP, &m_images[4], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[5], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[6], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[7], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[8], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[9], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[10], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[11], opType)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + if (AllocateNodes(8) && AllocateSections(&m_graphs[0], 1)) + { + // initialize the data in the nodes... + m_pNodes[0].header.kernel = DVP_KN_XYXY_TO_Y800; // Get Luma first + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[1]; + //m_pNodes[0].header.affinity = DVP_CORE_CPU; + + m_pNodes[1].header.kernel = DVP_KN_CANNY_IMAGE_SMOOTHING; + dvp_knode_to(&m_pNodes[1], DVP_ImageConvolution_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[1], DVP_ImageConvolution_t)->output = m_images[2]; + dvp_knode_to(&m_pNodes[1], DVP_ImageConvolution_t)->mask = m_images[3]; + dvp_knode_to(&m_pNodes[1], DVP_ImageConvolution_t)->shiftMask = 8; + //m_pNodes[1].header.affinity = DVP_CORE_CPU; + + m_pNodes[2].header.kernel = DVP_KN_CANNY_2D_GRADIENT; + dvp_knode_to(&m_pNodes[2], DVP_Canny2dGradient_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[2], DVP_Canny2dGradient_t)->outGradX = m_images[4]; + dvp_knode_to(&m_pNodes[2], DVP_Canny2dGradient_t)->outGradY = m_images[5]; + dvp_knode_to(&m_pNodes[2], DVP_Canny2dGradient_t)->outMag = m_images[6]; + //m_pNodes[2].header.affinity = DVP_CORE_CPU; + + m_pNodes[3].header.kernel = DVP_KN_CANNY_NONMAX_SUPPRESSION; + dvp_knode_to(&m_pNodes[3], DVP_CannyNonMaxSuppression_t)->inGradX = m_images[4]; + dvp_knode_to(&m_pNodes[3], DVP_CannyNonMaxSuppression_t)->inGradY = m_images[5]; + dvp_knode_to(&m_pNodes[3], DVP_CannyNonMaxSuppression_t)->inMag = m_images[6]; + dvp_knode_to(&m_pNodes[3], DVP_CannyNonMaxSuppression_t)->output = m_images[7]; + // m_pNodes[3].header.affinity = DVP_CORE_DSP; + + m_pNodes[4].header.kernel = DVP_KN_CANNY_HYST_THRESHHOLD; + dvp_knode_to(&m_pNodes[4], DVP_CannyHystThresholding_t)->inMag = m_images[6]; + dvp_knode_to(&m_pNodes[4], DVP_CannyHystThresholding_t)->inEdgeMap = m_images[7]; + dvp_knode_to(&m_pNodes[4], DVP_CannyHystThresholding_t)->output = m_images[8]; + dvp_knode_to(&m_pNodes[4], DVP_CannyHystThresholding_t)->loThresh = 35; + dvp_knode_to(&m_pNodes[4], DVP_CannyHystThresholding_t)->hiThresh = 122; + //m_pNodes[4].header.affinity = DVP_CORE_CPU; + + m_pNodes[5].header.kernel = DVP_KN_INTEGRAL_IMAGE_8; + dvp_knode_to(&m_pNodes[5], DVP_Transform_t)->input = m_images[8]; + dvp_knode_to(&m_pNodes[5], DVP_Transform_t)->output = m_images[9]; + if(dvp_knode_to(&m_pNodes[5], DVP_Transform_t)->input.width> 2049 ||dvp_knode_to(&m_pNodes[5], DVP_Transform_t)->input.height> 819 ) + m_pNodes[5].header.affinity = DVP_CORE_CPU; + + m_pNodes[6].header.kernel = DVP_KN_IMG_THR_LE2MIN_8; + dvp_knode_to(&m_pNodes[6], DVP_Threshold_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[6], DVP_Threshold_t)->output = m_images[10]; + dvp_knode_to(&m_pNodes[6], DVP_Threshold_t)->thresh = 100; + //m_pNodes[6].header.affinity = DVP_CORE_CPU; + + m_pNodes[7].header.kernel = DVP_KN_VLIB_CCL; + dvp_knode_to(&m_pNodes[7], DVP_CCL_t)->input = m_images[8]; + dvp_knode_to(&m_pNodes[7], DVP_CCL_t)->output = m_images[11]; + dvp_knode_to(&m_pNodes[7], DVP_CCL_t)->minBlobAreaInPixels = 7; + dvp_knode_to(&m_pNodes[7], DVP_CCL_t)->connected8Flag = DVP_CCL_8_CONNECTED; + dvp_knode_to(&m_pNodes[7], DVP_CCL_t)->numCCs= 0; // Initialize to 0 + //m_pNodes[7].header.affinity = DVP_CORE_CPU; + + DVP_Image_Fill(&m_images[3], (DVP_S08*)gaussian_7x7, 7*7*sizeof(DVP_S08)); // Copying the mask + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + status = CameraInit(this, m_images[0].color); + if (status == STATUS_SUCCESS) + { + if (m_imgdbg_enabled && AllocateImageDebug(11)) + { + ImageDebug_Init(&m_imgdbg[0], &m_images[0], m_imgdbg_path, "00_inputCanny"); + ImageDebug_Init(&m_imgdbg[1], &m_images[1], m_imgdbg_path, "01_lumaCanny"); + ImageDebug_Init(&m_imgdbg[2], &m_images[2], m_imgdbg_path, "02_cannySmooth"); + ImageDebug_Init(&m_imgdbg[3], &m_images[4], m_imgdbg_path, "03_canny2dgradX"); + ImageDebug_Init(&m_imgdbg[4], &m_images[5], m_imgdbg_path, "04_canny2dgradY"); + ImageDebug_Init(&m_imgdbg[5], &m_images[6], m_imgdbg_path, "05_canny2dmag"); + ImageDebug_Init(&m_imgdbg[6], &m_images[7], m_imgdbg_path, "06_cannyNonma"); + ImageDebug_Init(&m_imgdbg[7], &m_images[8], m_imgdbg_path, "07_dThresh"); + ImageDebug_Init(&m_imgdbg[8], &m_images[9], m_imgdbg_path, "08_intImg"); + ImageDebug_Init(&m_imgdbg[9], &m_images[10], m_imgdbg_path, "09_thresh"); + ImageDebug_Init(&m_imgdbg[10], &m_images[11], m_imgdbg_path, "10_ccl"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + + DVP_PRINT(DVP_ZONE_ENGINE, "About to process %u frames!\n",m_numFrames); + } + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} + +status_e TestVisionEngine::Test_SimcopGraphSetup() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_VLIB) && defined(DVP_USE_IMGLIB) + DVP_Image_t tmpImages[3]; + DVP_Bounds_t bound = {NULL, 0, 0}; + DVP_S08 maskOnes[3][3] = {{1,1,1},{1,1,1},{1,1,1}}; + DVP_S08 maskBlurNeg3x3[3][3] = {{-5, 20, 17} , + {19, -28, 13} , + {-22, 9, 33}}; + DVP_S08 maskBlur7x7[7][7] = {{5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5}}; + // 3x3 Gaussian kernel with SQ0.8 coefficients + const DVP_S08 gaussian_7x7[49] = + { + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 16, 32, 16, 0, 0, + 0, 0, 32, 64, 32, 0, 0, + 0, 0, 16, 32, 16, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 + }; + DVP_S08 maskAvg[7] = {1,2,3,4,3,2,1}; + DVP_MemType_e camType = DVP_MTYPE_DEFAULT; + DVP_MemType_e smallType = DVP_MTYPE_MPUCACHED_VIRTUAL; + +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + camType = DVP_MTYPE_MPUNONCACHED_2DTILED; + smallType = DVP_MTYPE_MPUNONCACHED_1DTILED; +#endif + if (m_hDVP) + { + if (AllocateImageStructs(75)) + { + /** **/ + DVP_Image_Init(&m_images[0], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[1], m_width, m_height, FOURCC_YV24); + DVP_Image_Init(&tmpImages[0], m_width, ((m_height-1)/16+1)*16, FOURCC_Y800); // Height needs to be divisible by 16 for Sobel and multineighbor + DVP_Image_Init(&tmpImages[1], m_width, ((m_height-1)/16+1)*16, FOURCC_Y800); + DVP_Image_Init(&tmpImages[2], m_width, ((m_height-1)/16+1)*16, FOURCC_Y800); + DVP_Image_Init(&m_images[2], m_width, ((m_height-1)/16+1)*16, FOURCC_Y800); + DVP_Image_Init(&m_images[3], m_width, ((m_height-1)/16+1)*16, FOURCC_Y800); + DVP_Image_Init(&m_images[4], m_width, ((m_height-1)/16+1)*16, FOURCC_Y800); + DVP_Image_Init(&m_images[5], ((m_height-1)/16+1)*16, m_width, FOURCC_Y800); // Height/width transposed + DVP_Image_Init(&m_images[6], m_width, ((m_height-1)/16+1)*16, FOURCC_Y800); + DVP_Image_Init(&m_images[7], ((m_height-1)/16+1)*16, m_width, FOURCC_Y800); // Height/width transposed + /** Misc**/ + DVP_Image_Init(&m_images[8], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[9], m_width, m_height, FOURCC_RGBP); + DVP_Image_Init(&m_images[10], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[11], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[12], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[13], m_width, m_height, FOURCC_IYUV); + /** Morph**/ + DVP_Image_Init(&m_images[14], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[15], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[16], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[17], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[18], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[19], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[20], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[21], 3, 3, FOURCC_Y800); + /** NonMax**/ + DVP_Image_Init(&m_images[22], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[23], m_width, m_height+2, FOURCC_Y800); + DVP_Image_Init(&m_images[24], m_width, m_height+4, FOURCC_Y800); + DVP_Image_Init(&m_images[25], m_width, m_height+6, FOURCC_Y800); + DVP_Image_Init(&m_images[26], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[27], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[28], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[29], 3, 3, FOURCC_Y800); + DVP_Image_Init(&m_images[30], 5, 5, FOURCC_Y800); + DVP_Image_Init(&m_images[31], 7, 7, FOURCC_Y800); + /** Canny**/ + DVP_Image_Init(&m_images[32], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[33], 7, 7, FOURCC_Y800); + DVP_Image_Init(&m_images[34], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[35], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[36], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[37], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[38], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[39], m_width, m_height, FOURCC_RGBA); + DVP_Image_Init(&m_images[40], m_width, m_height, FOURCC_Y800); + /** New **/ + DVP_Image_Init(&m_images[41], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[42], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[43], 7, 1, FOURCC_Y800); + DVP_Image_Init(&m_images[44], 1, 7, FOURCC_Y800); + DVP_Image_Init(&m_images[45], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[46], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[47], m_width, ((m_height-1)/16+1)*16, FOURCC_Y16); + DVP_Image_Init(&m_images[48], m_width, ((m_height-1)/16+1)*16, FOURCC_Y16); + DVP_Image_Init(&m_images[49], m_width, ((m_height-1)/16+1)*16, FOURCC_Y800); + DVP_Image_Init(&m_images[50], ((m_height-1)/16+1)*16, m_width, FOURCC_Y800); // Height/width transposed + DVP_Image_Init(&m_images[51], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[52], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[53], m_width, m_height, FOURCC_RGBP); + /** Imglib **/ + DVP_Image_Init(&m_images[54], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[55], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[56], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[57], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[58], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[59], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[60], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[61], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[62], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[63], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[64], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[65], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[66], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[67], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[68], m_width, m_height, FOURCC_Y800); + if(m_width<1280) + { + DVP_Image_Init(&m_images[69], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[70], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[71], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[72], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[73], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[74], m_width, m_height, FOURCC_Y16); + } + /** Misc**/ + if (!DVP_Image_Alloc(m_hDVP, &m_images[0], camType) || + !DVP_Image_Alloc(m_hDVP, &m_images[1], DVP_MTYPE_DEFAULT) || + //Skipping tmpImages since they are fields that are already allocated in [1] + !DVP_Image_Alloc(m_hDVP, &m_images[2], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[3], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[4], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[5], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[6], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[7], DVP_MTYPE_DEFAULT) || + /** Misc **/ +#if defined(DVP_USE_ION) || defined(DVP_USE_TILER) || defined(DVP_USE_BO) + !DVP_Image_Alloc(m_hDVP, &m_images[8], DVP_MTYPE_MPUNONCACHED_2DTILED) || +#else + !DVP_Image_Alloc(m_hDVP, &m_images[8], DVP_MTYPE_DEFAULT) || +#endif + !DVP_Image_Alloc(m_hDVP, &m_images[9], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[10], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[11], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[12], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[13], DVP_MTYPE_DEFAULT) || + /** Morph**/ + !DVP_Image_Alloc(m_hDVP, &m_images[14], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[15], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[16], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[17], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[18], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[19], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[20], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[21], smallType) || // Mask can be in virtual space since it is copied + /** NonMax**/ + !DVP_Image_Alloc(m_hDVP, &m_images[22], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[23], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[24], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[25], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[26], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[27], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[28], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[29], smallType) || // Mask can be in virtual space since it is copied + !DVP_Image_Alloc(m_hDVP, &m_images[30], smallType) || // Mask can be in virtual space since it is copied + !DVP_Image_Alloc(m_hDVP, &m_images[31], smallType) || // Mask can be in virtual space since it is copied + /** Canny**/ + !DVP_Image_Alloc(m_hDVP, &m_images[32], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[33], smallType) || // Mask can be in virtual space since it is copied + !DVP_Image_Alloc(m_hDVP, &m_images[34], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[35], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[36], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[37], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[38], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[39], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[40], DVP_MTYPE_DEFAULT) || + /** New Requests**/ + !DVP_Image_Alloc(m_hDVP, &m_images[41], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[42], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[43], smallType) || + !DVP_Image_Alloc(m_hDVP, &m_images[44], smallType) || + !DVP_Image_Alloc(m_hDVP, &m_images[45], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[46], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[47], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[48], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[49], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[50], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[51], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[52], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[53], DVP_MTYPE_DEFAULT) || + /** Imglib **/ + !DVP_Image_Alloc(m_hDVP, &m_images[54], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[55], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[56], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[57], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[58], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[59], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[60], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[61], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[62], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[63], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[64], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[65], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[66], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[67], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[68], DVP_MTYPE_DEFAULT)) + return STATUS_NOT_ENOUGH_MEMORY; + + if(m_width<1280) + if(!DVP_Image_Alloc(m_hDVP, &m_images[69], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[70], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[71], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[72], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[73], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[74], DVP_MTYPE_DEFAULT)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + if (AllocateNodes(56) && AllocateSections(&m_graphs[0], 1)) + { + /********* + Misc + **********/ + // initialize the data in the nodes... + m_pNodes[0].header.kernel = DVP_KN_UYVY_TO_YUV444p; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[1]; + + tmpImages[0].pBuffer[0] = m_images[1].pBuffer[0]; // Using Luma from YUV444p function + tmpImages[0].pData[0] = m_images[1].pData[0]; // Using Luma from YUV444p function + tmpImages[0].y_stride = m_images[1].y_stride; + tmpImages[0].memType = m_images[1].memType; + + tmpImages[1].pBuffer[0] = m_images[1].pBuffer[1]; // Using Chroma from YUV444p function + tmpImages[1].pData[0] = m_images[1].pData[1]; // Using Chroma from YUV444p function + tmpImages[1].y_stride = m_images[1].y_stride; + tmpImages[1].memType = m_images[1].memType; + + tmpImages[2].pBuffer[0] = m_images[1].pBuffer[2]; // Using Chroma from YUV444p function + tmpImages[2].pData[0] = m_images[1].pData[2]; // Using Chroma from YUV444p function + tmpImages[2].y_stride = m_images[1].y_stride; + tmpImages[2].memType = m_images[1].memType; + + m_pNodes[1].header.kernel = DVP_KN_NOOP; + m_pNodes[2].header.kernel = DVP_KN_NOOP; + + /********* + + **********/ + m_pNodes[3].header.kernel = DVP_KN_XYXY_TO_Y800; + dvp_knode_to(&m_pNodes[3], DVP_Transform_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[3], DVP_Transform_t)->output = m_images[8]; + + m_pNodes[4].header.kernel = DVP_KN_UYVY_TO_RGBp; + dvp_knode_to(&m_pNodes[4], DVP_Transform_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[4], DVP_Transform_t)->output = m_images[9]; + + m_pNodes[5].header.kernel = DVP_KN_IIR_HORZ; + dvp_knode_to(&m_pNodes[5], DVP_IIR_t)->input = m_images[8]; + dvp_knode_to(&m_pNodes[5], DVP_IIR_t)->output = m_images[10]; + dvp_knode_to(&m_pNodes[5], DVP_IIR_t)->weight = 2000; + dvp_knode_to(&m_pNodes[5], DVP_IIR_t)->bounds[0] = bound; + dvp_knode_to(&m_pNodes[5], DVP_IIR_t)->bounds[1] = bound; + dvp_knode_to(&m_pNodes[5], DVP_IIR_t)->scratch = m_images[11]; + + m_pNodes[6].header.kernel = DVP_KN_IIR_VERT; + dvp_knode_to(&m_pNodes[6], DVP_IIR_t)->input = m_images[8]; + dvp_knode_to(&m_pNodes[6], DVP_IIR_t)->output = m_images[12]; + dvp_knode_to(&m_pNodes[6], DVP_IIR_t)->weight = 2000; + dvp_knode_to(&m_pNodes[6], DVP_IIR_t)->bounds[0] = bound; + dvp_knode_to(&m_pNodes[6], DVP_IIR_t)->bounds[1] = bound; + dvp_knode_to(&m_pNodes[6], DVP_IIR_t)->scratch = m_images[11]; + + m_pNodes[7].header.kernel = DVP_KN_UYVY_TO_YUV420p; + dvp_knode_to(&m_pNodes[7], DVP_Transform_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[7], DVP_Transform_t)->output = m_images[13]; + + /********* + Morph + **********/ + m_pNodes[8].header.kernel = DVP_KN_THRESHOLD; // Then threshold for binary image functions + dvp_knode_to(&m_pNodes[8], DVP_Transform_t)->input = m_images[8]; // Using Luma from Luma Extract function + dvp_knode_to(&m_pNodes[8], DVP_Transform_t)->output = m_images[14]; // Thresholded output + + m_pNodes[9].header.kernel = DVP_KN_ERODE_CROSS; + dvp_knode_to(&m_pNodes[9], DVP_Morphology_t)->input = m_images[14]; + dvp_knode_to(&m_pNodes[9], DVP_Morphology_t)->output = m_images[15]; + + m_pNodes[10].header.kernel = DVP_KN_ERODE_SQUARE; + dvp_knode_to(&m_pNodes[10], DVP_Morphology_t)->input = m_images[14]; + dvp_knode_to(&m_pNodes[10], DVP_Morphology_t)->output = m_images[16]; + + m_pNodes[11].header.kernel = DVP_KN_ERODE_MASK; + dvp_knode_to(&m_pNodes[11], DVP_Morphology_t)->input = m_images[14]; + dvp_knode_to(&m_pNodes[11], DVP_Morphology_t)->output = m_images[17]; + dvp_knode_to(&m_pNodes[11], DVP_Morphology_t)->mask = m_images[21]; + + m_pNodes[12].header.kernel = DVP_KN_DILATE_CROSS; + dvp_knode_to(&m_pNodes[12], DVP_Morphology_t)->input = m_images[14]; + dvp_knode_to(&m_pNodes[12], DVP_Morphology_t)->output = m_images[18]; + + m_pNodes[13].header.kernel = DVP_KN_DILATE_SQUARE; + dvp_knode_to(&m_pNodes[13], DVP_Morphology_t)->input = m_images[14]; + dvp_knode_to(&m_pNodes[13], DVP_Morphology_t)->output = m_images[19]; + + m_pNodes[14].header.kernel = DVP_KN_DILATE_MASK; + dvp_knode_to(&m_pNodes[14], DVP_Morphology_t)->input = m_images[14]; + dvp_knode_to(&m_pNodes[14], DVP_Morphology_t)->output = m_images[20]; + dvp_knode_to(&m_pNodes[14], DVP_Morphology_t)->mask = m_images[21]; + + DVP_Image_Fill(&m_images[21], (DVP_S08 *)maskOnes, 3*3*sizeof(DVP_S08)); // Setting the mask to be a square (all 1s) + + /********* + NonMax + **********/ + m_pNodes[15].header.kernel = DVP_KN_XSTRIDE_CONVERT; + dvp_knode_to(&m_pNodes[15], DVP_Transform_t)->input = m_images[8]; + dvp_knode_to(&m_pNodes[15], DVP_Transform_t)->output = m_images[22]; + + m_pNodes[16].header.kernel = DVP_KN_NONMAXSUPPRESS_3x3_S16; + dvp_knode_to(&m_pNodes[16], DVP_Threshold_t)->input = m_images[22]; + dvp_knode_to(&m_pNodes[16], DVP_Threshold_t)->output = m_images[23]; + dvp_knode_to(&m_pNodes[16], DVP_Threshold_t)->thresh = 100; + if(dvp_knode_to(&m_pNodes[16], DVP_Threshold_t)->input.width > 992) + m_pNodes[16].header.affinity = DVP_CORE_CPU; + + m_pNodes[17].header.kernel = DVP_KN_NONMAXSUPPRESS_5x5_S16; + dvp_knode_to(&m_pNodes[17], DVP_Threshold_t)->input = m_images[22]; + dvp_knode_to(&m_pNodes[17], DVP_Threshold_t)->output = m_images[24]; + dvp_knode_to(&m_pNodes[17], DVP_Threshold_t)->thresh = 100; + if(dvp_knode_to(&m_pNodes[17], DVP_Threshold_t)->input.width > 992) + m_pNodes[17].header.affinity = DVP_CORE_CPU; + + m_pNodes[18].header.kernel = DVP_KN_NONMAXSUPPRESS_7x7_S16; + dvp_knode_to(&m_pNodes[18], DVP_Threshold_t)->input = m_images[22]; + dvp_knode_to(&m_pNodes[18], DVP_Threshold_t)->output = m_images[25]; + dvp_knode_to(&m_pNodes[18], DVP_Threshold_t)->thresh = 100; + if(dvp_knode_to(&m_pNodes[18], DVP_Threshold_t)->input.width > 768) + m_pNodes[18].header.affinity = DVP_CORE_CPU; + + m_pNodes[19].header.kernel = DVP_KN_CONV_3x3; + dvp_knode_to(&m_pNodes[19], DVP_ImageConvolution_t)->input = m_images[8]; + dvp_knode_to(&m_pNodes[19], DVP_ImageConvolution_t)->output = m_images[26]; + dvp_knode_to(&m_pNodes[19], DVP_ImageConvolution_t)->mask = m_images[29]; + dvp_knode_to(&m_pNodes[19], DVP_ImageConvolution_t)->shiftMask = 6; + + m_pNodes[20].header.kernel = DVP_KN_CONV_5x5; + dvp_knode_to(&m_pNodes[20], DVP_ImageConvolution_t)->input = m_images[8]; + dvp_knode_to(&m_pNodes[20], DVP_ImageConvolution_t)->output = m_images[27]; + dvp_knode_to(&m_pNodes[20], DVP_ImageConvolution_t)->mask = m_images[30]; + dvp_knode_to(&m_pNodes[20], DVP_ImageConvolution_t)->shiftMask = 7; + + m_pNodes[21].header.kernel = DVP_KN_CONV_7x7; + dvp_knode_to(&m_pNodes[21], DVP_ImageConvolution_t)->input = m_images[8]; + dvp_knode_to(&m_pNodes[21], DVP_ImageConvolution_t)->output = m_images[28]; + dvp_knode_to(&m_pNodes[21], DVP_ImageConvolution_t)->mask = m_images[31]; + dvp_knode_to(&m_pNodes[21], DVP_ImageConvolution_t)->shiftMask = 8; + + DVP_Image_Fill(&m_images[29], (DVP_S08*)maskBlurNeg3x3, 3*3*sizeof(DVP_S08)); + DVP_Image_Fill(&m_images[30], (DVP_S08*)maskBlur7x7, 5*5*sizeof(DVP_S08)); + DVP_Image_Fill(&m_images[31], (DVP_S08*)maskBlur7x7, 7*7*sizeof(DVP_S08)); + + /********* + Canny + **********/ + m_pNodes[22].header.kernel = DVP_KN_CANNY_IMAGE_SMOOTHING; + dvp_knode_to(&m_pNodes[22], DVP_ImageConvolution_t)->input = m_images[8]; + dvp_knode_to(&m_pNodes[22], DVP_ImageConvolution_t)->output = m_images[32]; + dvp_knode_to(&m_pNodes[22], DVP_ImageConvolution_t)->mask = m_images[33]; + dvp_knode_to(&m_pNodes[22], DVP_ImageConvolution_t)->shiftMask = 8; + + m_pNodes[23].header.kernel = DVP_KN_CANNY_2D_GRADIENT; + dvp_knode_to(&m_pNodes[23], DVP_Canny2dGradient_t)->input = m_images[32]; + dvp_knode_to(&m_pNodes[23], DVP_Canny2dGradient_t)->outGradX = m_images[34]; + dvp_knode_to(&m_pNodes[23], DVP_Canny2dGradient_t)->outGradY = m_images[35]; + dvp_knode_to(&m_pNodes[23], DVP_Canny2dGradient_t)->outMag = m_images[36]; + + m_pNodes[24].header.kernel = DVP_KN_CANNY_NONMAX_SUPPRESSION; + dvp_knode_to(&m_pNodes[24], DVP_CannyNonMaxSuppression_t)->inGradX = m_images[34]; + dvp_knode_to(&m_pNodes[24], DVP_CannyNonMaxSuppression_t)->inGradY = m_images[35]; + dvp_knode_to(&m_pNodes[24], DVP_CannyNonMaxSuppression_t)->inMag = m_images[36]; + dvp_knode_to(&m_pNodes[24], DVP_CannyNonMaxSuppression_t)->output = m_images[37]; + + m_pNodes[25].header.kernel = DVP_KN_CANNY_HYST_THRESHHOLD; + dvp_knode_to(&m_pNodes[25], DVP_CannyHystThresholding_t)->inMag = m_images[36]; + dvp_knode_to(&m_pNodes[25], DVP_CannyHystThresholding_t)->inEdgeMap = m_images[37]; + dvp_knode_to(&m_pNodes[25], DVP_CannyHystThresholding_t)->output = m_images[38]; + dvp_knode_to(&m_pNodes[25], DVP_CannyHystThresholding_t)->loThresh = 35; + dvp_knode_to(&m_pNodes[25], DVP_CannyHystThresholding_t)->hiThresh = 122; + + m_pNodes[26].header.kernel = DVP_KN_INTEGRAL_IMAGE_8; + dvp_knode_to(&m_pNodes[26], DVP_Transform_t)->input = m_images[8]; + dvp_knode_to(&m_pNodes[26], DVP_Transform_t)->output = m_images[39]; + if(dvp_knode_to(&m_pNodes[26], DVP_Transform_t)->input.width> 2049 ||dvp_knode_to(&m_pNodes[26], DVP_Transform_t)->input.height> 819 ) + m_pNodes[26].header.affinity = DVP_CORE_CPU; + + m_pNodes[27].header.kernel = DVP_KN_NOOP; + + DVP_Image_Fill(&m_images[33], (DVP_S08*)gaussian_7x7, 7*7*sizeof(DVP_S08)); // Copying the mask +#if defined(DVP_USE_VRUN) + /********* + New Requests + **********/ + m_pNodes[28].header.kernel = DVP_KN_VRUN_CONV_MxN; + dvp_knode_to(&m_pNodes[28], DVP_ImageConvolution_t)->input = m_images[8]; + dvp_knode_to(&m_pNodes[28], DVP_ImageConvolution_t)->output = m_images[41]; + dvp_knode_to(&m_pNodes[28], DVP_ImageConvolution_t)->mask = m_images[43]; + dvp_knode_to(&m_pNodes[28], DVP_ImageConvolution_t)->shiftMask = 4; + + m_pNodes[29].header.kernel = DVP_KN_VRUN_CONV_MxN; + dvp_knode_to(&m_pNodes[29], DVP_ImageConvolution_t)->input = m_images[8]; + dvp_knode_to(&m_pNodes[29], DVP_ImageConvolution_t)->output = m_images[42]; + dvp_knode_to(&m_pNodes[29], DVP_ImageConvolution_t)->mask = m_images[44]; + dvp_knode_to(&m_pNodes[29], DVP_ImageConvolution_t)->shiftMask = 4; +#endif + DVP_Image_Fill(&m_images[43], (DVP_S08*)maskAvg, 7*sizeof(DVP_S08)); // Copying the mask + DVP_Image_Fill(&m_images[44], (DVP_S08*)maskAvg, 7*sizeof(DVP_S08)); // Copying the mask + + m_pNodes[30].header.kernel = DVP_KN_NOOP; + m_pNodes[31].header.kernel = DVP_KN_NOOP; + m_pNodes[32].header.kernel = DVP_KN_NOOP; + m_pNodes[33].header.kernel = DVP_KN_NOOP; + + m_pNodes[34].header.kernel = DVP_KN_YUV444p_TO_RGBp; + dvp_knode_to(&m_pNodes[34], DVP_Transform_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[34], DVP_Transform_t)->output = m_images[53]; + + /********* + Imglib + **********/ + m_pNodes[35].header.kernel = DVP_KN_XSTRIDE_SHIFT; + dvp_knode_to(&m_pNodes[35], DVP_Transform_t)->input = m_images[8]; // Use 8bit luma + dvp_knode_to(&m_pNodes[35], DVP_Transform_t)->output = m_images[54]; // Output 16bit luma + + m_pNodes[36].header.kernel = DVP_KN_THR_GT2MAX_8; + dvp_knode_to(&m_pNodes[36], DVP_Threshold_t)->input = m_images[8]; // Use 8bit luma + dvp_knode_to(&m_pNodes[36], DVP_Threshold_t)->output = m_images[55]; + dvp_knode_to(&m_pNodes[36], DVP_Threshold_t)->thresh = 128; + + m_pNodes[37].header.kernel = DVP_KN_THR_GT2THR_8; + dvp_knode_to(&m_pNodes[37], DVP_Threshold_t)->input = m_images[8]; // Use 8bit luma + dvp_knode_to(&m_pNodes[37], DVP_Threshold_t)->output = m_images[56]; + dvp_knode_to(&m_pNodes[37], DVP_Threshold_t)->thresh = 128; + + m_pNodes[38].header.kernel = DVP_KN_THR_LE2MIN_8; + dvp_knode_to(&m_pNodes[38], DVP_Threshold_t)->input = m_images[8]; // Use 8bit luma + dvp_knode_to(&m_pNodes[38], DVP_Threshold_t)->output = m_images[57]; + dvp_knode_to(&m_pNodes[38], DVP_Threshold_t)->thresh = 128; + + m_pNodes[39].header.kernel = DVP_KN_THR_LE2THR_8; + dvp_knode_to(&m_pNodes[39], DVP_Threshold_t)->input = m_images[8]; // Use 8bit luma + dvp_knode_to(&m_pNodes[39], DVP_Threshold_t)->output = m_images[58]; + dvp_knode_to(&m_pNodes[39], DVP_Threshold_t)->thresh = 128; + + m_pNodes[40].header.kernel = DVP_KN_THR_GT2MAX_16; + dvp_knode_to(&m_pNodes[40], DVP_Threshold_t)->input = m_images[54]; // Use 16bit luma + dvp_knode_to(&m_pNodes[40], DVP_Threshold_t)->output = m_images[59]; + dvp_knode_to(&m_pNodes[40], DVP_Threshold_t)->thresh = (DVP_S16)0x8000; + + m_pNodes[41].header.kernel = DVP_KN_THR_GT2THR_16; + dvp_knode_to(&m_pNodes[41], DVP_Threshold_t)->input = m_images[54]; // Use 16bit luma + dvp_knode_to(&m_pNodes[41], DVP_Threshold_t)->output = m_images[60]; + dvp_knode_to(&m_pNodes[41], DVP_Threshold_t)->thresh = (DVP_S16)0x8000; + + m_pNodes[42].header.kernel = DVP_KN_THR_LE2MIN_16; + dvp_knode_to(&m_pNodes[42], DVP_Threshold_t)->input = m_images[54]; // Use 16bit luma + dvp_knode_to(&m_pNodes[42], DVP_Threshold_t)->output = m_images[61]; + dvp_knode_to(&m_pNodes[42], DVP_Threshold_t)->thresh = (DVP_S16)0x8000; + + m_pNodes[43].header.kernel = DVP_KN_THR_LE2THR_16; + dvp_knode_to(&m_pNodes[43], DVP_Threshold_t)->input = m_images[54]; // Use 16bit luma + dvp_knode_to(&m_pNodes[43], DVP_Threshold_t)->output = m_images[62]; + dvp_knode_to(&m_pNodes[43], DVP_Threshold_t)->thresh = (DVP_S16)0x8000; + + m_pNodes[44].header.kernel = DVP_KN_SOBEL_3x3_8s; + dvp_knode_to(&m_pNodes[44], DVP_Transform_t)->input = m_images[8]; // Use 8bit luma + dvp_knode_to(&m_pNodes[44], DVP_Transform_t)->output = m_images[63]; + + m_pNodes[45].header.kernel = DVP_KN_SOBEL_3x3_8; + dvp_knode_to(&m_pNodes[45], DVP_Transform_t)->input = m_images[8]; // Use 8bit luma + dvp_knode_to(&m_pNodes[45], DVP_Transform_t)->output = m_images[64]; + + m_pNodes[46].header.kernel = DVP_KN_SOBEL_5x5_8s; + dvp_knode_to(&m_pNodes[46], DVP_Transform_t)->input = m_images[8]; // Use 8bit luma + dvp_knode_to(&m_pNodes[46], DVP_Transform_t)->output = m_images[65]; + + m_pNodes[47].header.kernel = DVP_KN_SOBEL_5x5_8; + dvp_knode_to(&m_pNodes[47], DVP_Transform_t)->input = m_images[8]; // Use 8bit luma + dvp_knode_to(&m_pNodes[47], DVP_Transform_t)->output = m_images[66]; + + m_pNodes[48].header.kernel = DVP_KN_SOBEL_7x7_8s; + dvp_knode_to(&m_pNodes[48], DVP_Transform_t)->input = m_images[8]; // Use 8bit luma + dvp_knode_to(&m_pNodes[48], DVP_Transform_t)->output = m_images[67]; + + m_pNodes[49].header.kernel = DVP_KN_SOBEL_7x7_8; + dvp_knode_to(&m_pNodes[49], DVP_Transform_t)->input = m_images[8]; // Use 8bit luma + dvp_knode_to(&m_pNodes[49], DVP_Transform_t)->output = m_images[68]; + + m_pNodes[50].header.kernel = DVP_KN_SOBEL_3x3_16s; + dvp_knode_to(&m_pNodes[50], DVP_Transform_t)->input = m_images[54]; // Use 16bit luma + if(m_width < 1280) + dvp_knode_to(&m_pNodes[50], DVP_Transform_t)->output = m_images[69]; + else + dvp_knode_to(&m_pNodes[50], DVP_Transform_t)->output = m_images[62]; + + m_pNodes[51].header.kernel = DVP_KN_SOBEL_3x3_16; + dvp_knode_to(&m_pNodes[51], DVP_Transform_t)->input = m_images[54]; // Use 16bit luma + if(m_width < 1280) + dvp_knode_to(&m_pNodes[51], DVP_Transform_t)->output = m_images[70]; + else + dvp_knode_to(&m_pNodes[51], DVP_Transform_t)->output = m_images[62]; + + m_pNodes[52].header.kernel = DVP_KN_SOBEL_5x5_16s; + dvp_knode_to(&m_pNodes[52], DVP_Transform_t)->input = m_images[54]; // Use 16bit luma + if(m_width < 1280) + dvp_knode_to(&m_pNodes[52], DVP_Transform_t)->output = m_images[71]; + else + dvp_knode_to(&m_pNodes[52], DVP_Transform_t)->output = m_images[62]; + + m_pNodes[53].header.kernel = DVP_KN_SOBEL_5x5_16; + dvp_knode_to(&m_pNodes[53], DVP_Transform_t)->input = m_images[54]; // Use 16bit luma + if(m_width < 1280) + dvp_knode_to(&m_pNodes[53], DVP_Transform_t)->output = m_images[72]; + else + dvp_knode_to(&m_pNodes[53], DVP_Transform_t)->output = m_images[62]; + + m_pNodes[54].header.kernel = DVP_KN_SOBEL_7x7_16s; + dvp_knode_to(&m_pNodes[54], DVP_Transform_t)->input = m_images[54]; // Use 16bit luma + if(m_width < 1280) + dvp_knode_to(&m_pNodes[54], DVP_Transform_t)->output = m_images[73]; + else + dvp_knode_to(&m_pNodes[54], DVP_Transform_t)->output = m_images[62]; + + m_pNodes[55].header.kernel = DVP_KN_SOBEL_7x7_16; + dvp_knode_to(&m_pNodes[55], DVP_Transform_t)->input = m_images[54]; // Use 16bit luma + if(m_width < 1280) + dvp_knode_to(&m_pNodes[55], DVP_Transform_t)->output = m_images[74]; + else + dvp_knode_to(&m_pNodes[55], DVP_Transform_t)->output = m_images[62]; + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + + if(m_testcore != DVP_CORE_MIN) { + for(uint32_t testnode=0; testnodeinput = m_images[0]; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[1]; + m_pNodes[0].header.affinity = DVP_CORE_DSP; + + m_pNodes[1].header.kernel = DVP_KN_XSTRIDE_CONVERT; // Generates a 16bit per luma value (still only uses lower 8 bits) + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->output = m_images[2]; + + memcpy(m_buffers[0].pData, edgeMap8, sizeof(edgeMap8)); // initialize edges array + memset(m_buffers[1].pData, 0, 256); // initialize histArray + + m_pNodes[2].header.kernel = DVP_KN_VLIB_HISTOGRAM_8; + dvp_knode_to(&m_pNodes[2], DVP_Histogram_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[2], DVP_Histogram_t)->edges = m_buffers[0]; //delineates boundaries between bins + dvp_knode_to(&m_pNodes[2], DVP_Histogram_t)->histArray = m_buffers[1]; //internal buffer should be cleared first time only + dvp_knode_to(&m_pNodes[2], DVP_Histogram_t)->h[0] = m_buffers[2]; + dvp_knode_to(&m_pNodes[2], DVP_Histogram_t)->h[1] = m_buffers[3]; + dvp_knode_to(&m_pNodes[2], DVP_Histogram_t)->h[2] = m_buffers[4]; + dvp_knode_to(&m_pNodes[2], DVP_Histogram_t)->hOut = m_buffers[5]; + dvp_knode_to(&m_pNodes[2], DVP_Histogram_t)->numBins = numBins; + dvp_knode_to(&m_pNodes[2], DVP_Histogram_t)->binWeight = 1; + dvp_knode_to(&m_pNodes[2], DVP_Histogram_t)->clearFlag = 1; + // m_pNodes[2].header.affinity = DVP_CORE_CPU; + + // set all weights to 1 + DVP_U16 *pTmp = (DVP_U16 *)m_buffers[6].pData; + for(i=0; iinput = m_images[1]; + dvp_knode_to(&m_pNodes[3], DVP_Histogram_t)->edges = m_buffers[0]; //delineates boundaries between bins + dvp_knode_to(&m_pNodes[3], DVP_Histogram_t)->histArray = m_buffers[1]; //internal buffer should be cleared first time only + dvp_knode_to(&m_pNodes[3], DVP_Histogram_t)->h[0] = m_buffers[2]; + dvp_knode_to(&m_pNodes[3], DVP_Histogram_t)->h[1] = m_buffers[3]; + dvp_knode_to(&m_pNodes[3], DVP_Histogram_t)->h[2] = m_buffers[4]; + dvp_knode_to(&m_pNodes[3], DVP_Histogram_t)->hOut = m_buffers[7]; + dvp_knode_to(&m_pNodes[3], DVP_Histogram_t)->numBins = numBins; + dvp_knode_to(&m_pNodes[3], DVP_Histogram_t)->binWeights = m_buffers[6]; + dvp_knode_to(&m_pNodes[3], DVP_Histogram_t)->clearFlag = 1; + m_pNodes[3].header.resv[0] = 1; // I am explicitly setting this flag since the previous histogram 8 should have already initialized the histArray. + // m_pNodes[3].header.affinity = DVP_CORE_CPU; + + memcpy(m_buffers[8].pData, edgeMap16, sizeof(edgeMap16)); // initialize edges array + memset(m_buffers[9].pData, 0, 256*2); // initialize histArray + + m_pNodes[4].header.kernel = DVP_KN_VLIB_HISTOGRAM_16; + dvp_knode_to(&m_pNodes[4], DVP_Histogram_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[4], DVP_Histogram_t)->edges = m_buffers[8]; //delineates boundaries between bins + dvp_knode_to(&m_pNodes[4], DVP_Histogram_t)->histArray = m_buffers[9]; //internal buffer should be cleared first time only + dvp_knode_to(&m_pNodes[4], DVP_Histogram_t)->h[0] = m_buffers[2]; + dvp_knode_to(&m_pNodes[4], DVP_Histogram_t)->hOut = m_buffers[10]; + dvp_knode_to(&m_pNodes[4], DVP_Histogram_t)->numBins = numBins; + dvp_knode_to(&m_pNodes[4], DVP_Histogram_t)->binWeight = 1; + dvp_knode_to(&m_pNodes[4], DVP_Histogram_t)->clearFlag = 1; + //m_pNodes[4].header.affinity = DVP_CORE_CPU; + + m_pNodes[5].header.kernel = DVP_KN_VLIB_WEIGHTED_HISTOGRAM_16; + dvp_knode_to(&m_pNodes[5], DVP_Histogram_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[5], DVP_Histogram_t)->edges = m_buffers[8]; //delineates boundaries between bins + dvp_knode_to(&m_pNodes[5], DVP_Histogram_t)->histArray = m_buffers[9]; //internal buffer should be cleared first time only + dvp_knode_to(&m_pNodes[5], DVP_Histogram_t)->h[0] = m_buffers[2]; + dvp_knode_to(&m_pNodes[5], DVP_Histogram_t)->hOut = m_buffers[11]; + dvp_knode_to(&m_pNodes[5], DVP_Histogram_t)->numBins = numBins; + dvp_knode_to(&m_pNodes[5], DVP_Histogram_t)->binWeights = m_buffers[6]; + dvp_knode_to(&m_pNodes[5], DVP_Histogram_t)->clearFlag = 1; + m_pNodes[5].header.resv[0] = 1; // I am explicitly setting this flag since the previous histogram 16 should have already initialized the histArray. + // m_pNodes[5].header.affinity = DVP_CORE_CPU; + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + + } + status = CameraInit(this, m_images[0].color); + if (status == STATUS_SUCCESS) + { + if (m_imgdbg_enabled && AllocateImageDebug(7)) + { + ImageDebug_Init(&m_imgdbg[0], &m_images[0], m_imgdbg_path, "00_input"); + ImageDebug_Init(&m_imgdbg[1], &m_images[1], m_imgdbg_path, "01_luma"); + ImageDebug_Init(&m_imgdbg[2], &m_images[2], m_imgdbg_path, "02_luma16bit"); + BufferDebug_Init(&m_imgdbg[3], &m_buffers[5], m_imgdbg_path, "03_8bitHist", ".bw"); + BufferDebug_Init(&m_imgdbg[4], &m_buffers[7], m_imgdbg_path, "04_8bitWHist", ".bw"); + BufferDebug_Init(&m_imgdbg[5], &m_buffers[10], m_imgdbg_path, "05_16bitHist", ".bw"); + BufferDebug_Init(&m_imgdbg[6], &m_buffers[11], m_imgdbg_path, "06_16bitWHist", ".bw"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + DVP_PRINT(DVP_ZONE_ENGINE, "About to process %u frames!\n",m_numFrames); + } + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} + +status_e TestVisionEngine::Test_TeslaGraphSetup() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_VLIB) + DVP_U32 i; + DVP_Bounds_t bound = {NULL, 0, 0}; + DVP_S32 ONE_10p5 = 32, ONE_8p7 = 128; + +#define CAMERA_NOISE_S16 0x0A00 //SQ12.3 +#define CAMERA_NOISE_S32 0x00A00000 // SQ16.15 +#define THRESHOLD_FACTOR_S16 0x31ff //SQ4.11 +#define THRESHOLD_FACTOR_S32 0x31fffff9 // SQ4.27 +#define MAX_S16 32767 +#define MAX_0p16 1 +#define MAX_4p12 16 +#define MAX_12p4 4096 +#define MAX_13p2 8192 +#define MAX_10p5 1024 +#define NFEATURES 4 +#define IIR_ALPHA_S16 0x10 // SQ0.15 +#define IIR_ALPHA_S32 0x00001000 // SQ0.31 +#define LGM_ORDER 6 +#define LAB_D 4 +#define sD_2x4 (4) +#define mD_2x4 (2) +#define sD_4x6 (6) +#define mD_4x6 (2) +#define SimplexN 3 +#define MAX_S32_S 2147483648 +#define MAX_4p27 16 +#define HIST_ND_DIMX 4 + // DECLARE AND INITIALIZE MIXTURE OF GAUSSIANS PARAMETERS + // update rate for weights, SQ0.15 + DVP_S16 updateRate1 = 0.001 * MAX_S16/MAX_0p16; + // update rate for means and variances, SQ0.31 + DVP_S16 updateRate2 = 0.001 * MAX_S16/MAX_0p16; + // mahalanobis distance threshold, SQ4.27 + DVP_S16 mdThreshold = (2.5*2.5) * (MAX_S16/MAX_4p12); + // background subtraction threshold, SQ0.15 + DVP_S16 bsThreshold = 0.9 * MAX_S16/MAX_0p16; + // initial weight for new component, SQ0.15 + DVP_S16 initialWt = 0.001 * (MAX_S16/MAX_0p16); + // initial variance for new component, SQ16.15 + DVP_S16 initialVar = 320 * (MAX_S16/MAX_12p4); + + if (m_hDVP) + { + if (AllocateImageStructs(65)) + { + DVP_Image_Init(&m_images[0], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[1], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[2], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[3], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[4], m_width, m_height, FOURCC_Y16); //HSLp (H 16bit) + DVP_Image_Init(&m_images[5], m_width-4, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[6], (m_width-4)/2, (m_height-3)/2, FOURCC_Y800); + DVP_Image_Init(&m_images[7], (m_width-4)/2, (m_height-3)/2, FOURCC_Y800); + DVP_Image_Init(&m_images[8], (m_width/8), (m_height/8)*21, FOURCC_Y800); + DVP_Image_Init(&m_images[9], (m_width/8), (m_height/8)*21, FOURCC_Y16); + DVP_Image_Init(&m_images[10], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[11], m_width, m_height, FOURCC_RGBA); + DVP_Image_Init(&m_images[12], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[13], m_width, m_height, FOURCC_RGBA); + DVP_Image_Init(&m_images[14], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[15], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[16], m_width, 8, FOURCC_Y16); + DVP_Image_Init(&m_images[17], m_width/32, m_height, FOURCC_RGBA); + DVP_Image_Init(&m_images[18], m_width/32, m_height, FOURCC_RGBA); + DVP_Image_Init(&m_images[19], m_width, m_height*3, FOURCC_Y16); //mog wts + DVP_Image_Init(&m_images[20], m_width, m_height*3, FOURCC_Y16); //mog mu + DVP_Image_Init(&m_images[21], m_width, m_height*3, FOURCC_Y16); //mog var + DVP_Image_Init(&m_images[22], m_width, m_height*3, FOURCC_Y800); //mog intbuf for 16/32 + DVP_Image_Init(&m_images[23], m_width, m_height, FOURCC_Y800); //mog compidx + DVP_Image_Init(&m_images[24], m_width/32, m_height, FOURCC_RGBA); //mog fgmask + DVP_Image_Init(&m_images[25], m_width, m_height*3, FOURCC_Y16); //mog wts + DVP_Image_Init(&m_images[26], m_width, m_height*3, FOURCC_RGBA); //mog mu + DVP_Image_Init(&m_images[27], m_width, m_height*3, FOURCC_RGBA); //mog var + DVP_Image_Init(&m_images[28], m_width, m_height, FOURCC_Y800); //mog compidx + DVP_Image_Init(&m_images[29], m_width/32, m_height, FOURCC_RGBA); //mog fgmask + DVP_Image_Init(&m_images[30], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[31], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[32], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[33], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[34], m_width, m_height, FOURCC_YV16); + DVP_Image_Init(&m_images[35], m_width, m_height, FOURCC_IYUV); + DVP_Image_Init(&m_images[36], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[37], m_width, m_height, FOURCC_Y16); // L (LABp) + DVP_Image_Init(&m_images[38], m_width, m_height, FOURCC_Y16); // a (LABp) + DVP_Image_Init(&m_images[39], m_width, m_height, FOURCC_Y16); // b (LABp) + DVP_Image_Init(&m_images[40], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[41], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[42], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[43], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[44], 267, 267, FOURCC_Y16); //hough space + DVP_Image_Init(&m_images[45], m_width/32, m_height, FOURCC_Y800); //mask for EWR + DVP_Image_Init(&m_images[46], m_width/32, m_height, FOURCC_Y800); //mask for EWR + DVP_Image_Init(&m_images[47], m_width/32, m_height, FOURCC_Y800); //mask for EWR + DVP_Image_Init(&m_images[48], m_width/32, m_height, FOURCC_Y800); //mask for EWR + DVP_Image_Init(&m_images[49], m_width/32, m_height, FOURCC_Y800); //mask for UWR + DVP_Image_Init(&m_images[50], m_width/32, m_height, FOURCC_Y800); //mask for UWR + DVP_Image_Init(&m_images[51], m_width, m_height, FOURCC_Y800); //HSLp (S) + DVP_Image_Init(&m_images[52], m_width, m_height, FOURCC_Y800); //HSLp (L) + DVP_Image_Init(&m_images[53], m_width, m_height, FOURCC_NV12); + DVP_Image_Init(&m_images[54], m_width, m_height, FOURCC_YV24); + DVP_Image_Init(&m_images[55], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[56], m_width, m_height, FOURCC_RGBA); //hyst thresh scratch + DVP_Image_Init(&m_images[57], m_width, m_height+1, FOURCC_RGBA); //intimg16 + DVP_Image_Init(&m_images[58], m_width, m_height, FOURCC_Y800);//extractBack16 + DVP_Image_Init(&m_images[59], (m_width-4)/2, (m_height-4)/2, FOURCC_Y800); + DVP_Image_Init(&m_images[60], (m_width-4)/2, (m_height-4)/2, FOURCC_Y16); + DVP_Image_Init(&m_images[61], m_width-4, 5, FOURCC_RGBA);//scratch buffer for gauss5x5 + DVP_Image_Init(&m_images[62], m_width/8, m_height, FOURCC_Y800); //pack + DVP_Image_Init(&m_images[63], m_width, m_height, FOURCC_Y800); //unpack + DVP_Image_Init(&m_images[64], m_width, m_height, FOURCC_RGBA); //harris32 + if (!DVP_Image_Alloc(m_hDVP, &m_images[0], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[1], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[2], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[3], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[4], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[5], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[6], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[7], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[8], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[9], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[10], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[11], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[12], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[13], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[14], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[15], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[16], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[17], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[18], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[19], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[20], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[21], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[22], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[23], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[24], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[25], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[26], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[27], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[28], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[29], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[30], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[31], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[32], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[33], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[34], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[35], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[36], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[37], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[38], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[39], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[40], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[41], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[42], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[43], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[44], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[45], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[46], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[47], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[48], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[49], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[50], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[51], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[52], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[53], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[54], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[55], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[56], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[57], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[58], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[59], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[60], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[61], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[62], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[63], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[64], DVP_MTYPE_DEFAULT)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + if (AllocateBufferStructs(67)) + { + DVP_Buffer_Init(&m_buffers[0], 1, 192*m_width); // scratch harris + DVP_Buffer_Init(&m_buffers[1], 2, m_width*m_height*.05); //5% edge points + DVP_Buffer_Init(&m_buffers[2], 2, 267); //Sin + DVP_Buffer_Init(&m_buffers[3], 2, 267); //Cos + DVP_Buffer_Init(&m_buffers[4], 2, 267 + 267%4); //ping + DVP_Buffer_Init(&m_buffers[5], 2, 267 + 267%4); //pong + DVP_Buffer_Init(&m_buffers[6], 2, 267 + 267%4); //pang + DVP_Buffer_Init(&m_buffers[7], 2, 267 + 267%4); //peng + DVP_Buffer_Init(&m_buffers[8], 2, NFEATURES); //x + DVP_Buffer_Init(&m_buffers[9], 2, NFEATURES); //y + DVP_Buffer_Init(&m_buffers[10], 2, NFEATURES); //outx + DVP_Buffer_Init(&m_buffers[11], 2, NFEATURES); //outx + DVP_Buffer_Init(&m_buffers[12], 1, 384); //scratch + DVP_Buffer_Init(&m_buffers[13], 2, (LGM_ORDER+1)*m_height); //legendre poly + DVP_Buffer_Init(&m_buffers[14], 2, (LGM_ORDER+1)*(LGM_ORDER+1)); //legendre mom + DVP_Buffer_Init(&m_buffers[15], 2, m_width*m_height); //kalman filter 2x4 + DVP_Buffer_Init(&m_buffers[16], 2, sD_2x4*sD_2x4); //transition + DVP_Buffer_Init(&m_buffers[17], 2, sD_2x4*sD_2x4); //errorCov + DVP_Buffer_Init(&m_buffers[18], 2, sD_2x4*sD_2x4); //predictedErrorCov + DVP_Buffer_Init(&m_buffers[19], 2, sD_2x4*sD_2x4); //processNoiseCov + DVP_Buffer_Init(&m_buffers[20], 2, mD_2x4*mD_2x4); //measurementNoiseCov + DVP_Buffer_Init(&m_buffers[21], 2, sD_2x4*mD_2x4); //measurement + DVP_Buffer_Init(&m_buffers[22], 2, sD_2x4); //state + DVP_Buffer_Init(&m_buffers[23], 2, sD_2x4); //predictedState + DVP_Buffer_Init(&m_buffers[24], 2, sD_2x4*mD_2x4); //kalmanGain + DVP_Buffer_Init(&m_buffers[25], 2, sD_2x4*sD_2x4); //temp1 + DVP_Buffer_Init(&m_buffers[26], 2, sD_2x4*sD_2x4); //temp2 + DVP_Buffer_Init(&m_buffers[27], 2, sD_2x4*sD_2x4); //temp3 + DVP_Buffer_Init(&m_buffers[28], 4, m_width*m_height); //kalman filter 4x6 + DVP_Buffer_Init(&m_buffers[29], 2, sD_4x6*sD_4x6); //transition + DVP_Buffer_Init(&m_buffers[30], 2, sD_4x6*sD_4x6); //errorCov + DVP_Buffer_Init(&m_buffers[31], 2, sD_4x6*sD_4x6); //predictedErrorCov + DVP_Buffer_Init(&m_buffers[32], 2, sD_4x6*sD_4x6); //processNoiseCov + DVP_Buffer_Init(&m_buffers[33], 2, mD_4x6*mD_4x6); //measurementNoiseCov + DVP_Buffer_Init(&m_buffers[34], 2, sD_4x6*mD_4x6); //measurement + DVP_Buffer_Init(&m_buffers[35], 2, sD_4x6); //state + DVP_Buffer_Init(&m_buffers[36], 2, sD_4x6); //predictedState + DVP_Buffer_Init(&m_buffers[37], 2, sD_4x6*mD_4x6); //kalmanGain + DVP_Buffer_Init(&m_buffers[38], 2, sD_4x6*sD_4x6); //temp1 + DVP_Buffer_Init(&m_buffers[39], 2, sD_4x6*sD_4x6); //temp2 + DVP_Buffer_Init(&m_buffers[40], 2, sD_4x6*sD_4x6); //temp3 + DVP_Buffer_Init(&m_buffers[41], 2, SimplexN); //Simplex start + DVP_Buffer_Init(&m_buffers[42], 2, SimplexN); //Simplex step + DVP_Buffer_Init(&m_buffers[43], 2, SimplexN); //Simplex stop + DVP_Buffer_Init(&m_buffers[44], 2, SimplexN+1); //Simplex v + DVP_Buffer_Init(&m_buffers[45], 2, SimplexN+1); //Simplex f + DVP_Buffer_Init(&m_buffers[46], 2, SimplexN); //Simplex vr + DVP_Buffer_Init(&m_buffers[47], 2, SimplexN); //Simplex ve + DVP_Buffer_Init(&m_buffers[48], 2, SimplexN); //Simplex vc + DVP_Buffer_Init(&m_buffers[49], 2, SimplexN); //Simplex vm + DVP_Buffer_Init(&m_buffers[50], 2, SimplexN); //Simplex3D start + DVP_Buffer_Init(&m_buffers[51], 2, SimplexN); //Simplex3D step + DVP_Buffer_Init(&m_buffers[52], 2, SimplexN); //Simplex3D stop + DVP_Buffer_Init(&m_buffers[53], 2, SimplexN+1); //Simplex3D v + DVP_Buffer_Init(&m_buffers[54], 2, SimplexN+1); //Simplex3D f + DVP_Buffer_Init(&m_buffers[55], 2, SimplexN); //Simplex3D vr + DVP_Buffer_Init(&m_buffers[56], 2, SimplexN); //Simplex3D ve + DVP_Buffer_Init(&m_buffers[57], 2, SimplexN); //Simplex3D vc + DVP_Buffer_Init(&m_buffers[58], 2, SimplexN); //Simplex3D vm + DVP_Buffer_Init(&m_buffers[59], 2, HIST_ND_DIMX); //Hist nD16 nbins + DVP_Buffer_Init(&m_buffers[60], 2, HIST_ND_DIMX); //Hist nD16 norms + DVP_Buffer_Init(&m_buffers[61], 2, m_width*m_height/HIST_ND_DIMX); //Hist int1 + DVP_Buffer_Init(&m_buffers[62], 2, 32*32*32*32); //Hist nD16 int2 + DVP_Buffer_Init(&m_buffers[63], 2, 32*32*32*32); //Hist nD16 H + DVP_Buffer_Init(&m_buffers[64], 4, m_width*m_height); //nms 32 + DVP_Buffer_Init(&m_buffers[65], 4, 4*(7 + m_width*m_height)); //nms5x5 32 scratch + DVP_Buffer_Init(&m_buffers[66], 1, 2197000); //lab LUT ref:VLIB_initUYVYint_to_LABpl_LUT_i.c + if (!DVP_Buffer_Alloc(m_hDVP, &m_buffers[0], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[1], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[2], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[3], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[4], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[5], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[6], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[7], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[8], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[9], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[10], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[11], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[12], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[13], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[14], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[15], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[16], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[17], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[18], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[19], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[20], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[21], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[22], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[23], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[24], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[25], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[26], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[27], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[28], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[29], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[30], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[31], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[32], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[33], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[34], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[35], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[36], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[37], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[38], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[39], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[40], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[41], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[42], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[43], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[44], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[45], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[46], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[47], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[48], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[49], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[50], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[51], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[52], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[53], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[54], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[55], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[56], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[57], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[58], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[59], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[60], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[61], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[62], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[63], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[64], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[65], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[66], DVP_MTYPE_DEFAULT)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + /*init Sin and Cos LUT for houghLines + */ + float Theta; + float ThetaMin = -80; + float ThetaMax = 79.6; + float NumThetaPoints = 267; + DVP_S16 *pSin = (DVP_S16*)m_buffers[2].pData; + DVP_S16 *pCos = (DVP_S16*)m_buffers[3].pData; + for(i = 0; i < NumThetaPoints; i++) + { + + Theta = ThetaMin + i*(ThetaMax - ThetaMin)/(NumThetaPoints-1); + + *(pSin + i) = (DVP_S16)(floor(256*sin(Theta*0.017453) + 0.5)); + *(pCos + i) = (DVP_S16)(floor(256*cos(Theta*0.017453) + 0.5)); + + // pTRIG[i] = (*(pCos + i)) | ((S32)(*(pSin + i)) << 16);; + + } + /*init Sin and Cos LUT for houghLines + */ + + /* Init buffers for Kalman Filter 2x4 */ + DVP_S16 *tmpPtr; + memset(m_buffers[16].pData, 0, sD_2x4*sD_2x4*sizeof(DVP_S16)); + memset(m_buffers[17].pData, 0, sD_2x4*sD_2x4*sizeof(DVP_S16)); + memset(m_buffers[18].pData, 0, sD_2x4*sD_2x4*sizeof(DVP_S16)); + memset(m_buffers[19].pData, 0, sD_2x4*sD_2x4*sizeof(DVP_S16)); + memset(m_buffers[20].pData, 0, mD_2x4*mD_2x4*sizeof(DVP_S16)); + memset(m_buffers[21].pData, 0, sD_2x4*mD_2x4*sizeof(DVP_S16)); + memset(m_buffers[22].pData, 0, sD_2x4*sizeof(DVP_S16)); + memset(m_buffers[23].pData, 0, sD_2x4*sizeof(DVP_S16)); + memset(m_buffers[24].pData, 0, sD_2x4*mD_2x4*sizeof(DVP_S16)); + memset(m_buffers[25].pData, 0, sD_2x4*sD_2x4*sizeof(DVP_S16)); + memset(m_buffers[26].pData, 0, sD_2x4*sD_2x4*sizeof(DVP_S16)); + memset(m_buffers[27].pData, 0, sD_2x4*sD_2x4*sizeof(DVP_S16)); + + // initialize matrices + for(i=0;iinput = m_images[0]; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[1]; + m_pNodes[0].header.affinity = DVP_CORE_DSP; + + m_pNodes[1].header.kernel = DVP_KN_XSTRIDE_CONVERT; // Generates a 16bit per luma value (still only uses lower 8 bits) for X + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->output = m_images[2]; + + m_pNodes[2].header.kernel = DVP_KN_XSTRIDE_CONVERT; // Generates 16bit per luma for Y + dvp_knode_to(&m_pNodes[2], DVP_Transform_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[2], DVP_Transform_t)->output = m_images[3]; + + m_pNodes[3].header.kernel = DVP_KN_VLIB_BHATTACHAYA_DISTANCE; // Call Battacharya distance on dsp + dvp_knode_to(&m_pNodes[3], DVP_Distance_t)->X = m_images[2]; + dvp_knode_to(&m_pNodes[3], DVP_Distance_t)->Y = m_images[3]; + dvp_knode_to(&m_pNodes[3], DVP_Distance_t)->distance = 0; //Initialize to zero + m_pNodes[3].header.affinity = DVP_CORE_DSP; + + m_pNodes[4].header.kernel = DVP_KN_VLIB_L1DISTANCE; // Call L1 distance on dsp + dvp_knode_to(&m_pNodes[4], DVP_Distance_t)->X = m_images[2]; + dvp_knode_to(&m_pNodes[4], DVP_Distance_t)->Y = m_images[3]; + dvp_knode_to(&m_pNodes[4], DVP_Distance_t)->distance = 0; //Initialize to zero + m_pNodes[4].header.affinity = DVP_CORE_DSP; + + m_pNodes[5].header.kernel = DVP_KN_VLIB_UYVY_TO_HSLp; + dvp_knode_to(&m_pNodes[5], DVP_Int2Pl_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[5], DVP_Int2Pl_t)->output1 = m_images[4]; + dvp_knode_to(&m_pNodes[5], DVP_Int2Pl_t)->output2 = m_images[51]; + dvp_knode_to(&m_pNodes[5], DVP_Int2Pl_t)->output3 = m_images[52]; + m_pNodes[5].header.affinity = DVP_CORE_DSP; + + m_pNodes[6].header.kernel = DVP_KN_VLIB_GRADIENT_V5x5_PYRAMID_8; + dvp_knode_to(&m_pNodes[6], DVP_Gradient_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[6], DVP_Gradient_t)->output = m_images[6]; + dvp_knode_to(&m_pNodes[6], DVP_Gradient_t)->scratch = m_images[5]; + m_pNodes[6].header.affinity = DVP_CORE_DSP; + + m_pNodes[7].header.kernel = DVP_KN_VLIB_GRADIENT_H5x5_PYRAMID_8; + dvp_knode_to(&m_pNodes[7], DVP_Gradient_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[7], DVP_Gradient_t)->output = m_images[7]; + dvp_knode_to(&m_pNodes[7], DVP_Gradient_t)->scratch = m_images[5]; + m_pNodes[7].header.affinity = DVP_CORE_DSP; + + m_pNodes[8].header.kernel = DVP_KN_VLIB_IMAGE_PYRAMID_8; + dvp_knode_to(&m_pNodes[8], DVP_Transform_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[8], DVP_Transform_t)->output = m_images[8]; + m_pNodes[8].header.affinity = DVP_CORE_DSP; + + m_pNodes[9].header.kernel = DVP_KN_VLIB_IMAGE_PYRAMID_16; + dvp_knode_to(&m_pNodes[9], DVP_Transform_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[9], DVP_Transform_t)->output = m_images[9]; + m_pNodes[9].header.affinity = DVP_CORE_DSP; + + m_pNodes[10].header.kernel = DVP_KN_VLIB_INIT_MEAN_LUMA_S16; + dvp_knode_to(&m_pNodes[10], DVP_Transform_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[10], DVP_Transform_t)->output = m_images[10]; + m_pNodes[10].header.affinity = DVP_CORE_DSP; + + m_pNodes[11].header.kernel = DVP_KN_VLIB_INIT_MEAN_LUMA_S32; + dvp_knode_to(&m_pNodes[11], DVP_Transform_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[11], DVP_Transform_t)->output = m_images[11]; + m_pNodes[11].header.affinity = DVP_CORE_DSP; + + m_pNodes[12].header.kernel = DVP_KN_VLIB_INIT_VAR_CONST_S16; + dvp_knode_to(&m_pNodes[12], DVP_ConstVar_t)->var = m_images[12]; + dvp_knode_to(&m_pNodes[12], DVP_ConstVar_t)->constVar = CAMERA_NOISE_S16/32; + m_pNodes[12].header.affinity = DVP_CORE_DSP; + + m_pNodes[13].header.kernel = DVP_KN_VLIB_INIT_VAR_CONST_S32; + dvp_knode_to(&m_pNodes[13], DVP_ConstVar_t)->var = m_images[13]; + dvp_knode_to(&m_pNodes[13], DVP_ConstVar_t)->constVar = CAMERA_NOISE_S32/32; + m_pNodes[13].header.affinity = DVP_CORE_DSP; + + m_pNodes[14].header.kernel = DVP_KN_VLIB_IIR_HORZ_16; + dvp_knode_to(&m_pNodes[14], DVP_IIR_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[14], DVP_IIR_t)->output = m_images[14]; + dvp_knode_to(&m_pNodes[14], DVP_IIR_t)->weight = 2000; + dvp_knode_to(&m_pNodes[14], DVP_IIR_t)->bounds[0] = bound; + dvp_knode_to(&m_pNodes[14], DVP_IIR_t)->bounds[1] = bound; + dvp_knode_to(&m_pNodes[14], DVP_IIR_t)->scratch = m_images[16]; + m_pNodes[14].header.affinity = DVP_CORE_DSP; + + m_pNodes[15].header.kernel = DVP_KN_VLIB_IIR_VERT_16; + dvp_knode_to(&m_pNodes[15], DVP_IIR_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[15], DVP_IIR_t)->output = m_images[15]; + dvp_knode_to(&m_pNodes[15], DVP_IIR_t)->weight = 2000; + dvp_knode_to(&m_pNodes[15], DVP_IIR_t)->bounds[0] = bound; + dvp_knode_to(&m_pNodes[15], DVP_IIR_t)->bounds[1] = bound; + dvp_knode_to(&m_pNodes[15], DVP_IIR_t)->scratch = m_images[16]; + m_pNodes[15].header.affinity = DVP_CORE_DSP; + + m_pNodes[16].header.kernel = DVP_KN_VLIB_SUB_BACK_S16; + dvp_knode_to(&m_pNodes[16], DVP_SubBackground_t)->newestData = m_images[1]; + dvp_knode_to(&m_pNodes[16], DVP_SubBackground_t)->output32packed = m_images[17]; + dvp_knode_to(&m_pNodes[16], DVP_SubBackground_t)->currentMean = m_images[10]; + dvp_knode_to(&m_pNodes[16], DVP_SubBackground_t)->currentVar = m_images[12]; + dvp_knode_to(&m_pNodes[16], DVP_SubBackground_t)->thresholdGlobal = CAMERA_NOISE_S16/32; + dvp_knode_to(&m_pNodes[16], DVP_SubBackground_t)->thresholdFactor = THRESHOLD_FACTOR_S16/2; + m_pNodes[16].header.affinity = DVP_CORE_DSP; + + m_pNodes[17].header.kernel = DVP_KN_VLIB_SUB_BACK_S32; + dvp_knode_to(&m_pNodes[17], DVP_SubBackground_t)->newestData = m_images[1]; + dvp_knode_to(&m_pNodes[17], DVP_SubBackground_t)->output32packed = m_images[18]; + dvp_knode_to(&m_pNodes[17], DVP_SubBackground_t)->currentMean = m_images[11]; + dvp_knode_to(&m_pNodes[17], DVP_SubBackground_t)->currentVar = m_images[13]; + dvp_knode_to(&m_pNodes[17], DVP_SubBackground_t)->thresholdGlobal = CAMERA_NOISE_S32/32; + dvp_knode_to(&m_pNodes[17], DVP_SubBackground_t)->thresholdFactor = THRESHOLD_FACTOR_S32/2; + m_pNodes[17].header.affinity = DVP_CORE_DSP; + + m_pNodes[18].header.kernel = DVP_KN_VLIB_MOG_S16; + dvp_knode_to(&m_pNodes[18], DVP_Mog_t)->image = m_images[1]; + dvp_knode_to(&m_pNodes[18], DVP_Mog_t)->wts = m_images[19]; + dvp_knode_to(&m_pNodes[18], DVP_Mog_t)->means = m_images[20]; + dvp_knode_to(&m_pNodes[18], DVP_Mog_t)->vars = m_images[21]; + dvp_knode_to(&m_pNodes[18], DVP_Mog_t)->scratch = m_images[22]; + dvp_knode_to(&m_pNodes[18], DVP_Mog_t)->compIndex = m_images[23]; + dvp_knode_to(&m_pNodes[18], DVP_Mog_t)->fgmask = m_images[24]; + dvp_knode_to(&m_pNodes[18], DVP_Mog_t)->alpha = updateRate1; + dvp_knode_to(&m_pNodes[18], DVP_Mog_t)->rho = updateRate2; + dvp_knode_to(&m_pNodes[18], DVP_Mog_t)->delta = mdThreshold; + dvp_knode_to(&m_pNodes[18], DVP_Mog_t)->T = bsThreshold; + dvp_knode_to(&m_pNodes[18], DVP_Mog_t)->ini_wt = initialWt; + dvp_knode_to(&m_pNodes[18], DVP_Mog_t)->ini_var = initialVar; + m_pNodes[18].header.affinity = DVP_CORE_DSP; + + m_pNodes[19].header.kernel = DVP_KN_VLIB_MOG_S32; + dvp_knode_to(&m_pNodes[19], DVP_Mog_t)->image = m_images[1]; + dvp_knode_to(&m_pNodes[19], DVP_Mog_t)->wts = m_images[25]; + dvp_knode_to(&m_pNodes[19], DVP_Mog_t)->means = m_images[26]; + dvp_knode_to(&m_pNodes[19], DVP_Mog_t)->vars = m_images[27]; + dvp_knode_to(&m_pNodes[19], DVP_Mog_t)->scratch = m_images[22]; + dvp_knode_to(&m_pNodes[19], DVP_Mog_t)->compIndex = m_images[28]; + dvp_knode_to(&m_pNodes[19], DVP_Mog_t)->fgmask = m_images[29]; + dvp_knode_to(&m_pNodes[19], DVP_Mog_t)->alpha = updateRate1; + dvp_knode_to(&m_pNodes[19], DVP_Mog_t)->rho = updateRate2; + dvp_knode_to(&m_pNodes[19], DVP_Mog_t)->delta = mdThreshold; + dvp_knode_to(&m_pNodes[19], DVP_Mog_t)->T = bsThreshold; + dvp_knode_to(&m_pNodes[19], DVP_Mog_t)->ini_wt = initialWt; + dvp_knode_to(&m_pNodes[19], DVP_Mog_t)->ini_var = initialVar; + m_pNodes[19].header.affinity = DVP_CORE_DSP; + + m_pNodes[20].header.kernel = DVP_KN_VLIB_NORMALFLOW_16; + dvp_knode_to(&m_pNodes[20], DVP_NormalFlow_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[20], DVP_NormalFlow_t)->mag = m_images[3]; + dvp_knode_to(&m_pNodes[20], DVP_NormalFlow_t)->x = m_images[3]; + dvp_knode_to(&m_pNodes[20], DVP_NormalFlow_t)->y = m_images[3]; + dvp_knode_to(&m_pNodes[20], DVP_NormalFlow_t)->lut = m_images[30]; + dvp_knode_to(&m_pNodes[20], DVP_NormalFlow_t)->u = m_images[31]; + dvp_knode_to(&m_pNodes[20], DVP_NormalFlow_t)->v = m_images[32]; + dvp_knode_to(&m_pNodes[20], DVP_NormalFlow_t)->thresh = 10; + m_pNodes[20].header.affinity = DVP_CORE_DSP; + + m_pNodes[21].header.kernel = DVP_KN_VLIB_ERODE_SINGLEPIXEL; + dvp_knode_to(&m_pNodes[21], DVP_Morphology_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[21], DVP_Morphology_t)->output = m_images[33]; + m_pNodes[21].header.affinity = DVP_CORE_DSP; + + m_pNodes[22].header.kernel = DVP_KN_UYVY_TO_YUV422p; + dvp_knode_to(&m_pNodes[22], DVP_Transform_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[22], DVP_Transform_t)->output = m_images[34]; + m_pNodes[22].header.affinity = DVP_CORE_DSP; + + m_pNodes[23].header.kernel = DVP_KN_UYVY_TO_YUV420p; + dvp_knode_to(&m_pNodes[23], DVP_Transform_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[23], DVP_Transform_t)->output = m_images[35]; + m_pNodes[23].header.affinity = DVP_CORE_DSP; + + m_pNodes[24].header.kernel = DVP_KN_YUV422p_TO_UYVY; + dvp_knode_to(&m_pNodes[24], DVP_Transform_t)->input = m_images[34]; + dvp_knode_to(&m_pNodes[24], DVP_Transform_t)->output = m_images[36]; + m_pNodes[24].header.affinity = DVP_CORE_DSP; + + m_pNodes[25].header.kernel = DVP_KN_VLIB_UYVY_TO_LABp; + dvp_knode_to(&m_pNodes[25], DVP_Int2Pl_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[25], DVP_Int2Pl_t)->output1 = m_images[37]; + dvp_knode_to(&m_pNodes[25], DVP_Int2Pl_t)->output2 = m_images[38]; + dvp_knode_to(&m_pNodes[25], DVP_Int2Pl_t)->output3 = m_images[39]; + dvp_knode_to(&m_pNodes[25], DVP_Int2Pl_t)->scratch = m_buffers[66]; + dvp_knode_to(&m_pNodes[25], DVP_Int2Pl_t)->factor = 4; + m_pNodes[25].header.affinity = DVP_CORE_DSP; + + m_pNodes[26].header.kernel = DVP_KN_CANNY_2D_GRADIENT; + dvp_knode_to(&m_pNodes[26], DVP_Canny2dGradient_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[26], DVP_Canny2dGradient_t)->outGradX = m_images[40]; + dvp_knode_to(&m_pNodes[26], DVP_Canny2dGradient_t)->outGradY = m_images[41]; + dvp_knode_to(&m_pNodes[26], DVP_Canny2dGradient_t)->outMag = m_images[42]; + m_pNodes[26].header.affinity = DVP_CORE_DSP; + + m_pNodes[27].header.kernel = DVP_KN_VLIB_HARRIS_SCORE_7x7; + dvp_knode_to(&m_pNodes[27], DVP_HarrisDSP_t)->inGradX = m_images[40]; + dvp_knode_to(&m_pNodes[27], DVP_HarrisDSP_t)->inGradY = m_images[41]; + dvp_knode_to(&m_pNodes[27], DVP_HarrisDSP_t)->scratch = m_buffers[0]; + dvp_knode_to(&m_pNodes[27], DVP_HarrisDSP_t)->harrisScore = m_images[43]; + dvp_knode_to(&m_pNodes[27], DVP_HarrisDSP_t)->k = 1310; + m_pNodes[27].header.affinity = DVP_CORE_DSP; + + m_pNodes[28].header.kernel = DVP_KN_VLIB_TRACK_FEATURES_LUCAS_7x7; + dvp_knode_to(&m_pNodes[28], DVP_TrackFeatures_t)->im1 = m_images[1]; + dvp_knode_to(&m_pNodes[28], DVP_TrackFeatures_t)->im2 = m_images[1]; + dvp_knode_to(&m_pNodes[28], DVP_TrackFeatures_t)->gradx = m_images[40]; + dvp_knode_to(&m_pNodes[28], DVP_TrackFeatures_t)->grady = m_images[41]; + dvp_knode_to(&m_pNodes[28], DVP_TrackFeatures_t)->x = m_buffers[8]; + dvp_knode_to(&m_pNodes[28], DVP_TrackFeatures_t)->y = m_buffers[9]; + dvp_knode_to(&m_pNodes[28], DVP_TrackFeatures_t)->outx = m_buffers[10]; + dvp_knode_to(&m_pNodes[28], DVP_TrackFeatures_t)->outy = m_buffers[11]; + dvp_knode_to(&m_pNodes[28], DVP_TrackFeatures_t)->scratch = m_buffers[12]; + dvp_knode_to(&m_pNodes[28], DVP_TrackFeatures_t)->nfeatures = NFEATURES; + dvp_knode_to(&m_pNodes[28], DVP_TrackFeatures_t)->max_iters = 10; + + m_pNodes[29].header.kernel = DVP_KN_VLIB_HOUGH_LINE_FROM_LIST; + dvp_knode_to(&m_pNodes[29], DVP_HoughLine_t)->pEdgeMapList = m_buffers[1]; + dvp_knode_to(&m_pNodes[29], DVP_HoughLine_t)->pOutHoughSpace = m_images[44]; + dvp_knode_to(&m_pNodes[29], DVP_HoughLine_t)->pSIN = m_buffers[2]; + dvp_knode_to(&m_pNodes[29], DVP_HoughLine_t)->pCOS = m_buffers[3]; + dvp_knode_to(&m_pNodes[29], DVP_HoughLine_t)->ping = m_buffers[4]; + dvp_knode_to(&m_pNodes[29], DVP_HoughLine_t)->pong = m_buffers[5]; + dvp_knode_to(&m_pNodes[29], DVP_HoughLine_t)->pang = m_buffers[6]; + dvp_knode_to(&m_pNodes[29], DVP_HoughLine_t)->peng = m_buffers[7]; + dvp_knode_to(&m_pNodes[29], DVP_HoughLine_t)->outBlkWidth = m_width; + dvp_knode_to(&m_pNodes[29], DVP_HoughLine_t)->outBlkHeight = m_height; + dvp_knode_to(&m_pNodes[29], DVP_HoughLine_t)->listSize = m_height*m_width*.05; + dvp_knode_to(&m_pNodes[29], DVP_HoughLine_t)->thetaRange = 267; + dvp_knode_to(&m_pNodes[29], DVP_HoughLine_t)->rhoMaxLength = 267; + m_pNodes[29].header.affinity = DVP_CORE_DSP; + + m_pNodes[30].header.kernel = DVP_KN_VLIB_EWR_MEAN_S16; + dvp_knode_to(&m_pNodes[30], DVP_EMean_t)->mean = m_images[10]; + dvp_knode_to(&m_pNodes[30], DVP_EMean_t)->data = m_images[1]; + dvp_knode_to(&m_pNodes[30], DVP_EMean_t)->mask = m_images[45]; + dvp_knode_to(&m_pNodes[30], DVP_EMean_t)->weight = IIR_ALPHA_S16; + m_pNodes[30].header.affinity = DVP_CORE_DSP; + + m_pNodes[31].header.kernel = DVP_KN_VLIB_EWR_MEAN_S32; + dvp_knode_to(&m_pNodes[31], DVP_EMean_t)->mean = m_images[11]; + dvp_knode_to(&m_pNodes[31], DVP_EMean_t)->data = m_images[1]; + dvp_knode_to(&m_pNodes[31], DVP_EMean_t)->mask = m_images[46]; + dvp_knode_to(&m_pNodes[31], DVP_EMean_t)->weight = IIR_ALPHA_S32; + m_pNodes[31].header.affinity = DVP_CORE_DSP; + + m_pNodes[32].header.kernel = DVP_KN_VLIB_EWR_VAR_S16; + dvp_knode_to(&m_pNodes[32], DVP_EMean_t)->var = m_images[12]; + dvp_knode_to(&m_pNodes[32], DVP_EMean_t)->mean = m_images[10]; + dvp_knode_to(&m_pNodes[32], DVP_EMean_t)->data = m_images[1]; + dvp_knode_to(&m_pNodes[32], DVP_EMean_t)->mask = m_images[47]; + dvp_knode_to(&m_pNodes[32], DVP_EMean_t)->weight = IIR_ALPHA_S16; + m_pNodes[32].header.affinity = DVP_CORE_DSP; + + m_pNodes[33].header.kernel = DVP_KN_VLIB_EWR_VAR_S32; + dvp_knode_to(&m_pNodes[33], DVP_EMean_t)->var = m_images[13]; + dvp_knode_to(&m_pNodes[33], DVP_EMean_t)->mean = m_images[11]; + dvp_knode_to(&m_pNodes[33], DVP_EMean_t)->data = m_images[1]; + dvp_knode_to(&m_pNodes[33], DVP_EMean_t)->mask = m_images[48]; + dvp_knode_to(&m_pNodes[33], DVP_EMean_t)->weight = IIR_ALPHA_S32; + m_pNodes[33].header.affinity = DVP_CORE_DSP; + + m_pNodes[34].header.kernel = DVP_KN_VLIB_UWR_MEAN_S16; + dvp_knode_to(&m_pNodes[34], DVP_UMean_t)->old_mean = m_images[10]; + dvp_knode_to(&m_pNodes[34], DVP_UMean_t)->new_mean = m_images[10]; + dvp_knode_to(&m_pNodes[34], DVP_UMean_t)->old_data = m_images[1]; + dvp_knode_to(&m_pNodes[34], DVP_UMean_t)->new_data = m_images[1]; + dvp_knode_to(&m_pNodes[34], DVP_UMean_t)->old_mask = m_images[49]; + dvp_knode_to(&m_pNodes[34], DVP_UMean_t)->new_mask = m_images[49]; + dvp_knode_to(&m_pNodes[34], DVP_UMean_t)->bufferLength = 10; + m_pNodes[34].header.affinity = DVP_CORE_DSP; + + m_pNodes[35].header.kernel = DVP_KN_VLIB_UWR_VAR_S16; + dvp_knode_to(&m_pNodes[35], DVP_UMean_t)->old_var = m_images[12]; + dvp_knode_to(&m_pNodes[35], DVP_UMean_t)->new_var = m_images[12]; + dvp_knode_to(&m_pNodes[35], DVP_UMean_t)->old_mean = m_images[10]; + dvp_knode_to(&m_pNodes[35], DVP_UMean_t)->new_mean = m_images[10]; + dvp_knode_to(&m_pNodes[35], DVP_UMean_t)->old_data = m_images[1]; + dvp_knode_to(&m_pNodes[35], DVP_UMean_t)->new_data = m_images[1]; + dvp_knode_to(&m_pNodes[35], DVP_UMean_t)->old_mask = m_images[50]; + dvp_knode_to(&m_pNodes[35], DVP_UMean_t)->new_mask = m_images[50]; + dvp_knode_to(&m_pNodes[35], DVP_UMean_t)->bufferLength = 10; + m_pNodes[35].header.affinity = DVP_CORE_DSP; + + m_pNodes[36].header.kernel = DVP_KN_VLIB_LEGENDRE_MOMENTS_INIT; + dvp_knode_to(&m_pNodes[36], DVP_LegendreMoments_t)->lPoly = m_buffers[13]; + dvp_knode_to(&m_pNodes[36], DVP_LegendreMoments_t)->order = LGM_ORDER; + + m_pNodes[37].header.kernel = DVP_KN_VLIB_LEGENDRE_MOMENTS; + dvp_knode_to(&m_pNodes[37], DVP_LegendreMoments_t)->im = m_images[2]; + dvp_knode_to(&m_pNodes[37], DVP_LegendreMoments_t)->lPoly = m_buffers[13]; + dvp_knode_to(&m_pNodes[37], DVP_LegendreMoments_t)->lMoments = m_buffers[14]; + dvp_knode_to(&m_pNodes[37], DVP_LegendreMoments_t)->order = LGM_ORDER; + + m_pNodes[38].header.kernel = DVP_KN_NV12_TO_YUV444p; + dvp_knode_to(&m_pNodes[38], DVP_Transform_t)->input = m_images[53]; + dvp_knode_to(&m_pNodes[38], DVP_Transform_t)->output = m_images[54]; + m_pNodes[38].header.affinity = DVP_CORE_DSP; + + m_pNodes[39].header.kernel = DVP_KN_CANNY_NONMAX_SUPPRESSION; + dvp_knode_to(&m_pNodes[39], DVP_CannyNonMaxSuppression_t)->inGradX = m_images[40]; + dvp_knode_to(&m_pNodes[39], DVP_CannyNonMaxSuppression_t)->inGradY = m_images[41]; + dvp_knode_to(&m_pNodes[39], DVP_CannyNonMaxSuppression_t)->inMag = m_images[42]; + dvp_knode_to(&m_pNodes[39], DVP_CannyNonMaxSuppression_t)->output = m_images[55]; + m_pNodes[39].header.affinity = DVP_CORE_DSP; + + m_pNodes[40].header.kernel = DVP_KN_VLIB_HYST_THRESHOLD; + dvp_knode_to(&m_pNodes[40], DVP_CannyHystThresholding_t)->inMag = m_images[42]; + dvp_knode_to(&m_pNodes[40], DVP_CannyHystThresholding_t)->inEdgeMap = m_images[55]; + dvp_knode_to(&m_pNodes[40], DVP_CannyHystThresholding_t)->output = m_images[56]; //scratch + dvp_knode_to(&m_pNodes[40], DVP_CannyHystThresholding_t)->loThresh = 35; + dvp_knode_to(&m_pNodes[40], DVP_CannyHystThresholding_t)->hiThresh = 122; + + m_pNodes[41].header.kernel = DVP_KN_VLIB_KALMAN_2x4; + dvp_knode_to(&m_pNodes[41], DVP_KalmanFilter_t)->inMeasurements = m_buffers[15]; + dvp_knode_to(&m_pNodes[41], DVP_KalmanFilter_t)->transition = m_buffers[16]; + dvp_knode_to(&m_pNodes[41], DVP_KalmanFilter_t)->errorCov = m_buffers[17]; + dvp_knode_to(&m_pNodes[41], DVP_KalmanFilter_t)->predictedErrorCov = m_buffers[18]; + dvp_knode_to(&m_pNodes[41], DVP_KalmanFilter_t)->state = m_buffers[19]; + dvp_knode_to(&m_pNodes[41], DVP_KalmanFilter_t)->predictedState = m_buffers[20]; + dvp_knode_to(&m_pNodes[41], DVP_KalmanFilter_t)->measurement = m_buffers[21]; + dvp_knode_to(&m_pNodes[41], DVP_KalmanFilter_t)->processNoiseCov = m_buffers[22]; + dvp_knode_to(&m_pNodes[41], DVP_KalmanFilter_t)->measurementNoiseCov = m_buffers[23]; + dvp_knode_to(&m_pNodes[41], DVP_KalmanFilter_t)->kalmanGain = m_buffers[24]; + dvp_knode_to(&m_pNodes[41], DVP_KalmanFilter_t)->temp1 = m_buffers[25]; + dvp_knode_to(&m_pNodes[41], DVP_KalmanFilter_t)->temp2 = m_buffers[26]; + dvp_knode_to(&m_pNodes[41], DVP_KalmanFilter_t)->temp3 = m_buffers[27]; + dvp_knode_to(&m_pNodes[41], DVP_KalmanFilter_t)->nMeasurements = m_width*m_height; + dvp_knode_to(&m_pNodes[41], DVP_KalmanFilter_t)->sD = sD_2x4; + dvp_knode_to(&m_pNodes[41], DVP_KalmanFilter_t)->mD = mD_2x4; + + m_pNodes[42].header.kernel = DVP_KN_VLIB_KALMAN_4x6; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->inMeasurements = m_buffers[28]; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->transition = m_buffers[29]; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->errorCov = m_buffers[30]; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->predictedErrorCov = m_buffers[31]; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->state = m_buffers[32]; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->predictedState = m_buffers[33]; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->measurement = m_buffers[34]; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->processNoiseCov = m_buffers[35]; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->measurementNoiseCov = m_buffers[36]; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->kalmanGain = m_buffers[37]; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->temp1 = m_buffers[38]; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->temp2 = m_buffers[39]; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->temp3 = m_buffers[40]; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->scaleFactor = 5; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->nMeasurements = m_width*m_height; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->sD = sD_4x6; + dvp_knode_to(&m_pNodes[42], DVP_KalmanFilter_t)->mD = mD_4x6; + + m_pNodes[43].header.kernel = DVP_KN_VLIB_NEDLER_MEAD_SIMPLEX_16; + dvp_knode_to(&m_pNodes[43], DVP_Simplex_t)->start = m_buffers[41]; + dvp_knode_to(&m_pNodes[43], DVP_Simplex_t)->step = m_buffers[42]; + dvp_knode_to(&m_pNodes[43], DVP_Simplex_t)->stop = m_buffers[43]; + dvp_knode_to(&m_pNodes[43], DVP_Simplex_t)->intBuf[0] = m_buffers[44]; + dvp_knode_to(&m_pNodes[43], DVP_Simplex_t)->intBuf[1] = m_buffers[45]; + dvp_knode_to(&m_pNodes[43], DVP_Simplex_t)->intBuf[2] = m_buffers[46]; + dvp_knode_to(&m_pNodes[43], DVP_Simplex_t)->intBuf[3] = m_buffers[47]; + dvp_knode_to(&m_pNodes[43], DVP_Simplex_t)->intBuf[4] = m_buffers[48]; + dvp_knode_to(&m_pNodes[43], DVP_Simplex_t)->intBuf[5] = m_buffers[49]; + dvp_knode_to(&m_pNodes[43], DVP_Simplex_t)->N_val = SimplexN; + dvp_knode_to(&m_pNodes[43], DVP_Simplex_t)->N_INV = 32767 / SimplexN; + dvp_knode_to(&m_pNodes[43], DVP_Simplex_t)->MaxIteration = 200; + dvp_knode_to(&m_pNodes[43], DVP_Simplex_t)->EPSILON = 0.00001 * MAX_S32_S/MAX_4p27; + dvp_knode_to(&m_pNodes[43], DVP_Simplex_t)->addtlArgs.n = SimplexN; + dvp_knode_to(&m_pNodes[43], DVP_Simplex_t)->addtlArgs.coeff = 10; + + m_pNodes[44].header.kernel = DVP_KN_VLIB_NEDLER_MEAD_SIMPLEX_3D; + dvp_knode_to(&m_pNodes[44], DVP_Simplex_t)->start = m_buffers[50]; + dvp_knode_to(&m_pNodes[44], DVP_Simplex_t)->step = m_buffers[51]; + dvp_knode_to(&m_pNodes[44], DVP_Simplex_t)->stop = m_buffers[52]; + dvp_knode_to(&m_pNodes[44], DVP_Simplex_t)->intBuf[0] = m_buffers[53]; + dvp_knode_to(&m_pNodes[44], DVP_Simplex_t)->intBuf[1] = m_buffers[54]; + dvp_knode_to(&m_pNodes[44], DVP_Simplex_t)->intBuf[2] = m_buffers[55]; + dvp_knode_to(&m_pNodes[44], DVP_Simplex_t)->intBuf[3] = m_buffers[56]; + dvp_knode_to(&m_pNodes[44], DVP_Simplex_t)->intBuf[4] = m_buffers[57]; + dvp_knode_to(&m_pNodes[44], DVP_Simplex_t)->intBuf[5] = m_buffers[58]; + dvp_knode_to(&m_pNodes[44], DVP_Simplex_t)->MaxIteration = 200; + dvp_knode_to(&m_pNodes[44], DVP_Simplex_t)->EPSILON = 0.00001 * MAX_S32_S/MAX_4p27; + dvp_knode_to(&m_pNodes[44], DVP_Simplex_t)->addtlArgs.n = SimplexN; + dvp_knode_to(&m_pNodes[44], DVP_Simplex_t)->addtlArgs.coeff = 10; + + m_pNodes[45].header.kernel = DVP_KN_VLIB_INTEGRAL_IMAGE_16; + dvp_knode_to(&m_pNodes[45], DVP_Transform_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[45], DVP_Transform_t)->output = m_images[57]; + + m_pNodes[46].header.kernel = DVP_KN_VLIB_EXTRACT_BACK_8_16; + dvp_knode_to(&m_pNodes[46], DVP_Transform_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[46], DVP_Transform_t)->output = m_images[58]; + + m_pNodes[47].header.kernel = DVP_KN_VLIB_GAUSSIAN_5x5_PYRAMID_8; + dvp_knode_to(&m_pNodes[47], DVP_Gradient_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[47], DVP_Gradient_t)->output = m_images[59]; + dvp_knode_to(&m_pNodes[47], DVP_Gradient_t)->scratch = m_images[61]; + + m_pNodes[48].header.kernel = DVP_KN_VLIB_GAUSSIAN_5x5_PYRAMID_16; + dvp_knode_to(&m_pNodes[48], DVP_Gradient_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[48], DVP_Gradient_t)->output = m_images[60]; + dvp_knode_to(&m_pNodes[48], DVP_Gradient_t)->scratch = m_images[61]; + + m_pNodes[49].header.kernel = DVP_KN_VLIB_HISTOGRAM_ND_16; + dvp_knode_to(&m_pNodes[49], DVP_Histogram_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[49], DVP_Histogram_t)->numBinsArray = m_buffers[59]; + dvp_knode_to(&m_pNodes[49], DVP_Histogram_t)->h[0] = m_buffers[60]; + dvp_knode_to(&m_pNodes[49], DVP_Histogram_t)->h[1] = m_buffers[61]; + dvp_knode_to(&m_pNodes[49], DVP_Histogram_t)->h[2] = m_buffers[62]; + dvp_knode_to(&m_pNodes[49], DVP_Histogram_t)->hOut = m_buffers[63]; + dvp_knode_to(&m_pNodes[49], DVP_Histogram_t)->dimX = HIST_ND_DIMX; + dvp_knode_to(&m_pNodes[49], DVP_Histogram_t)->binWeight = 1; + dvp_knode_to(&m_pNodes[49], DVP_Histogram_t)->clearFlag = 0; + m_buffers[59].pData[0] = 32; m_buffers[59].pData[1] = 32; m_buffers[59].pData[2] = 32; m_buffers[59].pData[3] = 32; + tmpPtr = (DVP_S16*)m_buffers[60].pData; + tmpPtr[0] = 256; tmpPtr[1] = 256; tmpPtr[2] = 256; tmpPtr[3] = 256; + + m_pNodes[50].header.kernel = DVP_KN_VLIB_PACK_MASK_32; + dvp_knode_to(&m_pNodes[50], DVP_Transform_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[50], DVP_Transform_t)->output = m_images[62]; + + m_pNodes[51].header.kernel = DVP_KN_VLIB_UNPACK_MASK_32; + dvp_knode_to(&m_pNodes[51], DVP_Transform_t)->input = m_images[62]; + dvp_knode_to(&m_pNodes[51], DVP_Transform_t)->output = m_images[63]; + + m_pNodes[52].header.kernel = DVP_KN_VLIB_HARRIS_SCORE_7x7_U32; + dvp_knode_to(&m_pNodes[52], DVP_HarrisDSP_t)->inGradX = m_images[40]; + dvp_knode_to(&m_pNodes[52], DVP_HarrisDSP_t)->inGradY = m_images[41]; + dvp_knode_to(&m_pNodes[52], DVP_HarrisDSP_t)->scratch = m_buffers[0]; + dvp_knode_to(&m_pNodes[52], DVP_HarrisDSP_t)->harrisScore = m_images[64]; + dvp_knode_to(&m_pNodes[52], DVP_HarrisDSP_t)->k = 1310; + + m_pNodes[53].header.kernel = DVP_KN_VLIB_NONMAXSUPPRESS_U32; + dvp_knode_to(&m_pNodes[53], DVP_Nonmax_NxN_t)->input = m_images[64]; + dvp_knode_to(&m_pNodes[53], DVP_Nonmax_NxN_t)->pixIndex = m_buffers[64]; + dvp_knode_to(&m_pNodes[53], DVP_Nonmax_NxN_t)->scratch = m_buffers[65]; + dvp_knode_to(&m_pNodes[53], DVP_Nonmax_NxN_t)->threshold = 100; + dvp_knode_to(&m_pNodes[53], DVP_Nonmax_NxN_t)->p = 5; + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + + } + + if(m_testcore != DVP_CORE_MIN) { + for(uint32_t testnode=0; testnodeinput = m_images[m_camIdx]; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[4]; + + m_pNodes[1].header.kernel = DVP_KN_NV12_TO_YUV444p; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = m_images[m_camIdx]; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->output = m_images[5]; + + m_pNodes[2].header.kernel = DVP_KN_YUV444p_TO_UYVY; + dvp_knode_to(&m_pNodes[2], DVP_Transform_t)->input = m_images[5];//444p + dvp_knode_to(&m_pNodes[2], DVP_Transform_t)->output = m_images[6];//UYVY + + m_pNodes[3].header.kernel = DVP_KN_UYVY_TO_HSLp; + dvp_knode_to(&m_pNodes[3], DVP_Int2Pl_t)->input = m_images[6]; + dvp_knode_to(&m_pNodes[3], DVP_Int2Pl_t)->output1 = m_images[7]; + dvp_knode_to(&m_pNodes[3], DVP_Int2Pl_t)->output2 = m_images[8]; + dvp_knode_to(&m_pNodes[3], DVP_Int2Pl_t)->output3 = m_images[9]; + //m_pNodes[3].affinity = DVP_CORE_DSP; + + //DVP_KN_NV12_TO_UYVY + //m_pNodes[4].header.kernel = DVP_KN_NV12_TO_UYVY; + //dvp_knode_to(&m_pNodes[4], DVP_Transform_t)->input = m_images[m_camIdx];//NV12 + //dvp_knode_to(&m_pNodes[4], DVP_Transform_t)->output = m_images[10];//UYVY + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + status = CameraInit(this, m_fourcc); + if (status == STATUS_SUCCESS) + { + if (m_imgdbg_enabled && AllocateImageDebug(8)) + { + ImageDebug_Init(&m_imgdbg[0], &m_images[0], m_imgdbg_path, "00_input"); + ImageDebug_Init(&m_imgdbg[1], &m_images[4], m_imgdbg_path, "01_YUV444"); + ImageDebug_Init(&m_imgdbg[2], &m_images[5], m_imgdbg_path, "01_YUV444"); + ImageDebug_Init(&m_imgdbg[3], &m_images[6], m_imgdbg_path, "02_UYVY"); + ImageDebug_Init(&m_imgdbg[4], &m_images[7], m_imgdbg_path, "03_H"); + ImageDebug_Init(&m_imgdbg[5], &m_images[8], m_imgdbg_path, "03_S"); + ImageDebug_Init(&m_imgdbg[6], &m_images[9], m_imgdbg_path, "03_V"); + ImageDebug_Init(&m_imgdbg[7], &m_images[10], m_imgdbg_path, "04_UYVY"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + DVP_PRINT(DVP_ZONE_ENGINE, "About to process %u frames!\n",m_numFrames); + } + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} + +status_e TestVisionEngine::Test_UYVYScalingGraph() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_YUV) + DVP_MemType_e opType = DVP_MTYPE_DEFAULT; + +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + opType = DVP_MTYPE_MPUCACHED_1DTILED; +#endif + if (m_display_enabled) + m_display = DVP_Display_Create(m_width, m_height, m_width, m_height, DVP_DISPLAY_WIDTH, DVP_DISPLAY_HEIGHT, m_width, m_height, 0, 0, FOURCC_UYVY, 0, DVP_DISPLAY_NUM_BUFFERS); + if (m_hDVP) + { + if (AllocateImageStructs(6)) + { + DVP_Image_Init(&m_images[0], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[1], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[2], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[3], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[4], m_width/2, m_height/2, FOURCC_UYVY); + DVP_Image_Init(&m_images[5], m_width/4, m_height/4, FOURCC_UYVY); + m_camIdx = m_dispIdx = 0; + m_camMin = m_dispMin = 0; + m_camMax = m_dispMax = 4; + if (m_display_enabled) + { + DVP_Display_Alloc(m_display, &m_images[0]); + DVP_Display_Alloc(m_display, &m_images[1]); + DVP_Display_Alloc(m_display, &m_images[2]); + DVP_Display_Alloc(m_display, &m_images[3]); + } +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + else { + m_images[0].memType = DVP_MTYPE_MPUNONCACHED_2DTILED; + m_images[1].memType = DVP_MTYPE_MPUNONCACHED_2DTILED; + m_images[2].memType = DVP_MTYPE_MPUNONCACHED_2DTILED; + m_images[3].memType = DVP_MTYPE_MPUNONCACHED_2DTILED; + } +#endif + if (!DVP_Image_Alloc(m_hDVP, &m_images[0],(DVP_MemType_e)m_images[0].memType) || + !DVP_Image_Alloc(m_hDVP, &m_images[1],(DVP_MemType_e)m_images[1].memType) || + !DVP_Image_Alloc(m_hDVP, &m_images[2],(DVP_MemType_e)m_images[2].memType) || + !DVP_Image_Alloc(m_hDVP, &m_images[3],(DVP_MemType_e)m_images[3].memType) || + !DVP_Image_Alloc(m_hDVP, &m_images[4], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[5], opType)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + if (AllocateNodes(2) && AllocateSections(&m_graphs[0], 1)) + { + // initialize the data in the nodes... + m_pNodes[0].header.kernel = DVP_KN_YUV_UYVY_HALF_SCALE; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = m_images[m_camIdx]; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[4]; + + m_pNodes[1].header.kernel = DVP_KN_YUV_UYVY_QTR_SCALE; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = m_images[m_camIdx]; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->output = m_images[5]; + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + status = CameraInit(this, m_images[0].color); + if (status == STATUS_SUCCESS) + { + if (m_imgdbg_enabled && AllocateImageDebug(2)) + { + //ImageDebug_Init(&m_imgdbg[0], &m_images[0], m_imgdbg_path, "00_input"); + ImageDebug_Init(&m_imgdbg[0], &m_images[4], m_imgdbg_path, "01_half"); + ImageDebug_Init(&m_imgdbg[1], &m_images[5], m_imgdbg_path, "02_qtr"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + DVP_PRINT(DVP_ZONE_ENGINE, "About to process %u frames!\n",m_numFrames); + } + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} + + +status_e TestVisionEngine::Test_Rotate() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_YUV) + if (m_display_enabled) + m_display = DVP_Display_Create(m_width, m_height, m_width, m_height, DVP_DISPLAY_WIDTH, DVP_DISPLAY_HEIGHT, m_width, m_height, 0, 0, FOURCC_UYVY, 0, DVP_DISPLAY_NUM_BUFFERS); + if (m_hDVP) + { + if (AllocateImageStructs(9)) + { + DVP_Image_Init(&m_images[0], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[1], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[2], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[3], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[4], m_width, m_height, FOURCC_IYUV); + DVP_Image_Init(&m_images[5], m_height, m_width, FOURCC_IYUV); + DVP_Image_Init(&m_images[6], m_height, m_width, FOURCC_IYUV); + DVP_Image_Init(&m_images[7], m_height, m_width, FOURCC_UYVY); + DVP_Image_Init(&m_images[8], m_height, m_width, FOURCC_UYVY); + m_camIdx = m_dispIdx = 0; + m_camMin = m_dispMin = 0; + m_camMax = m_dispMax = 4; + if (m_display_enabled) + { + DVP_Display_Alloc(m_display, &m_images[0]); + DVP_Display_Alloc(m_display, &m_images[1]); + DVP_Display_Alloc(m_display, &m_images[2]); + DVP_Display_Alloc(m_display, &m_images[3]); + } +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + else { + m_images[0].memType = DVP_MTYPE_MPUNONCACHED_2DTILED; + m_images[1].memType = DVP_MTYPE_MPUNONCACHED_2DTILED; + m_images[2].memType = DVP_MTYPE_MPUNONCACHED_2DTILED; + m_images[3].memType = DVP_MTYPE_MPUNONCACHED_2DTILED; + } +#endif + if (!DVP_Image_Alloc(m_hDVP, &m_images[0],(DVP_MemType_e)m_images[0].memType) || + !DVP_Image_Alloc(m_hDVP, &m_images[1],(DVP_MemType_e)m_images[1].memType) || + !DVP_Image_Alloc(m_hDVP, &m_images[2],(DVP_MemType_e)m_images[2].memType) || + !DVP_Image_Alloc(m_hDVP, &m_images[3],(DVP_MemType_e)m_images[3].memType) || + !DVP_Image_Alloc(m_hDVP, &m_images[4], DVP_MTYPE_MPUCACHED_VIRTUAL) || + !DVP_Image_Alloc(m_hDVP, &m_images[5], DVP_MTYPE_MPUCACHED_VIRTUAL) || + !DVP_Image_Alloc(m_hDVP, &m_images[6], DVP_MTYPE_MPUCACHED_VIRTUAL) || + !DVP_Image_Alloc(m_hDVP, &m_images[7], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[8], DVP_MTYPE_DEFAULT)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + if (AllocateNodes(5) && AllocateSections(&m_graphs[0], 1)) + { + // initialize the data in the nodes... + m_pNodes[0].header.kernel = DVP_KN_UYVY_TO_YUV420p; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = m_images[m_camIdx]; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[4]; + m_pNodes[0].header.affinity = DVP_CORE_CPU; + + m_pNodes[1].header.kernel = DVP_KN_YUV_Y800_ROTATE_CW_90; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = m_images[4]; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->output = m_images[5]; + + m_pNodes[2].header.kernel = DVP_KN_YUV_Y800_ROTATE_CCW_90; + dvp_knode_to(&m_pNodes[2], DVP_Transform_t)->input = m_images[4]; + dvp_knode_to(&m_pNodes[2], DVP_Transform_t)->output = m_images[6]; + + m_pNodes[3].header.kernel = DVP_KN_YUV_UYVY_ROTATE_CW_90; + dvp_knode_to(&m_pNodes[3], DVP_Transform_t)->input = m_images[m_camIdx]; + dvp_knode_to(&m_pNodes[3], DVP_Transform_t)->output = m_images[7]; + + m_pNodes[4].header.kernel = DVP_KN_YUV_UYVY_ROTATE_CCW_90; + dvp_knode_to(&m_pNodes[4], DVP_Transform_t)->input = m_images[m_camIdx]; + dvp_knode_to(&m_pNodes[4], DVP_Transform_t)->output = m_images[8]; + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + + } + status = CameraInit(this, m_images[0].color); + if (status == STATUS_SUCCESS) + { + if (m_imgdbg_enabled && AllocateImageDebug(5)) + { + ImageDebug_Init(&m_imgdbg[0], &m_images[4], m_imgdbg_path, "01_input"); + ImageDebug_Init(&m_imgdbg[1], &m_images[5], m_imgdbg_path, "02_cw90"); + ImageDebug_Init(&m_imgdbg[2], &m_images[6], m_imgdbg_path, "03_ccw90"); + ImageDebug_Init(&m_imgdbg[3], &m_images[7], m_imgdbg_path, "04_cw90"); + ImageDebug_Init(&m_imgdbg[4], &m_images[8], m_imgdbg_path, "05_ccw90"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + DVP_PRINT(DVP_ZONE_ENGINE, "About to process %u frames!\n",m_numFrames); + } + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} + +status_e TestVisionEngine::Test_Disparity() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_VLIB) && defined(DVP_USE_YUV) + if (m_hDVP) + { + if (m_pCam == NULL) + { + m_pCam = VisionCamFactory(m_camtype); + if (m_pCam == NULL) + return STATUS_NOT_ENOUGH_MEMORY; + } + VisionCamStereoInfo info = {VCAM_STEREO_LAYOUT_LEFTRIGHT, 1}; + //VisionCamWhiteBalType white = VCAM_WHITE_BAL_CONTROL_AUTO; + VisionCamResType res; + uint32_t color = FOURCC_NV12; + m_sensorIndex = VCAM_SENSOR_STEREO; + m_capmode = VCAM_STEREO_MODE; + //int brightness = 50; + int32_t allocWidth; + int32_t allocHeight; + +#if 0 // Explicity specify combined width/height on test command line + if (info.layout == VCAM_STEREO_LAYOUT_LEFTRIGHT && info.subsampling == 1) { + m_width *= 2; + } else if (info.layout == VCAM_STEREO_LAYOUT_TOPBOTTOM && info.subsampling == 1) { + m_height *= 2; + } +#endif + + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->init(this)); + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_WIDTH, &m_width, sizeof(uint32_t))); + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_HEIGHT, &m_height, sizeof(uint32_t))); + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_COLOR_SPACE_FOURCC, &color, sizeof(fourcc_t))); + // Can't set ROTATION here, see below + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_FPS_FIXED, &m_fps, sizeof(uint32_t))); + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_NAME, m_name, (int32_t)strlen(m_name))); + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_CAP_MODE, &m_capmode, sizeof(m_capmode))); + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_SENSOR_SELECT, &m_sensorIndex, sizeof( m_sensorIndex) )); + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_STEREO_INFO, &info, sizeof(info))); + + memset(&res, 0, sizeof(res)); + // VCAM_PARAM_2DBUFFER_DIM should only be called after resolutions, color space, cap mode, and + // optionally stereo information is set. + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->getParameter(VCAM_PARAM_2DBUFFER_DIM, &res, sizeof(res))); + + allocWidth = res.mWidth; + allocHeight = res.mHeight; + + m_camIdx = m_dispIdx = 0; + m_camMin = m_dispMin = 0; + m_camMax = m_dispMax = 4; + + if (m_display_enabled) + m_display = DVP_Display_Create(m_width, m_height, allocWidth, allocHeight, DVP_DISPLAY_WIDTH, DVP_DISPLAY_HEIGHT, allocWidth, allocHeight, 0, 0, color, 0, m_dispMax+1); + + if (AllocateImageStructs(m_dispMax+4)) + { + for (m_dispIdx = m_dispMin; m_dispIdx < m_dispMax; m_dispIdx++) + { + DVP_Image_Init(&m_images[m_dispIdx], allocWidth, allocHeight, color); + m_images[m_dispIdx].width = m_width; + m_images[m_dispIdx].height = m_height; + } + + DVP_Image_Init(&m_images[m_dispMax+0], m_width/2, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[m_dispMax+1], m_width/2, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[m_dispMax+2], m_width/2, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[m_dispMax+3], m_width/2, m_height/2, FOURCC_YU24); + + if (m_display_enabled) { + for (m_dispIdx = m_dispMin; m_dispIdx < m_dispMax; m_dispIdx++) + if (DVP_Display_Alloc(m_display, &m_images[m_dispIdx]) == DVP_FALSE) + return STATUS_NOT_ENOUGH_MEMORY; + } +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + else { + for (m_dispIdx = m_dispMin; m_dispIdx < m_dispMax; m_dispIdx++) + m_images[m_dispIdx].memType = DVP_MTYPE_MPUNONCACHED_2DTILED; + } +#endif + for (m_dispIdx = m_dispMin; m_dispIdx < m_dispMax; m_dispIdx++) { + if (DVP_Image_Alloc(m_hDVP, &m_images[m_dispIdx],(DVP_MemType_e)m_images[m_dispIdx].memType) == DVP_FALSE) + return STATUS_NOT_ENOUGH_MEMORY; + } + + if (!DVP_Image_Alloc(m_hDVP, &m_images[m_dispMax+0], DVP_MTYPE_MPUCACHED_VIRTUAL) || + !DVP_Image_Alloc(m_hDVP, &m_images[m_dispMax+1], DVP_MTYPE_MPUCACHED_VIRTUAL) || + !DVP_Image_Alloc(m_hDVP, &m_images[m_dispMax+2], DVP_MTYPE_MPUCACHED_VIRTUAL) || + !DVP_Image_Alloc(m_hDVP, &m_images[m_dispMax+3], DVP_MTYPE_DEFAULT)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + +// VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_FLICKER,&m_flicker,sizeof(m_flicker))); +// VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_BRIGHTNESS, &brightness, sizeof(brightness))); +// VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_AWB_MODE, &white, sizeof(white))); +// VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_NAME, m_name, sizeof(m_name))); + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->useBuffers(&m_images[m_camIdx], m_camMax)); + // @todo BUG: Can't set ROTATION until after useBuffers + /** @todo Additionally, OMX-CAMERA STEREO mode can't handle the rotation values! */ + if (m_capmode != VCAM_STEREO_MODE) + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_ROTATION, &m_camera_rotation, sizeof(uint32_t))); + + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->enablePreviewCbk(m_camcallback)); + DVP_PerformanceStart(&m_capPerf); // we'll time the camera init to first capture + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->sendCommand(VCAM_CMD_PREVIEW_START)); + //VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_DO_MANUALFOCUS, &m_focusDepth, sizeof(m_focusDepth))); + + if (AllocateNodes(2) && AllocateSections(&m_graphs[0], 1)) + { + // initialize the data in the nodes... + m_pNodes[0].header.kernel = DVP_KN_VLIB_DISPARITY_SAD8; + dvp_knode_to(&m_pNodes[0], DVP_Disparity_t)->left = m_images[m_camIdx]; + dvp_knode_to(&m_pNodes[0], DVP_Disparity_t)->right = m_images[m_camIdx]; + dvp_knode_to(&m_pNodes[0], DVP_Disparity_t)->disparity = m_images[m_dispMax+0]; + dvp_knode_to(&m_pNodes[0], DVP_Disparity_t)->mincost = m_images[m_dispMax+1]; + dvp_knode_to(&m_pNodes[0], DVP_Disparity_t)->cost = m_images[m_dispMax+2]; + dvp_knode_to(&m_pNodes[0], DVP_Disparity_t)->displacement = 10; + + // initialize the data in the nodes... + m_pNodes[1].header.kernel = DVP_KN_NV12_TO_YUV444p; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = m_images[m_camIdx]; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->output = m_images[m_dispMax+3]; + //m_pNodes[1].header.affinity = DVP_CORE_CPU; + + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + if (m_imgdbg_enabled && AllocateImageDebug(5)) + { + ImageDebug_Init(&m_imgdbg[0], &m_images[m_camIdx], m_imgdbg_path, "01_input"); + ImageDebug_Init(&m_imgdbg[1], &m_images[m_dispMax+0], m_imgdbg_path, "02_disparity"); + ImageDebug_Init(&m_imgdbg[2], &m_images[m_dispMax+1], m_imgdbg_path, "03_mincost"); + ImageDebug_Init(&m_imgdbg[3], &m_images[m_dispMax+2], m_imgdbg_path, "04_cost"); + ImageDebug_Init(&m_imgdbg[4], &m_images[m_dispMax+3], m_imgdbg_path, "05_yuv444"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} + +status_e TestVisionEngine::Test_Tismo() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_TISMO) + m_imgdbg_enabled = true_e; + if (m_hDVP) + { + if (m_pCam == NULL) + { + m_pCam = VisionCamFactory(m_camtype); + if (m_pCam == NULL) + return STATUS_NOT_ENOUGH_MEMORY; + } +#define TOPBOTTOM 1 +#define DISPLAY_DISPARITY 0 +#define FULL_SCREEN_DISPARITY 1 +#if TOPBOTTOM + VisionCamStereoInfo info = {VCAM_STEREO_LAYOUT_TOPBOTTOM, 1}; +#else + VisionCamStereoInfo info = {VCAM_STEREO_LAYOUT_LEFTRIGHT, 1}; +#endif + //VisionCamWhiteBalType white = VCAM_WHITE_BAL_CONTROL_AUTO; + VisionCamResType res; + uint32_t color = FOURCC_NV12; //FOURCC_Y800;//FOURCC_NV12; + m_sensorIndex = VCAM_SENSOR_STEREO; + m_capmode = VCAM_STEREO_MODE; + //int brightness = 50; + int32_t allocWidth; + int32_t allocHeight; + int32_t argWidth = m_width; + int32_t argHeight = m_height; + + // Command line specifies width/height of each view. + if (info.layout == VCAM_STEREO_LAYOUT_LEFTRIGHT && info.subsampling == 1) { + m_width *= 2; + } else if (info.layout == VCAM_STEREO_LAYOUT_TOPBOTTOM && info.subsampling == 1) { + m_height *= 2; + } + + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->init(this)); + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_WIDTH, &m_width, sizeof(uint32_t))); + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_HEIGHT, &m_height, sizeof(uint32_t))); + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_COLOR_SPACE_FOURCC, &color, sizeof(fourcc_t))); + // Can't set ROTATION here, see below + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_FPS_FIXED, &m_fps, sizeof(uint32_t))); + if (m_camtype == VISIONCAM_FILE) + { + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_NAME, m_name, (int32_t)strlen(m_name))); + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_PATH, m_path, (int32_t)strlen(m_path))); + } + //VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_NAME, m_name, (int32_t)strlen(m_name))); + //VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_PATH, m_path, (int32_t)strlen(m_path))); + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_SENSOR_SELECT, &m_sensorIndex, sizeof( m_sensorIndex) )); + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_CAP_MODE, &m_capmode, sizeof(m_capmode))); + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_STEREO_INFO, &info, sizeof(info))); + + memset(&res, 0, sizeof(res)); + // VCAM_PARAM_2DBUFFER_DIM should only be called after resolutions, color space, cap mode, and + // optionally stereo information is set. + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->getParameter(VCAM_PARAM_2DBUFFER_DIM, &res, sizeof(res))); + +#if TOPBOTTOM && DISPLAY_DISPARITY + allocWidth = m_width*2; +#else + allocWidth = res.mWidth; +#endif + allocHeight = res.mHeight; + + m_camIdx = m_dispIdx = 0; + m_camMin = m_dispMin = 0; + m_camMax = m_dispMax = 4; + + if (m_display_enabled) +#if TOPBOTTOM && DISPLAY_DISPARITY +#if FULL_SCREEN_DISPARITY + m_display = DVP_Display_Create(m_width, m_height/2, allocWidth, allocHeight, DVP_DISPLAY_WIDTH, DVP_DISPLAY_HEIGHT, 640, 480, 0, m_width, color, 0, m_dispMax+1); +#else + m_display = DVP_Display_Create(m_width*2, m_height, allocWidth, allocHeight, DVP_DISPLAY_WIDTH, DVP_DISPLAY_HEIGHT, allocWidth, allocHeight, 0, 0, color, 0, m_dispMax+1); +#endif +#else + m_display = DVP_Display_Create(m_width, m_height, allocWidth, allocHeight, DVP_DISPLAY_WIDTH, DVP_DISPLAY_HEIGHT, allocWidth, allocHeight, 0, 0, color, 0, m_dispMax+1); +#endif + + if (AllocateImageStructs(m_dispMax+3)) + { + for (m_dispIdx = m_dispMin; m_dispIdx < m_dispMax; m_dispIdx++) + { + DVP_Image_Init(&m_images[m_dispIdx], allocWidth, allocHeight, color); + m_images[m_dispIdx].width = m_width; + m_images[m_dispIdx].height = m_height; + } + + DVP_Image_Init(&m_images[m_dispMax], argWidth, argHeight, FOURCC_NV12); //Disparity Map + DVP_Image_Init(&m_images[m_dispMax+1], argWidth, argHeight, FOURCC_Y800); //Valid Codes + DVP_Image_Init(&m_images[m_dispMax+2], argWidth, argHeight, FOURCC_NV12); //Right + + if (m_display_enabled) + { + for (m_dispIdx = m_dispMin; m_dispIdx < m_dispMax; m_dispIdx++) { + if (DVP_Display_Alloc(m_display, &m_images[m_dispIdx]) == DVP_FALSE) + return STATUS_NOT_ENOUGH_MEMORY; + + for (DVP_U32 y = 0; y < m_images[m_dispIdx].bufHeight; y++) { + int i = (y * m_images[m_dispIdx].y_stride); + memset(&m_images[m_dispIdx].pData[0][i], 0, m_images[m_dispIdx].bufWidth*m_images[m_dispIdx].x_stride); + } + for (DVP_U32 y = 0; y < m_images[m_dispIdx].bufHeight/2; y++) { + int i = (y * m_images[m_dispIdx].y_stride); + memset(&m_images[m_dispIdx].pData[1][i], 0x80, m_images[m_dispIdx].bufWidth*m_images[m_dispIdx].x_stride); + } + } + } + else { + for (m_dispIdx = m_dispMin; m_dispIdx < m_dispMax; m_dispIdx++) + { +#if defined(DVP_USE_GRALLOC) + m_images[m_dispIdx].memType = DVP_MTYPE_GRALLOC_2DTILED; +#elif defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + m_images[m_dispIdx].memType = DVP_MTYPE_MPUNONCACHED_2DTILED; +#endif + } + } + + for (m_dispIdx = m_dispMin; m_dispIdx < m_dispMax; m_dispIdx++) { + if (DVP_Image_Alloc(m_hDVP, &m_images[m_dispIdx],(DVP_MemType_e)m_images[m_dispIdx].memType) == DVP_FALSE) + return STATUS_NOT_ENOUGH_MEMORY; + } +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + if (!DVP_Image_Alloc(m_hDVP, &m_images[m_dispMax+0], DVP_MTYPE_MPUNONCACHED_2DTILED) || + !DVP_Image_Alloc(m_hDVP, &m_images[m_dispMax+1], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[m_dispMax+2], DVP_MTYPE_DEFAULT)) + return STATUS_NOT_ENOUGH_MEMORY; +#else + if (!DVP_Image_Alloc(m_hDVP, &m_images[m_dispMax+0], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[m_dispMax+1], DVP_MTYPE_DEFAULT) || + !DVP_Image_Alloc(m_hDVP, &m_images[m_dispMax+2], DVP_MTYPE_DEFAULT)) + return STATUS_NOT_ENOUGH_MEMORY; +#endif + } + else + return STATUS_NOT_ENOUGH_MEMORY; + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->useBuffers(&m_images[m_camIdx], m_camMax)); + // @todo BUG: Can't set ROTATION until after useBuffers + /** @todo Additionally, OMX-CAMERA STEREO mode can't handle the rotation values! */ + if (m_capmode != VCAM_STEREO_MODE) + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_ROTATION, &m_camera_rotation, sizeof(uint32_t))); + + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->enablePreviewCbk(m_camcallback)); + DVP_PerformanceStart(&m_capPerf); // we'll time the camera init to first capture + VCAM_COMPLAIN_IF_FAILED(status, m_pCam->sendCommand(VCAM_CMD_PREVIEW_START)); + //VCAM_COMPLAIN_IF_FAILED(status, m_pCam->setParameter(VCAM_PARAM_DO_MANUALFOCUS, &m_focusDepth, sizeof(m_focusDepth))); + if (AllocateNodes(1) && AllocateGraphs(1) && AllocateSections(&m_graphs[0], 1)) + { + // initialize the data in the nodes... +#ifdef DVP_USE_TISMO + m_pNodes[0].header.kernel = DVP_KN_TISMO_DISPARITY; +#else + m_pNodes[0].header.kernel = DVP_KN_DISPARITY_SAD8; +#endif + // construct the left and right images from the camera input + DVP_Image_t left = m_images[m_dispMin]; + DVP_Image_t right = m_images[m_dispMin]; + DVP_Image_t disp = m_images[m_dispMin]; + + left.width = argWidth; + left.height = argHeight; + right.width = argWidth; + right.height = argHeight; + disp.width = argWidth; + disp.height = argHeight; + + // y stride should be the same + if (info.layout == VCAM_STEREO_LAYOUT_LEFTRIGHT && info.subsampling == 1) { + right.pData[0] = right.pBuffer[0] + left.width*left.x_stride; + disp = m_images[m_dispMax]; + } else if (info.layout == VCAM_STEREO_LAYOUT_TOPBOTTOM && info.subsampling == 1) { + right.pData[0] = left.pBuffer[0] + left.height*left.y_stride; +#if DISPLAY_DISPARITY + disp.pData[0] = left.pBuffer[0] + left.width*left.x_stride; + disp.pData[1] = left.pBuffer[1] + left.width*left.x_stride; +#endif + } + + //Copy right frame to separate buffer: WORKAROUND + DVP_Image_Copy(&m_images[m_dispMax+2], &right); + dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->left = left; + dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->right = right; // m_images[m_dispMax+2]; +#if DISPLAY_DISPARITY + dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->output = disp; +#else + dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->output = m_images[m_dispMax]; +#endif + dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->invalid = m_images[m_dispMax+1]; + dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->dMin = 40; + dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->dMax = 80; + dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->windowSize = 11; + dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->consistency = 4; + dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->uniqueness = 160; + + // put all the nodes in the section. + m_correlation[0].portIdx = VCAM_PORT_PREVIEW; + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + + if (status == STATUS_SUCCESS) + { + if (m_imgdbg_enabled && AllocateImageDebug(5)) + { + m_dbgImage = m_images[m_dispMin]; +#if TOPBOTTOM +#if DISPLAY_DISPARITY + m_dbgImage.width = argWidth * 2; + m_dbgImage.y_stride *= 2; +#endif + m_dbgImage.height = m_height; +#else + m_dbgImage.width = m_width; +#endif + ImageDebug_Init(&m_imgdbg[0], &m_dbgImage, m_imgdbg_path, "tismo"); + ImageDebug_Init(&m_imgdbg[1], &dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->output, m_imgdbg_path, "01_disparity"); + ImageDebug_Init(&m_imgdbg[2], &dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->invalid, m_imgdbg_path, "02_invalid"); + ImageDebug_Init(&m_imgdbg[3], &dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->left, m_imgdbg_path, "02_left"); + ImageDebug_Init(&m_imgdbg[4], &dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->right, m_imgdbg_path, "02_right"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + DVP_PRINT(DVP_ZONE_ENGINE, "About to process %u frames!\n",m_numFrames); + } + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} + +status_e TestVisionEngine::Test_Imglib() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_IMGLIB) + DVP_MemType_e camType = DVP_MTYPE_DEFAULT; + DVP_MemType_e opType = DVP_MTYPE_DEFAULT; +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + camType = DVP_MTYPE_MPUNONCACHED_2DTILED; + opType = DVP_MTYPE_MPUNONCACHED_1DTILED; +#endif + DVP_S16 maskBlurNeg3x3[3][3] = {{-5, 20, 17} , + {19, -28, 13} , + {-22, 9, 33}}; + DVP_S16 maskBlur11x11[11][11] ={{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}}; + + DVP_S08 maskBlur11x11_8[11][11] ={{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}}; + + DVP_U08 maskSAD16x16[16][16] ={{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5} , + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}}; + if (m_hDVP) + { + if (AllocateImageStructs(72)) + { + DVP_Image_Init(&m_images[0], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[1], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[2], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[3], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[4], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[5], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[6], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[7], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[8], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[9], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[10], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[11], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[12], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[13], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[14], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[15], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[16], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[17], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[18], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[19], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[20], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[21], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[22], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[23], 3, 3, FOURCC_Y16); + DVP_Image_Init(&m_images[24], 5, 5, FOURCC_Y16); + DVP_Image_Init(&m_images[25], 7, 7, FOURCC_Y16); + DVP_Image_Init(&m_images[26], 11, 11, FOURCC_Y800); + DVP_Image_Init(&m_images[27], 11, 11, FOURCC_Y16); + DVP_Image_Init(&m_images[28], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[29], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[30], m_width, m_height, FOURCC_Y800); //conv 11x11 c8 + DVP_Image_Init(&m_images[31], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[32], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[33], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[34], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[35], m_width, m_height, FOURCC_YV16); + DVP_Image_Init(&m_images[36], m_width, m_height, FOURCC_RGB565); + DVP_Image_Init(&m_images[37], m_width, m_height, FOURCC_Y16); //clipping + DVP_Image_Init(&m_images[38], m_width, m_height, FOURCC_RGBA); //corr 3x3 c8 + DVP_Image_Init(&m_images[39], m_width, m_height, FOURCC_RGBA); //corr 3x3 c16 + DVP_Image_Init(&m_images[40], m_width, m_height, FOURCC_RGBA); //corr 3x3 i16 + DVP_Image_Init(&m_images[41], m_width, m_height, FOURCC_RGBA); //corr 5x5 c16 + DVP_Image_Init(&m_images[42], m_width, m_height, FOURCC_RGBA); //corr 11x11 c16 + DVP_Image_Init(&m_images[43], m_width, m_height, FOURCC_RGBA); //corr 11x11 c16 + DVP_Image_Init(&m_images[44], m_width, m_height, FOURCC_Y16); //corr gen c16 + DVP_Image_Init(&m_images[45], m_width, m_height, FOURCC_RGBA); //corr gen iq + DVP_Image_Init(&m_images[46], m_width, m_height, FOURCC_Y800); //median 3x3 + DVP_Image_Init(&m_images[47], m_width, m_height, FOURCC_Y16); //median 3x3 16s + DVP_Image_Init(&m_images[48], m_width, m_height, FOURCC_Y16); //expand + DVP_Image_Init(&m_images[49], m_width, m_height, FOURCC_Y800); //saturate + DVP_Image_Init(&m_images[50], m_width, m_height, FOURCC_Y16); //demuxbe Y + DVP_Image_Init(&m_images[51], m_width/2, m_height, FOURCC_Y16); //demuxbe cr + DVP_Image_Init(&m_images[52], m_width/2, m_height, FOURCC_Y16); //demuxbe cb + DVP_Image_Init(&m_images[53], m_width, m_height, FOURCC_Y16); //demuxbe Y + DVP_Image_Init(&m_images[54], m_width/2, m_height, FOURCC_Y16); //demuxbe cr + DVP_Image_Init(&m_images[55], m_width/2, m_height, FOURCC_Y16); //demuxbe cb + DVP_Image_Init(&m_images[56], m_width, m_height, FOURCC_Y800); //sad 8x8 + DVP_Image_Init(&m_images[57], m_width, m_height, FOURCC_Y800); //sad 16x16 + DVP_Image_Init(&m_images[58], 16, 16, FOURCC_Y800); //sad ref image + DVP_Image_Init(&m_images[59], m_width, m_height, FOURCC_Y800); //sad 3x3 + DVP_Image_Init(&m_images[60], m_width, m_height, FOURCC_Y800); //sad 5x5 + DVP_Image_Init(&m_images[61], m_width, m_height, FOURCC_Y800); //sad 7x7 + DVP_Image_Init(&m_images[62], m_width, m_height, FOURCC_Y800); //err_diff 8 + DVP_Image_Init(&m_images[63], m_width, m_height, FOURCC_Y16); //err_diff 16 + DVP_Image_Init(&m_images[64], m_width+2, 1, FOURCC_Y16); //err_diff scratch + DVP_Image_Init(&m_images[65], m_width, m_height, FOURCC_Y16); //fdct 8x8 + DVP_Image_Init(&m_images[66], m_width, m_height, FOURCC_Y16); //idct 8x8 + DVP_Image_Init(&m_images[67], m_width, m_height, FOURCC_RGBA); //mad 8x8 + DVP_Image_Init(&m_images[68], m_width, m_height, FOURCC_RGBA); //mad 16x16 + DVP_Image_Init(&m_images[69], m_width, m_height, FOURCC_Y16); // quantize + DVP_Image_Init(&m_images[70], m_width, m_height, FOURCC_Y16); // wave_horz + DVP_Image_Init(&m_images[71], m_width, m_height, FOURCC_Y16); // wave_vert + if (!DVP_Image_Alloc(m_hDVP, &m_images[0], camType) || + !DVP_Image_Alloc(m_hDVP, &m_images[1], opType) || // DEFAULT is 1DTILED when using TILER + !DVP_Image_Alloc(m_hDVP, &m_images[2], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[3], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[4], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[5], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[6], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[7], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[8], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[9], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[10], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[11], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[12], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[13], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[14], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[15], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[16], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[17], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[18], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[19], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[20], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[21], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[22], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[23], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[24], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[25], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[26], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[27], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[28], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[29], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[30], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[31], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[32], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[33], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[34], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[35], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[36], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[37], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[38], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[39], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[40], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[41], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[42], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[43], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[44], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[45], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[46], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[47], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[48], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[49], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[50], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[51], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[52], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[53], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[54], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[55], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[56], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[57], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[58], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[59], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[60], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[61], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[62], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[63], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[64], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[65], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[66], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[67], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[68], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[69], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[70], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[71], opType)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + if (AllocateBufferStructs(7)) + { + DVP_Buffer_Init(&m_buffers[0], 2, m_width*2); // scratch conv 5x5 7x7 + DVP_Buffer_Init(&m_buffers[1], 2, 256); //img histogream 8 + DVP_Buffer_Init(&m_buffers[2], 2, (1<<16)); //img histogream 16 + DVP_Buffer_Init(&m_buffers[3], 2, (1<<16)*4); //max temp buf required + DVP_Buffer_Init(&m_buffers[4], 2, 32); //quantize + DVP_Buffer_Init(&m_buffers[5], 2, 8); //wavelet + DVP_Buffer_Init(&m_buffers[6], 2, 8); //wavelet + if (!DVP_Buffer_Alloc(m_hDVP, &m_buffers[0], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[1], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[2], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[3], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[4], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[5], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[6], DVP_MTYPE_DEFAULT)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + if (AllocateNodes(61) && AllocateSections(&m_graphs[0], 1)) + { + // initialize the data in the nodes... + m_pNodes[0].header.kernel = DVP_KN_XYXY_TO_Y800; // Get Luma first + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[1]; + //m_pNodes[0].header.affinity = DVP_CORE_CPU; + + m_pNodes[1].header.kernel = DVP_KN_XSTRIDE_SHIFT; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = m_images[1]; // Use 8bit luma + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->output = m_images[2]; // Output 16bit luma + //m_pNodes[1].header.affinity = DVP_CORE_CPU; + + m_pNodes[2].header.kernel = DVP_KN_IMG_THR_GT2MAX_8; + dvp_knode_to(&m_pNodes[2], DVP_Threshold_t)->input = m_images[1]; // Use 8bit luma + dvp_knode_to(&m_pNodes[2], DVP_Threshold_t)->output = m_images[3]; + dvp_knode_to(&m_pNodes[2], DVP_Threshold_t)->thresh = 128; + //m_pNodes[2].header.affinity = DVP_CORE_CPU; + + m_pNodes[3].header.kernel = DVP_KN_IMG_THR_GT2THR_8; + dvp_knode_to(&m_pNodes[3], DVP_Threshold_t)->input = m_images[1]; // Use 8bit luma + dvp_knode_to(&m_pNodes[3], DVP_Threshold_t)->output = m_images[4]; + dvp_knode_to(&m_pNodes[3], DVP_Threshold_t)->thresh = 128; + //m_pNodes[3].header.affinity = DVP_CORE_CPU; + + m_pNodes[4].header.kernel = DVP_KN_IMG_THR_LE2MIN_8; + dvp_knode_to(&m_pNodes[4], DVP_Threshold_t)->input = m_images[1]; // Use 8bit luma + dvp_knode_to(&m_pNodes[4], DVP_Threshold_t)->output = m_images[5]; + dvp_knode_to(&m_pNodes[4], DVP_Threshold_t)->thresh = 128; + //m_pNodes[4].header.affinity = DVP_CORE_CPU; + + m_pNodes[5].header.kernel = DVP_KN_IMG_THR_LE2THR_8; + dvp_knode_to(&m_pNodes[5], DVP_Threshold_t)->input = m_images[1]; // Use 8bit luma + dvp_knode_to(&m_pNodes[5], DVP_Threshold_t)->output = m_images[6]; + dvp_knode_to(&m_pNodes[5], DVP_Threshold_t)->thresh = 128; + //m_pNodes[5].header.affinity = DVP_CORE_CPU; + + m_pNodes[6].header.kernel = DVP_KN_IMG_THR_GT2MAX_16; + dvp_knode_to(&m_pNodes[6], DVP_Threshold_t)->input = m_images[2]; // Use 16bit luma + dvp_knode_to(&m_pNodes[6], DVP_Threshold_t)->output = m_images[7]; + dvp_knode_to(&m_pNodes[6], DVP_Threshold_t)->thresh = (DVP_S16)0x8000; + //m_pNodes[6].header.affinity = DVP_CORE_CPU; + + m_pNodes[7].header.kernel = DVP_KN_IMG_THR_GT2THR_16; + dvp_knode_to(&m_pNodes[7], DVP_Threshold_t)->input = m_images[2]; // Use 16bit luma + dvp_knode_to(&m_pNodes[7], DVP_Threshold_t)->output = m_images[8]; + dvp_knode_to(&m_pNodes[7], DVP_Threshold_t)->thresh = (DVP_S16)0x8000; + //m_pNodes[7].header.affinity = DVP_CORE_CPU; + + m_pNodes[8].header.kernel = DVP_KN_IMG_THR_LE2MIN_16; + dvp_knode_to(&m_pNodes[8], DVP_Threshold_t)->input = m_images[2]; // Use 16bit luma + dvp_knode_to(&m_pNodes[8], DVP_Threshold_t)->output = m_images[9]; + dvp_knode_to(&m_pNodes[8], DVP_Threshold_t)->thresh = (DVP_S16)0x8000; + //m_pNodes[8].header.affinity = DVP_CORE_CPU; + + m_pNodes[9].header.kernel = DVP_KN_IMG_THR_LE2THR_16; + dvp_knode_to(&m_pNodes[9], DVP_Threshold_t)->input = m_images[2]; // Use 16bit luma + dvp_knode_to(&m_pNodes[9], DVP_Threshold_t)->output = m_images[10]; + dvp_knode_to(&m_pNodes[9], DVP_Threshold_t)->thresh = (DVP_S16)0x8000; + //m_pNodes[9].header.affinity = DVP_CORE_CPU; + + m_pNodes[10].header.kernel = DVP_KN_SOBEL_3x3_8s; + dvp_knode_to(&m_pNodes[10], DVP_Transform_t)->input = m_images[1]; // Use 8bit luma + dvp_knode_to(&m_pNodes[10], DVP_Transform_t)->output = m_images[11]; + //m_pNodes[10].header.affinity = DVP_CORE_CPU; + + m_pNodes[11].header.kernel = DVP_KN_IMG_SOBEL_3x3_8; + dvp_knode_to(&m_pNodes[11], DVP_Transform_t)->input = m_images[1]; // Use 8bit luma + dvp_knode_to(&m_pNodes[11], DVP_Transform_t)->output = m_images[12]; + //m_pNodes[11].header.affinity = DVP_CORE_CPU; + + m_pNodes[12].header.kernel = DVP_KN_SOBEL_5x5_8s; + dvp_knode_to(&m_pNodes[12], DVP_Transform_t)->input = m_images[1]; // Use 8bit luma + dvp_knode_to(&m_pNodes[12], DVP_Transform_t)->output = m_images[13]; + //m_pNodes[12].header.affinity = DVP_CORE_CPU; + + m_pNodes[13].header.kernel = DVP_KN_SOBEL_5x5_8; + dvp_knode_to(&m_pNodes[13], DVP_Transform_t)->input = m_images[1]; // Use 8bit luma + dvp_knode_to(&m_pNodes[13], DVP_Transform_t)->output = m_images[14]; + //m_pNodes[13].header.affinity = DVP_CORE_CPU; + + m_pNodes[14].header.kernel = DVP_KN_SOBEL_7x7_8s; + dvp_knode_to(&m_pNodes[14], DVP_Transform_t)->input = m_images[1]; // Use 8bit luma + dvp_knode_to(&m_pNodes[14], DVP_Transform_t)->output = m_images[15]; + //m_pNodes[14].header.affinity = DVP_CORE_CPU; + + m_pNodes[15].header.kernel = DVP_KN_SOBEL_7x7_8; + dvp_knode_to(&m_pNodes[15], DVP_Transform_t)->input = m_images[1]; // Use 8bit luma + dvp_knode_to(&m_pNodes[15], DVP_Transform_t)->output = m_images[16]; + //m_pNodes[15].header.affinity = DVP_CORE_CPU; + + m_pNodes[16].header.kernel = DVP_KN_IMG_SOBEL_3x3_16s; + dvp_knode_to(&m_pNodes[16], DVP_Transform_t)->input = m_images[2]; // Use 16bit luma + dvp_knode_to(&m_pNodes[16], DVP_Transform_t)->output = m_images[17]; + //m_pNodes[16].header.affinity = DVP_CORE_CPU; + + m_pNodes[17].header.kernel = DVP_KN_SOBEL_3x3_16; + dvp_knode_to(&m_pNodes[17], DVP_Transform_t)->input = m_images[2]; // Use 16bit luma + dvp_knode_to(&m_pNodes[17], DVP_Transform_t)->output = m_images[18]; + //m_pNodes[17].header.affinity = DVP_CORE_CPU; + + m_pNodes[18].header.kernel = DVP_KN_IMG_SOBEL_5x5_16s; + dvp_knode_to(&m_pNodes[18], DVP_Transform_t)->input = m_images[2]; // Use 16bit luma + dvp_knode_to(&m_pNodes[18], DVP_Transform_t)->output = m_images[19]; + //m_pNodes[18].header.affinity = DVP_CORE_CPU; + + m_pNodes[19].header.kernel = DVP_KN_SOBEL_5x5_16; + dvp_knode_to(&m_pNodes[19], DVP_Transform_t)->input = m_images[2]; // Use 16bit luma + dvp_knode_to(&m_pNodes[19], DVP_Transform_t)->output = m_images[20]; + //m_pNodes[19].header.affinity = DVP_CORE_CPU; + + m_pNodes[20].header.kernel = DVP_KN_IMG_SOBEL_7x7_16s; + dvp_knode_to(&m_pNodes[20], DVP_Transform_t)->input = m_images[2]; // Use 16bit luma + dvp_knode_to(&m_pNodes[20], DVP_Transform_t)->output = m_images[21]; + //m_pNodes[20].header.affinity = DVP_CORE_CPU; + + m_pNodes[21].header.kernel = DVP_KN_SOBEL_7x7_16; + dvp_knode_to(&m_pNodes[21], DVP_Transform_t)->input = m_images[2]; // Use 16bit luma + dvp_knode_to(&m_pNodes[21], DVP_Transform_t)->output = m_images[22]; + //m_pNodes[21].header.affinity = DVP_CORE_CPU; + + m_pNodes[22].header.kernel = DVP_KN_IMG_CONV_5x5_I8_C16; + dvp_knode_to(&m_pNodes[22], DVP_ImageConvolution_with_buffer_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[22], DVP_ImageConvolution_with_buffer_t)->output = m_images[28]; + dvp_knode_to(&m_pNodes[22], DVP_ImageConvolution_with_buffer_t)->mask = m_images[24]; + dvp_knode_to(&m_pNodes[22], DVP_ImageConvolution_with_buffer_t)->scratch = m_buffers[0]; + dvp_knode_to(&m_pNodes[22], DVP_ImageConvolution_with_buffer_t)->shiftMask = 9; + + m_pNodes[23].header.kernel = DVP_KN_IMG_CONV_7x7_I8_C16; + dvp_knode_to(&m_pNodes[23], DVP_ImageConvolution_with_buffer_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[23], DVP_ImageConvolution_with_buffer_t)->output = m_images[29]; + dvp_knode_to(&m_pNodes[23], DVP_ImageConvolution_with_buffer_t)->mask = m_images[25]; + dvp_knode_to(&m_pNodes[23], DVP_ImageConvolution_with_buffer_t)->scratch = m_buffers[0]; + dvp_knode_to(&m_pNodes[23], DVP_ImageConvolution_with_buffer_t)->shiftMask = 9; + + m_pNodes[24].header.kernel = DVP_KN_IMG_CONV_11x11; + dvp_knode_to(&m_pNodes[24], DVP_ImageConvolution_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[24], DVP_ImageConvolution_t)->output = m_images[30]; + dvp_knode_to(&m_pNodes[24], DVP_ImageConvolution_t)->mask = m_images[26]; + dvp_knode_to(&m_pNodes[24], DVP_ImageConvolution_t)->shiftMask = 9; + + m_pNodes[25].header.kernel = DVP_KN_IMG_CONV_3x3_I16s_C16; + dvp_knode_to(&m_pNodes[25], DVP_ImageConvolution_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[25], DVP_ImageConvolution_t)->output = m_images[31]; + dvp_knode_to(&m_pNodes[25], DVP_ImageConvolution_t)->mask = m_images[23]; + dvp_knode_to(&m_pNodes[25], DVP_ImageConvolution_t)->shiftMask = 13; + + m_pNodes[26].header.kernel = DVP_KN_IMG_CONV_5x5_I16s_C16; + dvp_knode_to(&m_pNodes[26], DVP_ImageConvolution_with_buffer_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[26], DVP_ImageConvolution_with_buffer_t)->output = m_images[32]; + dvp_knode_to(&m_pNodes[26], DVP_ImageConvolution_with_buffer_t)->mask = m_images[24]; + dvp_knode_to(&m_pNodes[26], DVP_ImageConvolution_with_buffer_t)->shiftMask = 13; + dvp_knode_to(&m_pNodes[26], DVP_ImageConvolution_with_buffer_t)->scratch = m_buffers[0]; + + m_pNodes[27].header.kernel = DVP_KN_IMG_CONV_7x7_I16s_C16; + dvp_knode_to(&m_pNodes[27], DVP_ImageConvolution_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[27], DVP_ImageConvolution_t)->output = m_images[33]; + dvp_knode_to(&m_pNodes[27], DVP_ImageConvolution_t)->mask = m_images[25]; + dvp_knode_to(&m_pNodes[27], DVP_ImageConvolution_t)->shiftMask = 13; + + m_pNodes[28].header.kernel = DVP_KN_IMG_CONV_11x11_I16s_C16; + dvp_knode_to(&m_pNodes[28], DVP_ImageConvolution_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[28], DVP_ImageConvolution_t)->output = m_images[34]; + dvp_knode_to(&m_pNodes[28], DVP_ImageConvolution_t)->mask = m_images[27]; + dvp_knode_to(&m_pNodes[28], DVP_ImageConvolution_t)->shiftMask = 13; + + m_pNodes[29].header.kernel = DVP_KN_UYVY_TO_YUV422p; + dvp_knode_to(&m_pNodes[29], DVP_Transform_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[29], DVP_Transform_t)->output = m_images[35]; + + m_pNodes[30].header.kernel = DVP_KN_IMG_YUV422p_TO_RGB565; + dvp_knode_to(&m_pNodes[30], DVP_Transform_t)->input = m_images[35]; // Use 16bit luma + dvp_knode_to(&m_pNodes[30], DVP_Transform_t)->output = m_images[36]; + + m_pNodes[31].header.kernel = DVP_KN_IMG_CLIPPING_16; + dvp_knode_to(&m_pNodes[31], DVP_CannyHystThresholding_t)->inMag = m_images[2]; + dvp_knode_to(&m_pNodes[31], DVP_CannyHystThresholding_t)->output = m_images[37]; + dvp_knode_to(&m_pNodes[31], DVP_CannyHystThresholding_t)->hiThresh = 128; + dvp_knode_to(&m_pNodes[31], DVP_CannyHystThresholding_t)->loThresh = 50; + + m_pNodes[32].header.kernel = DVP_KN_IMG_CORR_3x3; + dvp_knode_to(&m_pNodes[32], DVP_ImageCorrelation_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[32], DVP_ImageCorrelation_t)->output = m_images[38]; + dvp_knode_to(&m_pNodes[32], DVP_ImageCorrelation_t)->mask = m_images[26]; + dvp_knode_to(&m_pNodes[32], DVP_ImageCorrelation_t)->shift = 7; + dvp_knode_to(&m_pNodes[32], DVP_ImageCorrelation_t)->round = 64; + + m_pNodes[33].header.kernel = DVP_KN_IMG_CORR_3x3_I8_C16s; + dvp_knode_to(&m_pNodes[33], DVP_ImageCorrelation_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[33], DVP_ImageCorrelation_t)->output = m_images[39]; + dvp_knode_to(&m_pNodes[33], DVP_ImageCorrelation_t)->mask = m_images[23]; + + m_pNodes[34].header.kernel = DVP_KN_IMG_CORR_3x3_I16s_C16s; + dvp_knode_to(&m_pNodes[34], DVP_ImageCorrelation_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[34], DVP_ImageCorrelation_t)->output = m_images[40]; + dvp_knode_to(&m_pNodes[34], DVP_ImageCorrelation_t)->mask = m_images[23]; + dvp_knode_to(&m_pNodes[34], DVP_ImageCorrelation_t)->shift = 6; + dvp_knode_to(&m_pNodes[34], DVP_ImageCorrelation_t)->round = 1; + + m_pNodes[35].header.kernel = DVP_KN_IMG_CORR_5x5_I16s_C16s; + dvp_knode_to(&m_pNodes[35], DVP_ImageCorrelation_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[35], DVP_ImageCorrelation_t)->output = m_images[41]; + dvp_knode_to(&m_pNodes[35], DVP_ImageCorrelation_t)->mask = m_images[24]; + dvp_knode_to(&m_pNodes[35], DVP_ImageCorrelation_t)->shift = 9; + dvp_knode_to(&m_pNodes[35], DVP_ImageCorrelation_t)->round = 1; + + m_pNodes[36].header.kernel = DVP_KN_IMG_CORR_11x11_I8_C16s; + dvp_knode_to(&m_pNodes[36], DVP_ImageCorrelation_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[36], DVP_ImageCorrelation_t)->output = m_images[42]; + dvp_knode_to(&m_pNodes[36], DVP_ImageCorrelation_t)->mask = m_images[27]; + + m_pNodes[37].header.kernel = DVP_KN_IMG_CORR_11x11_I16s_C16s; + dvp_knode_to(&m_pNodes[37], DVP_ImageCorrelation_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[37], DVP_ImageCorrelation_t)->output = m_images[43]; + dvp_knode_to(&m_pNodes[37], DVP_ImageCorrelation_t)->mask = m_images[27]; + dvp_knode_to(&m_pNodes[37], DVP_ImageCorrelation_t)->shift = 13; + dvp_knode_to(&m_pNodes[37], DVP_ImageCorrelation_t)->round = 1; + + m_pNodes[38].header.kernel = DVP_KN_IMG_CORR_GEN_I16s_C16s; + dvp_knode_to(&m_pNodes[38], DVP_ImageCorrelation_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[38], DVP_ImageCorrelation_t)->output = m_images[44]; + dvp_knode_to(&m_pNodes[38], DVP_ImageCorrelation_t)->mask = m_images[27]; + dvp_knode_to(&m_pNodes[38], DVP_ImageCorrelation_t)->shift = 13; + dvp_knode_to(&m_pNodes[38], DVP_ImageCorrelation_t)->round = 1; + dvp_knode_to(&m_pNodes[38], DVP_ImageCorrelation_t)->m = 11; + + m_pNodes[39].header.kernel = DVP_KN_IMG_CORR_GEN_IQ; + dvp_knode_to(&m_pNodes[39], DVP_ImageCorrelation_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[39], DVP_ImageCorrelation_t)->output = m_images[45]; + dvp_knode_to(&m_pNodes[39], DVP_ImageCorrelation_t)->mask = m_images[27]; + dvp_knode_to(&m_pNodes[39], DVP_ImageCorrelation_t)->shift = 13; + dvp_knode_to(&m_pNodes[39], DVP_ImageCorrelation_t)->round = 1; + dvp_knode_to(&m_pNodes[39], DVP_ImageCorrelation_t)->m = 11; + dvp_knode_to(&m_pNodes[39], DVP_ImageCorrelation_t)->x_qpt = 20; + dvp_knode_to(&m_pNodes[39], DVP_ImageCorrelation_t)->h_qpt = 15; + dvp_knode_to(&m_pNodes[39], DVP_ImageCorrelation_t)->y_qpt = 10; + + m_pNodes[40].header.kernel = DVP_KN_IMG_HISTOGRAM_8; + dvp_knode_to(&m_pNodes[40], DVP_Histogram_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[40], DVP_Histogram_t)->histArray = m_buffers[3]; + dvp_knode_to(&m_pNodes[40], DVP_Histogram_t)->hOut = m_buffers[1]; + dvp_knode_to(&m_pNodes[40], DVP_Histogram_t)->binWeight = 1; + + m_pNodes[41].header.kernel = DVP_KN_IMG_HISTOGRAM_16; + dvp_knode_to(&m_pNodes[41], DVP_Histogram_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[41], DVP_Histogram_t)->histArray = m_buffers[3]; + dvp_knode_to(&m_pNodes[41], DVP_Histogram_t)->hOut = m_buffers[2]; + dvp_knode_to(&m_pNodes[41], DVP_Histogram_t)->binWeight = 1; + dvp_knode_to(&m_pNodes[41], DVP_Histogram_t)->numBins = 8; + + m_pNodes[42].header.kernel = DVP_KN_IMG_MEDIAN_3x3_8; + dvp_knode_to(&m_pNodes[42], DVP_Transform_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[42], DVP_Transform_t)->output = m_images[46]; + + m_pNodes[43].header.kernel = DVP_KN_IMG_MEDIAN_3x3_16s; + dvp_knode_to(&m_pNodes[43], DVP_Transform_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[43], DVP_Transform_t)->output = m_images[47]; + + m_pNodes[44].header.kernel = DVP_KN_IMG_PIX_EXPAND; + dvp_knode_to(&m_pNodes[44], DVP_Transform_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[44], DVP_Transform_t)->output = m_images[48]; + + m_pNodes[45].header.kernel = DVP_KN_IMG_PIX_SAT; + dvp_knode_to(&m_pNodes[45], DVP_Transform_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[45], DVP_Transform_t)->output = m_images[49]; + + m_pNodes[46].header.kernel = DVP_KN_IMG_YC_DEMUX_BE16_8; + dvp_knode_to(&m_pNodes[46], DVP_Int2Pl_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[46], DVP_Int2Pl_t)->output1 = m_images[50]; + dvp_knode_to(&m_pNodes[46], DVP_Int2Pl_t)->output2 = m_images[51]; + dvp_knode_to(&m_pNodes[46], DVP_Int2Pl_t)->output3 = m_images[52]; + + m_pNodes[47].header.kernel = DVP_KN_IMG_YC_DEMUX_LE16_8; + dvp_knode_to(&m_pNodes[47], DVP_Int2Pl_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[47], DVP_Int2Pl_t)->output1 = m_images[53]; + dvp_knode_to(&m_pNodes[47], DVP_Int2Pl_t)->output2 = m_images[54]; + dvp_knode_to(&m_pNodes[47], DVP_Int2Pl_t)->output3 = m_images[55]; + + if(m_testcore == DVP_CORE_DSP || DVP_CORE_CPU) + m_pNodes[48].header.kernel = DVP_KN_IMG_SAD_8x8; +#if defined(DVP_USE_VRUN) + else + m_pNodes[48].header.kernel = DVP_KN_VRUN_SAD_8x8; +#endif + dvp_knode_to(&m_pNodes[48], DVP_SAD_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[48], DVP_SAD_t)->output = m_images[56]; + dvp_knode_to(&m_pNodes[48], DVP_SAD_t)->refImg = m_images[58]; + dvp_knode_to(&m_pNodes[48], DVP_SAD_t)->shiftMask = 4; + dvp_knode_to(&m_pNodes[48], DVP_SAD_t)->refPitch = 8; + dvp_knode_to(&m_pNodes[48], DVP_SAD_t)->refStartOffset = 0; + + if(m_testcore == DVP_CORE_DSP || DVP_CORE_CPU) + m_pNodes[49].header.kernel = DVP_KN_IMG_SAD_16x16; +#if defined(DVP_USE_VRUN) + else + m_pNodes[49].header.kernel = DVP_KN_VRUN_SAD_16x16; +#endif + dvp_knode_to(&m_pNodes[49], DVP_SAD_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[49], DVP_SAD_t)->output = m_images[57]; + dvp_knode_to(&m_pNodes[49], DVP_SAD_t)->refImg = m_images[58]; + dvp_knode_to(&m_pNodes[49], DVP_SAD_t)->shiftMask = 8; + dvp_knode_to(&m_pNodes[49], DVP_SAD_t)->refPitch = 16; + dvp_knode_to(&m_pNodes[49], DVP_SAD_t)->refStartOffset = 0; + + if(m_testcore == DVP_CORE_DSP || DVP_CORE_CPU) + m_pNodes[50].header.kernel = DVP_KN_IMG_SAD_3x3; +#if defined(DVP_USE_VRUN) + else + m_pNodes[50].header.kernel = DVP_KN_VRUN_SAD_3x3; +#endif + dvp_knode_to(&m_pNodes[50], DVP_SAD_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[50], DVP_SAD_t)->output = m_images[59]; + dvp_knode_to(&m_pNodes[50], DVP_SAD_t)->refImg = m_images[58]; + dvp_knode_to(&m_pNodes[50], DVP_SAD_t)->refPitch = 3; + dvp_knode_to(&m_pNodes[50], DVP_SAD_t)->refStartOffset = 0; + + if(m_testcore == DVP_CORE_DSP || DVP_CORE_CPU) + m_pNodes[51].header.kernel = DVP_KN_IMG_SAD_5x5; +#if defined(DVP_USE_VRUN) + else + m_pNodes[51].header.kernel = DVP_KN_VRUN_SAD_5x5; +#endif + dvp_knode_to(&m_pNodes[51], DVP_SAD_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[51], DVP_SAD_t)->output = m_images[60]; + dvp_knode_to(&m_pNodes[51], DVP_SAD_t)->refImg = m_images[58]; + dvp_knode_to(&m_pNodes[51], DVP_SAD_t)->refPitch = 5; + dvp_knode_to(&m_pNodes[51], DVP_SAD_t)->refStartOffset = 0; + + if(m_testcore == DVP_CORE_DSP || DVP_CORE_CPU) + m_pNodes[52].header.kernel = DVP_KN_IMG_SAD_7x7; +#if defined(DVP_USE_VRUN) + else + m_pNodes[52].header.kernel = DVP_KN_VRUN_SAD_7x7; +#endif + dvp_knode_to(&m_pNodes[52], DVP_SAD_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[52], DVP_SAD_t)->output = m_images[61]; + dvp_knode_to(&m_pNodes[52], DVP_SAD_t)->refImg = m_images[58]; + dvp_knode_to(&m_pNodes[52], DVP_SAD_t)->refPitch = 7; + dvp_knode_to(&m_pNodes[52], DVP_SAD_t)->refStartOffset = 0; + + m_pNodes[53].header.kernel = DVP_KN_IMG_ERRDIFF_BIN_8; + dvp_knode_to(&m_pNodes[53], DVP_Threshold_t)->input = m_images[62]; + dvp_knode_to(&m_pNodes[53], DVP_Threshold_t)->output = m_images[64]; //scratch + dvp_knode_to(&m_pNodes[53], DVP_Threshold_t)->thresh = 100; + + m_pNodes[54].header.kernel = DVP_KN_IMG_ERRDIFF_BIN_16; + dvp_knode_to(&m_pNodes[54], DVP_Threshold_t)->input = m_images[63]; + dvp_knode_to(&m_pNodes[54], DVP_Threshold_t)->output = m_images[64]; //scratch + dvp_knode_to(&m_pNodes[54], DVP_Threshold_t)->thresh = 100; + + m_pNodes[55].header.kernel = DVP_KN_IMG_FDCT_8x8; + dvp_knode_to(&m_pNodes[55], DVP_Transform_t)->input = m_images[65]; + + m_pNodes[56].header.kernel = DVP_KN_IMG_IDCT_8x8_12Q4; + dvp_knode_to(&m_pNodes[56], DVP_Transform_t)->input = m_images[66]; + + m_pNodes[57].header.kernel = DVP_KN_IMG_MAD_8x8; + dvp_knode_to(&m_pNodes[57], DVP_SAD_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[57], DVP_SAD_t)->output = m_images[67]; + dvp_knode_to(&m_pNodes[57], DVP_SAD_t)->refImg = m_images[58]; + + m_pNodes[58].header.kernel = DVP_KN_IMG_MAD_16x16; + dvp_knode_to(&m_pNodes[58], DVP_SAD_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[58], DVP_SAD_t)->output = m_images[68]; + dvp_knode_to(&m_pNodes[58], DVP_SAD_t)->refImg = m_images[58]; + + m_pNodes[59].header.kernel = DVP_KN_IMG_QUANTIZE_16; + dvp_knode_to(&m_pNodes[59], DVP_ImageQuantization_t)->input = m_images[69]; //in-place operaition + dvp_knode_to(&m_pNodes[59], DVP_ImageQuantization_t)->recip_tbl = m_buffers[4]; + dvp_knode_to(&m_pNodes[59], DVP_ImageQuantization_t)->block_size = 32; + dvp_knode_to(&m_pNodes[59], DVP_ImageQuantization_t)->q_pt = 3; + + m_pNodes[60].header.kernel = DVP_KN_IMG_WAVE_HORZ; + dvp_knode_to(&m_pNodes[60], DVP_ImageWavelet_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[60], DVP_ImageWavelet_t)->output = m_images[70]; + dvp_knode_to(&m_pNodes[60], DVP_ImageWavelet_t)->qmf = m_buffers[5]; + dvp_knode_to(&m_pNodes[60], DVP_ImageWavelet_t)->mqmf = m_buffers[6]; + + memcpy(m_images[23].pData[0], maskBlurNeg3x3, 3*3*sizeof(DVP_S16)); + memcpy(m_images[24].pData[0], maskBlur11x11, 5*5*sizeof(DVP_S16)); + memcpy(m_images[25].pData[0], maskBlur11x11, 7*7*sizeof(DVP_S16)); + memcpy(m_images[26].pData[0], maskBlur11x11_8, 11*11*sizeof(DVP_U08)); + memcpy(m_images[27].pData[0], maskBlur11x11, 11*11*sizeof(DVP_S16)); + memcpy(m_images[58].pData[0], maskSAD16x16, 16*16*sizeof(DVP_U08)); + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + + if(m_testcore != DVP_CORE_MIN) { + for(uint32_t testnode=0; testnodeinput = m_images[0]; + dvp_knode_to(&m_pNodes[0], DVP_Affine_t)->output = m_images[1]; + dvp_knode_to(&m_pNodes[0], DVP_Affine_t)->pixpad = 6; + + // Rotation with no scaling + dvp_knode_to(&m_pNodes[0], DVP_Affine_t)->affine[0] = 4096*(DVP_S16)cos(angleRadians); + dvp_knode_to(&m_pNodes[0], DVP_Affine_t)->affine[1] = 4096*(DVP_S16)sin(angleRadians); + dvp_knode_to(&m_pNodes[0], DVP_Affine_t)->affine[2] = 8*x0in- + 8*dvp_knode_to(&m_pNodes[0], DVP_Affine_t)->affine[0]*x0out/4096- + 8*dvp_knode_to(&m_pNodes[0], DVP_Affine_t)->affine[1]*y0out/4096; + dvp_knode_to(&m_pNodes[0], DVP_Affine_t)->affine[3] = -4096*(DVP_S16)sin(angleRadians); + dvp_knode_to(&m_pNodes[0], DVP_Affine_t)->affine[4] = 4096*(DVP_S16)cos(angleRadians); + dvp_knode_to(&m_pNodes[0], DVP_Affine_t)->affine[5] = 8*y0in- + 8*dvp_knode_to(&m_pNodes[0], DVP_Affine_t)->affine[3]*x0out/4096- + 8*dvp_knode_to(&m_pNodes[0], DVP_Affine_t)->affine[4]*y0out/4096; + + for(int i=0; i<6; i++) + DVP_PRINT(DVP_ZONE_ALWAYS, "Affine[%d]: %d\n", i, dvp_knode_to(&m_pNodes[0], DVP_Affine_t)->affine[i]); + + m_pNodes[1].header.kernel = DVP_KN_XYXY_TO_Y800; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->output = m_images[2]; + + tmpImages[0].pBuffer[0] = m_images[2].pBuffer[0]; // Using Luma from luma extract function + tmpImages[0].pData[0] = m_images[2].pData[0]; + tmpImages[0].pBuffer[1] = m_images[3].pBuffer[1]; + tmpImages[0].pData[1] = m_images[3].pData[1]; + tmpImages[0].y_stride = m_images[2].y_stride; + tmpImages[0].y_start = m_images[2].y_start; + tmpImages[0].memType = m_images[3].memType; + + // NV12 Image Rotation + m_pNodes[2].header.kernel = DVP_KN_LDC_AFFINE_TRANSFORM; + dvp_knode_to(&m_pNodes[2], DVP_Affine_t)->input = tmpImages[0]; + dvp_knode_to(&m_pNodes[2], DVP_Affine_t)->output = m_images[3]; + dvp_knode_to(&m_pNodes[2], DVP_Affine_t)->pixpad = 6; + + // Rotation with no scaling + dvp_knode_to(&m_pNodes[2], DVP_Affine_t)->affine[0] = 4096*(DVP_S16)cos(angleRadians); + dvp_knode_to(&m_pNodes[2], DVP_Affine_t)->affine[1] = 4096*(DVP_S16)sin(angleRadians); + dvp_knode_to(&m_pNodes[2], DVP_Affine_t)->affine[2] = 8*x0in- + 8*dvp_knode_to(&m_pNodes[2], DVP_Affine_t)->affine[0]*x0out/4096- + 8*dvp_knode_to(&m_pNodes[2], DVP_Affine_t)->affine[1]*y0out/4096; + dvp_knode_to(&m_pNodes[2], DVP_Affine_t)->affine[3] = -4096*(DVP_S16)sin(angleRadians); + dvp_knode_to(&m_pNodes[2], DVP_Affine_t)->affine[4] = 4096*(DVP_S16)cos(angleRadians); + dvp_knode_to(&m_pNodes[2], DVP_Affine_t)->affine[5] = 8*y0in- + 8*dvp_knode_to(&m_pNodes[2], DVP_Affine_t)->affine[3]*x0out/4096- + 8*dvp_knode_to(&m_pNodes[2], DVP_Affine_t)->affine[4]*y0out/4096; + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + status = CameraInit(this, m_images[0].color); + if (status == STATUS_SUCCESS) + { + if (m_imgdbg_enabled && AllocateImageDebug(4)) + { + ImageDebug_Init(&m_imgdbg[0], &m_images[0], m_imgdbg_path, "00_input"); + ImageDebug_Init(&m_imgdbg[1], &m_images[1], m_imgdbg_path, "01_422_affine"); + ImageDebug_Init(&m_imgdbg[2], &m_images[2], m_imgdbg_path, "02_luma"); + ImageDebug_Init(&m_imgdbg[3], &m_images[3], m_imgdbg_path, "03_nv12_affine"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + DVP_PRINT(DVP_ZONE_ENGINE, "About to process %u frames!\n",m_numFrames); + } + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} + +status_e TestVisionEngine::Test_AR() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_VLIB) || defined(DVP_USE_VRUN) + DVP_MemType_e camType = DVP_MTYPE_DEFAULT; + DVP_MemType_e opType = DVP_MTYPE_DEFAULT; + +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + camType = DVP_MTYPE_MPUNONCACHED_2DTILED; + opType = DVP_MTYPE_MPUCACHED_1DTILED; +#endif +#define NPLUS1 4 + if (m_hDVP) + { + if (AllocateImageStructs(7)) + { + short new_m_width = ((m_width/NPLUS1) % 16)?((m_width/NPLUS1) + 15 ) & 0xFFFF0 : (m_width/NPLUS1); //next multiple of 16 + DVP_Image_Init(&m_images[0], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[1], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[2], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[3], new_m_width, m_height/NPLUS1, FOURCC_Y16); + DVP_Image_Init(&m_images[4], new_m_width, m_height/NPLUS1, FOURCC_Y16); + DVP_Image_Init(&m_images[5], new_m_width, m_height/NPLUS1, FOURCC_Y16); + DVP_Image_Init(&m_images[6], new_m_width, m_height/NPLUS1, FOURCC_Y800); + if (!DVP_Image_Alloc(m_hDVP, &m_images[0], camType) || + !DVP_Image_Alloc(m_hDVP, &m_images[1], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[2], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[3], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[4], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[5], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[6], opType)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + if (AllocateNodes(4) && AllocateSections(&m_graphs[0], 1)) + { + // initialize the data in the nodes... + m_pNodes[0].header.kernel = DVP_KN_XYXY_TO_Y800; // Get Luma first + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[1]; + +#if defined(DVP_USE_VRUN) + m_pNodes[1].header.kernel = DVP_KN_VRUN_HARRIS_SCORE_7x7; + dvp_knode_to(&m_pNodes[1], DVP_Harris_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[1], DVP_Harris_t)->harrisScore = m_images[2]; + dvp_knode_to(&m_pNodes[1], DVP_Harris_t)->k = 1310; + + m_pNodes[2].header.kernel = DVP_KN_VRUN_BLOCK_MAXIMA; // Get Luma first + dvp_knode_to(&m_pNodes[2], DVP_BlockMaxima_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[2], DVP_BlockMaxima_t)->blockMaximaMAX= m_images[3]; + dvp_knode_to(&m_pNodes[2], DVP_BlockMaxima_t)->blockMaximaX= m_images[4]; + dvp_knode_to(&m_pNodes[2], DVP_BlockMaxima_t)->blockMaximaY= m_images[5]; + dvp_knode_to(&m_pNodes[2], DVP_BlockMaxima_t)->nplus1 = NPLUS1; + + m_pNodes[3].header.kernel = DVP_KN_VRUN_NMS_STEP1; + dvp_knode_to(&m_pNodes[3], DVP_NMSStep1_t)->nmsStep1X = m_images[4]; + dvp_knode_to(&m_pNodes[3], DVP_NMSStep1_t)->nmsStep1Y = m_images[5]; + dvp_knode_to(&m_pNodes[3], DVP_NMSStep1_t)->nmsStep1Dst = m_images[6]; + dvp_knode_to(&m_pNodes[3], DVP_NMSStep1_t)->nplus1 = NPLUS1; +#endif + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + status = CameraInit(this, m_images[0].color); + if (status == STATUS_SUCCESS) + { + if (m_imgdbg_enabled && AllocateImageDebug(7)) + { + ImageDebug_Init(&m_imgdbg[0], &m_images[0], m_imgdbg_path, "00_input"); + ImageDebug_Init(&m_imgdbg[1], &m_images[1], m_imgdbg_path, "01_luma"); + ImageDebug_Init(&m_imgdbg[2], &m_images[2], m_imgdbg_path, "02_harrisScore"); + ImageDebug_Init(&m_imgdbg[3], &m_images[3], m_imgdbg_path, "03_ResultMAX"); + ImageDebug_Init(&m_imgdbg[4], &m_images[4], m_imgdbg_path, "03_ResultX"); + ImageDebug_Init(&m_imgdbg[5], &m_images[5], m_imgdbg_path, "03_ResultY"); + ImageDebug_Init(&m_imgdbg[6], &m_images[6], m_imgdbg_path, "04_nmsStep1"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + DVP_PRINT(DVP_ZONE_ENGINE, "About to process %u frames!\n",m_numFrames); + } + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} + +status_e TestVisionEngine::Test_HarrisCorner() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_VLIB) || defined(DVP_USE_VRUN) + DVP_MemType_e camType = DVP_MTYPE_DEFAULT; + DVP_MemType_e opType = DVP_MTYPE_DEFAULT; + +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + camType = DVP_MTYPE_MPUNONCACHED_2DTILED; + opType = DVP_MTYPE_MPUCACHED_1DTILED; +#endif +#define NPLUS1 4 + if (m_hDVP) + { + if (AllocateImageStructs(7)) + { + short new_m_width = ((m_width/NPLUS1) % (8*NPLUS1))?((m_width/NPLUS1) + (8*NPLUS1-1)) & (0xFFFF & ~(8*NPLUS1-1)) : (m_width/NPLUS1); + short new_m_height = ((m_height/NPLUS1) % (NPLUS1))?((m_height/NPLUS1) + (NPLUS1-1)) & (0xFFFF & ~(NPLUS1-1)) : (m_height/NPLUS1); + DVP_Image_Init(&m_images[0], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[1], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[2], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[3], new_m_width, new_m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[4], new_m_width, new_m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[5], new_m_width, new_m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[6], new_m_width, new_m_height, FOURCC_Y800); + + if (!DVP_Image_Alloc(m_hDVP, &m_images[0], camType) || + !DVP_Image_Alloc(m_hDVP, &m_images[1], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[2], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[3], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[4], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[5], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[6], opType)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + if (AllocateNodes(2) && AllocateSections(&m_graphs[0], 1)) + { + //initialize the data in the nodes... + m_pNodes[0].header.kernel = DVP_KN_XYXY_TO_Y800; // Get Luma first + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[1]; + +#if defined(DVP_USE_VRUN) + m_pNodes[1].header.kernel = DVP_KN_VRUN_HARRIS_CORNERS; + dvp_knode_to(&m_pNodes[1], DVP_HarrisCorners_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[1], DVP_HarrisCorners_t)->output = m_images[6]; + dvp_knode_to(&m_pNodes[1], DVP_HarrisCorners_t)->tempBuf1 = m_images[2]; + dvp_knode_to(&m_pNodes[1], DVP_HarrisCorners_t)->tempBuf2 = m_images[3]; + dvp_knode_to(&m_pNodes[1], DVP_HarrisCorners_t)->tempBuf3 = m_images[4]; + dvp_knode_to(&m_pNodes[1], DVP_HarrisCorners_t)->tempBuf4 = m_images[5]; + dvp_knode_to(&m_pNodes[1], DVP_HarrisCorners_t)->k = 1310; + dvp_knode_to(&m_pNodes[1], DVP_HarrisCorners_t)->nplus1 = NPLUS1; +#endif + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + status = CameraInit(this, m_images[0].color); + if (status == STATUS_SUCCESS) + { + if (m_imgdbg_enabled && AllocateImageDebug(7)) + { + ImageDebug_Init(&m_imgdbg[0], &m_images[0], m_imgdbg_path, "00_input"); + ImageDebug_Init(&m_imgdbg[1], &m_images[1], m_imgdbg_path, "01_luma"); + ImageDebug_Init(&m_imgdbg[2], &m_images[2], m_imgdbg_path, "02_tempHarrisScore"); + ImageDebug_Init(&m_imgdbg[3], &m_images[3], m_imgdbg_path, "03_tempResultMAX"); + ImageDebug_Init(&m_imgdbg[4], &m_images[4], m_imgdbg_path, "03_tempResultX"); + ImageDebug_Init(&m_imgdbg[5], &m_images[5], m_imgdbg_path, "03_tempResultY"); + ImageDebug_Init(&m_imgdbg[6], &m_images[6], m_imgdbg_path, "04_nmsStep1"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + DVP_PRINT(DVP_ZONE_ENGINE, "About to process %u frames!\n",m_numFrames); + } + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} + +status_e TestVisionEngine::Test_ORBnHarris() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_ORB) + DVP_MemType_e camType = DVP_MTYPE_DEFAULT; + DVP_MemType_e opType = DVP_MTYPE_DEFAULT; + +#if defined(DVP_USE_ION) || defined(DVP_USE_BO) + camType = DVP_MTYPE_GRALLOC_2DTILED; +#endif +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + opType = DVP_MTYPE_MPUNONCACHED_1DTILED; +#endif +#define NPLUS1 4 +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + if (m_hDVP) + { + if (AllocateImageStructs(10)) + { + unsigned short new_m_width = ((m_width/NPLUS1) % (8*NPLUS1))?((m_width/NPLUS1) + (8*NPLUS1-1)) & (0xFFFF & ~(8*NPLUS1-1)) : (m_width/NPLUS1); + unsigned short new_m_height = ((m_height/NPLUS1) % (NPLUS1))?((m_height/NPLUS1) + (NPLUS1-1)) & (0xFFFF & ~(NPLUS1-1)) : (m_height/NPLUS1); + DVP_Image_Init(&m_images[0], m_width, m_height, FOURCC_NV12); + DVP_Image_Init(&m_images[1], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[2], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[3], m_width+1, m_height+1, FOURCC_RGBA); + DVP_Image_Init(&m_images[4], m_width, m_height, FOURCC_YU24); + + DVP_Image_Init(&m_images[5], m_width, m_height, FOURCC_Y16);//Harris score + DVP_Image_Init(&m_images[6], MAX(new_m_width, m_width), MAX(new_m_height, m_height), FOURCC_Y16);//max + DVP_Image_Init(&m_images[7], MAX(new_m_width, m_width), MAX(new_m_height, m_height), FOURCC_Y16);//X + DVP_Image_Init(&m_images[8], MAX(new_m_width, m_width), MAX(new_m_height, m_height), FOURCC_Y16);//Y + DVP_Image_Init(&m_images[9], MAX(new_m_width, m_width), MAX(new_m_height, m_height), FOURCC_Y800);//NMS + + if (!DVP_Image_Alloc(m_hDVP, &m_images[0], camType) || + !DVP_Image_Alloc(m_hDVP, &m_images[1], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[2], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[3], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[4], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[5], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[6], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[7], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[8], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[9], opType)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + if (AllocateBufferStructs(3)) + { + DVP_Buffer_Init(&m_buffers[0], sizeof(DVP_Orb_data), CORB_MAX_FEATURES); + DVP_Buffer_Init(&m_buffers[1], sizeof(DVP_S08), CORB_NUM_PATTERNS*4); + DVP_Buffer_Init(&m_buffers[2], 1, 192*m_width); + if (!DVP_Buffer_Alloc(m_hDVP, &m_buffers[0], opType) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[1], opType) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[2], opType)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; +#if 0 + if (AllocateNodes(3) && AllocateSections(&m_graphs[0], 1)) + { + // initialize the data in the nodes... + m_pNodes[0].header.kernel = DVP_KN_VRUN_HARRIS_CORNERS; + dvp_knode_to(&m_pNodes[0], DVP_HarrisCorners_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[0], DVP_HarrisCorners_t)->output = m_images[9]; + dvp_knode_to(&m_pNodes[0], DVP_HarrisCorners_t)->tempBuf1 = m_images[5]; + dvp_knode_to(&m_pNodes[0], DVP_HarrisCorners_t)->tempBuf2 = m_images[6]; + dvp_knode_to(&m_pNodes[0], DVP_HarrisCorners_t)->tempBuf3 = m_images[7]; + dvp_knode_to(&m_pNodes[0], DVP_HarrisCorners_t)->tempBuf4 = m_images[8]; + dvp_knode_to(&m_pNodes[0], DVP_HarrisCorners_t)->k = 1311; + dvp_knode_to(&m_pNodes[0], DVP_HarrisCorners_t)->nplus1 = NPLUS1; +#else + if (AllocateNodes(4) && AllocateGraphs(1) && AllocateSections(&m_graphs[0], 1)) + { + m_pNodes[0].header.kernel = DVP_KN_CANNY_2D_GRADIENT; + dvp_knode_to(&m_pNodes[0], DVP_Canny2dGradient_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[0], DVP_Canny2dGradient_t)->outGradX = m_images[7]; + dvp_knode_to(&m_pNodes[0], DVP_Canny2dGradient_t)->outGradY = m_images[8]; + dvp_knode_to(&m_pNodes[0], DVP_Canny2dGradient_t)->outMag = m_images[6]; + m_pNodes[0].header.affinity = DVP_CORE_DSP; + + m_pNodes[1].header.kernel = DVP_KN_VLIB_HARRIS_SCORE_7x7; + dvp_knode_to(&m_pNodes[1], DVP_HarrisDSP_t)->inGradX = m_images[7]; + dvp_knode_to(&m_pNodes[1], DVP_HarrisDSP_t)->inGradY = m_images[8]; + dvp_knode_to(&m_pNodes[1], DVP_HarrisDSP_t)->scratch = m_buffers[2]; + dvp_knode_to(&m_pNodes[1], DVP_HarrisDSP_t)->harrisScore = m_images[5]; + dvp_knode_to(&m_pNodes[1], DVP_HarrisDSP_t)->k = 1311; + m_pNodes[1].header.affinity = DVP_CORE_DSP; +#endif //Switch harris to simcop + //Zero intialize the first row and column of m_images[3] + DVP_U32 i; + memset(m_images[3].pData[0], 0, m_images[3].width); + for(i=0;iinput = m_images[1]; + dvp_knode_to(&m_pNodes[m_numNodes-2], DVP_Transform_t)->output = m_images[3]; + dvp_knode_to(&m_pNodes[m_numNodes-2], DVP_Transform_t)->output.pData[0] = m_images[3].pBuffer[0] + m_images[3].y_stride*1 + m_images[3].x_stride*1; + dvp_knode_to(&m_pNodes[m_numNodes-2], DVP_Transform_t)->output.y_stride = m_images[3].y_stride-1; + dvp_knode_to(&m_pNodes[m_numNodes-2], DVP_Transform_t)->output.width = m_images[3].width-1; + dvp_knode_to(&m_pNodes[m_numNodes-2], DVP_Transform_t)->output.height = m_images[3].height-1; + m_pNodes[m_numNodes-2].header.affinity = DVP_CORE_DSP; + if(dvp_knode_to(&m_pNodes[m_numNodes-2], DVP_Transform_t)->input.width> 2049 ||dvp_knode_to(&m_pNodes[m_numNodes-2], DVP_Transform_t)->input.height> 819 ) + m_pNodes[m_numNodes-2].header.affinity = DVP_CORE_CPU; + + //initialize the data in the nodes... + m_pNodes[m_numNodes-1].header.kernel = DVP_KN_ORB; + memcpy(m_buffers[1].pData, orbPattern31, sizeof(DVP_S08)*CORB_NUM_PATTERNS*4); + dvp_knode_to(&m_pNodes[m_numNodes-1], DVP_Orb_t)->inputImage = m_images[1]; + dvp_knode_to(&m_pNodes[m_numNodes-1], DVP_Orb_t)->harrisImage = m_images[5]; + dvp_knode_to(&m_pNodes[m_numNodes-1], DVP_Orb_t)->integralImage = m_images[3]; + dvp_knode_to(&m_pNodes[m_numNodes-1], DVP_Orb_t)->orbOutput.nfeatures = 2000;//numFeatures + dvp_knode_to(&m_pNodes[m_numNodes-1], DVP_Orb_t)->orbOutput.orbData = m_buffers[0]; + dvp_knode_to(&m_pNodes[m_numNodes-1], DVP_Orb_t)->orbOutput.outImage = m_images[4]; + dvp_knode_to(&m_pNodes[m_numNodes-1], DVP_Orb_t)->orbPattern31 = m_buffers[1]; + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + status = CameraInit(this, m_images[0].color); + if (status == STATUS_SUCCESS) + { + if (m_imgdbg_enabled && AllocateImageDebug(3)) + { + ImageDebug_Init(&m_imgdbg[0], &m_images[0], m_imgdbg_path, "00_input"); + ImageDebug_Init(&m_imgdbg[1], &m_images[1], m_imgdbg_path, "00_lumaInput"); + ImageDebug_Init(&m_imgdbg[2], &m_images[4], m_imgdbg_path, "02_orbOut"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + DVP_PRINT(DVP_ZONE_ENGINE, "About to process %u frames!\n",m_numFrames); + } + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} + + +status_e TestVisionEngine::Test_Boundary() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_IMGLIB) + DVP_MemType_e camType = DVP_MTYPE_DEFAULT; + DVP_MemType_e opType = DVP_MTYPE_DEFAULT; +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + camType = DVP_MTYPE_MPUNONCACHED_2DTILED; +#endif + + if (m_hDVP) + { + if (AllocateImageStructs(6)) + { + DVP_Image_Init(&m_images[0], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[1], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[2], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[3], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[4], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[5], m_width, m_height, FOURCC_Y16); + if (!DVP_Image_Alloc(m_hDVP, &m_images[0], camType) || + !DVP_Image_Alloc(m_hDVP, &m_images[1], opType) || // DEFAULT is 1DTILED when using TILER + !DVP_Image_Alloc(m_hDVP, &m_images[2], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[3], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[4], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[5], opType)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + if (AllocateBufferStructs(4)) + { + DVP_Buffer_Init(&m_buffers[0], 4, m_width*m_height); // boundary8 outCoord (32bits) + DVP_Buffer_Init(&m_buffers[1], 4, m_width*m_height); // boundary8 outGray (32bits) + DVP_Buffer_Init(&m_buffers[2], 4, m_width*m_height); // boundary16 outCoord (32bits) + DVP_Buffer_Init(&m_buffers[3], 2, m_width*m_height); // boundary16 outGray (16bits) + if (!DVP_Buffer_Alloc(m_hDVP, &m_buffers[0], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[1], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[2], DVP_MTYPE_DEFAULT) || + !DVP_Buffer_Alloc(m_hDVP, &m_buffers[3], DVP_MTYPE_DEFAULT)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + if (AllocateNodes(7) && AllocateSections(&m_graphs[0], 1)) + { + // initialize the data in the nodes... + m_pNodes[0].header.kernel = DVP_KN_XYXY_TO_Y800; // Get Luma first + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[1]; + //m_pNodes[0].header.affinity = DVP_CORE_CPU; + + m_pNodes[1].header.kernel = DVP_KN_THRESHOLD; // Then threshold for binary image functions + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = m_images[1]; // Using Luma from Luma Extract function + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->output = m_images[2]; // Thresholded output + //m_pNodes[1].header.affinity = DVP_CORE_CPU; + + m_pNodes[2].header.kernel = DVP_KN_XSTRIDE_SHIFT; + dvp_knode_to(&m_pNodes[2], DVP_Transform_t)->input = m_images[2]; // Use 8bit luma + dvp_knode_to(&m_pNodes[2], DVP_Transform_t)->output = m_images[3]; // Output 16bit luma + //m_pNodes[2].header.affinity = DVP_CORE_CPU; + + m_pNodes[3].header.kernel = DVP_KN_IMG_BOUNDARY_8; + dvp_knode_to(&m_pNodes[3], DVP_Boundary_t)->input = m_images[2]; // Use 8bit luma + dvp_knode_to(&m_pNodes[3], DVP_Boundary_t)->outCoord = m_buffers[0]; + dvp_knode_to(&m_pNodes[3], DVP_Boundary_t)->outGray = m_buffers[1]; + //m_pNodes[3].header.affinity = DVP_CORE_CPU; + + m_pNodes[4].header.kernel = DVP_KN_IMG_BOUNDARY_16s; + dvp_knode_to(&m_pNodes[4], DVP_Boundary_t)->input = m_images[3]; // Use 16bit luma + dvp_knode_to(&m_pNodes[4], DVP_Boundary_t)->outCoord = m_buffers[2]; + dvp_knode_to(&m_pNodes[4], DVP_Boundary_t)->outGray = m_buffers[3]; + //m_pNodes[4].header.affinity = DVP_CORE_CPU; + + m_pNodes[5].header.kernel = DVP_KN_IMG_PERIMETER_8; + dvp_knode_to(&m_pNodes[5], DVP_Transform_t)->input = m_images[2]; // Use 8bit luma + dvp_knode_to(&m_pNodes[5], DVP_Transform_t)->output = m_images[4]; + //m_pNodes[5].header.affinity = DVP_CORE_CPU; + + m_pNodes[6].header.kernel = DVP_KN_IMG_PERIMETER_16; + dvp_knode_to(&m_pNodes[6], DVP_Transform_t)->input = m_images[3]; // Use 16bit luma + dvp_knode_to(&m_pNodes[6], DVP_Transform_t)->output = m_images[5]; + //m_pNodes[6].header.affinity = DVP_CORE_CPU; + + memset(m_buffers[0].pData, 0, m_buffers[0].numBytes); + memset(m_buffers[1].pData, 0, m_buffers[1].numBytes); + memset(m_buffers[2].pData, 0, m_buffers[2].numBytes); + memset(m_buffers[3].pData, 0, m_buffers[3].numBytes); + + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + status = CameraInit(this, m_images[0].color); + if (status == STATUS_SUCCESS) + { + if (m_imgdbg_enabled && AllocateImageDebug(10)) + { + ImageDebug_Init(&m_imgdbg[0], &m_images[0], m_imgdbg_path, "00_input"); + ImageDebug_Init(&m_imgdbg[1], &m_images[1], m_imgdbg_path, "01_luma"); + ImageDebug_Init(&m_imgdbg[2], &m_images[2], m_imgdbg_path, "02_bitimgThr"); + ImageDebug_Init(&m_imgdbg[3], &m_images[3], m_imgdbg_path, "03_bitimgThr16"); + ImageDebug_Init(&m_imgdbg[4], &m_images[4], m_imgdbg_path, "04_bitimgPerim8"); + ImageDebug_Init(&m_imgdbg[5], &m_images[5], m_imgdbg_path, "05_bitimgPerim16"); + BufferDebug_Init(&m_imgdbg[6], &m_buffers[0], m_imgdbg_path, "06_bound8_coord", ".bw"); + BufferDebug_Init(&m_imgdbg[7], &m_buffers[1], m_imgdbg_path, "07_bound8_gray", ".bw"); + BufferDebug_Init(&m_imgdbg[8], &m_buffers[2], m_imgdbg_path, "08_bound16_coord", ".bw"); + BufferDebug_Init(&m_imgdbg[9], &m_buffers[3], m_imgdbg_path, "09_bound16_gray", ".bw"); + ImageDebug_Open(m_imgdbg, m_numImgDbg); + } + // clear the performance + DVP_Perf_Clear(&m_graphs[0].totalperf); + DVP_PerformanceClear(m_hDVP, m_pNodes, m_numNodes); + DVP_PRINT(DVP_ZONE_ENGINE, "About to process %u frames!\n",m_numFrames); + } + } + else + status = STATUS_NO_RESOURCES; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + return status; +} + +status_e TestVisionEngine::Test_RVM() +{ + status_e status = STATUS_SUCCESS; +#if defined(DVP_USE_RVM) + char calibration_file[MAX_PATH]; + char lut_file[MAX_PATH]; + char system_command[MAX_PATH]; + int blockSize = 32; + + /**< The name of the lut binary file */ + sprintf(calibration_file, "raw/rvm_calib_%ux%u_to_%ux%u.txt", m_width, m_height, m_width, m_height); + sprintf(lut_file, "raw/rvm_lut_%ux%u_to_%ux%u_BL%d.bin", m_width, m_height, m_width, m_height, blockSize); + + FILE *lut, *calib; /**< filehandles */ + DVP_MemType_e camType = DVP_MTYPE_DEFAULT; + DVP_MemType_e opType = DVP_MTYPE_DEFAULT; +#if defined(DVP_USE_TILER) || defined(DVP_USE_ION) || defined(DVP_USE_BO) + camType = DVP_MTYPE_MPUNONCACHED_2DTILED; +#endif + + if (m_hDVP) + { + if (AllocateImageStructs(6)) + { + DVP_Image_Init(&m_images[0], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[1], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[2], m_width, m_height, FOURCC_Y16); + DVP_Image_Init(&m_images[3], m_width, m_height, FOURCC_UYVY); + DVP_Image_Init(&m_images[4], m_width, m_height, FOURCC_Y800); + DVP_Image_Init(&m_images[5], m_width, m_height, FOURCC_Y16); + if (!DVP_Image_Alloc(m_hDVP, &m_images[0], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[1], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[2], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[3], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[4], opType) || + !DVP_Image_Alloc(m_hDVP, &m_images[5], opType)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + // Check if LUT file already exists: if it does, then open it and read the LUT, + // if it doesn't, then generate it using the calibration file. + lut = fopen(lut_file, "rb"); + if (lut == NULL) { + calib = fopen(calibration_file, "r"); + if (calib == NULL) { + DVP_PRINT(DVP_ZONE_ERROR, "Error opening file %s for reading\n",calibration_file); + return STATUS_NO_RESOURCES; + } + fclose(calib); + DVP_PRINT(DVP_ZONE_ENGINE, "Generating file %s for rvm LUT input!\n",lut_file); + sprintf(system_command, "rvm_generate_lut %d %d %d %d %d raw/rvm_calib_%dx%d_to_%dx%d.txt raw/rvm_lut_%dx%d_to_%dx%d_BL%d.bin", + m_width, m_height, m_width, m_height, blockSize, + m_width, m_height, m_width, m_height, + m_width, m_height, m_width, m_height, blockSize); + system(system_command); + lut = fopen(lut_file, "rb"); + if (lut == NULL) { + DVP_PRINT(DVP_ZONE_ERROR, "Error opening file %s for reading\n",lut_file); + return STATUS_NO_RESOURCES; + } + } + DVP_PRINT(DVP_ZONE_ENGINE, "Opening file %s for rvm LUT input!\n",lut_file); + + fseek( lut, 0, SEEK_END ); + int fileSize = ftell( lut ); + rewind( lut ); + + if (AllocateBufferStructs(1)) + { + DVP_Buffer_Init(&m_buffers[0], 1, fileSize); + if (!DVP_Buffer_Alloc(m_hDVP, &m_buffers[0], DVP_MTYPE_DEFAULT)) + return STATUS_NOT_ENOUGH_MEMORY; + } + else + return STATUS_NOT_ENOUGH_MEMORY; + + fread( m_buffers[0].pData, 1, fileSize, lut ); + fclose( lut ); + + if (AllocateNodes(4) && AllocateSections(&m_graphs[0], 1)) + { + // initialize the data in the nodes... + + m_pNodes[0].header.kernel = DVP_KN_XYXY_TO_Y800; + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = m_images[0]; //422 + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->output = m_images[1]; //luma8 + + m_pNodes[1].header.kernel = DVP_KN_XSTRIDE_SHIFT; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = m_images[1]; //luma8 + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->output = m_images[2]; //luma16 + + m_pNodes[2].header.kernel = DVP_KN_RVM; //422 to 422 + dvp_knode_to(&m_pNodes[2], DVP_Rvm_t)->input = m_images[0]; + dvp_knode_to(&m_pNodes[2], DVP_Rvm_t)->output = m_images[3]; + dvp_knode_to(&m_pNodes[2], DVP_Rvm_t)->lut = m_buffers[0]; + + m_pNodes[3].header.kernel = DVP_KN_RVM; //luma8 to luma8 + dvp_knode_to(&m_pNodes[3], DVP_Rvm_t)->input = m_images[1]; + dvp_knode_to(&m_pNodes[3], DVP_Rvm_t)->output = m_images[4]; + dvp_knode_to(&m_pNodes[3], DVP_Rvm_t)->lut = m_buffers[0]; +#if 0 + m_pNodes[4].header.kernel = DVP_KN_RVM; //luma16 to luma16 + dvp_knode_to(&m_pNodes[4], DVP_Rvm_t)->input = m_images[2]; + dvp_knode_to(&m_pNodes[4], DVP_Rvm_t)->output = m_images[5]; + dvp_knode_to(&m_pNodes[4], DVP_Rvm_t)->lut = m_buffers[0]; +#endif + // put all the nodes in the section. + m_graphs[0].sections[0].pNodes = &m_pNodes[0]; + m_graphs[0].sections[0].numNodes = m_numNodes; + m_graphs[0].order[0] = 0; + } + + if(m_testcore != DVP_CORE_MIN) { + for(uint32_t testnode=0; testnodemFrameSource == VCAM_PORT_ALL || + cameraFrame->mFrameSource == VCAM_PORT_PREVIEW)) + { + DVP_Image_t *pImage = (DVP_Image_t *)cameraFrame->mFrameBuff; + // update the graph with the image that was given to us + if (m_graphtype == TI_GRAPH_TYPE_TEST4) + { + // this is an implicit memcpy + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = *pImage; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = *pImage; + dvp_knode_to(&m_pNodes[2], DVP_Transform_t)->input = *pImage; + dvp_knode_to(&m_pNodes[5], DVP_Transform_t)->input = *pImage; + DVP_PRINT(DVP_ZONE_ENGINE, "Updating Images in Graph with Returned Buffer from Camera %p\n", pImage); + DVP_PrintImage(DVP_ZONE_ENGINE, pImage); + DVP_PRINT(DVP_ZONE_ENGINE, "Dumping all images:\n"); + for (i = 0; i < m_numImages; i++) + DVP_PrintImage(DVP_ZONE_ENGINE, &m_images[i]); + } + else if (m_graphtype == TI_GRAPH_TYPE_TEST9) + { + DVP_PRINT(DVP_ZONE_ENGINE, "Updating Image in TEST9 Graph!\n"); + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = *pImage; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = *pImage; + //m_pNodes[4], DVP_Transform_t)->input = *pImage; + } + else if (m_graphtype == TI_GRAPH_TYPE_TEST10) + { + DVP_PRINT(DVP_ZONE_ENGINE, "Updating Image in TEST10 Graph!\n"); + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = *pImage; + dvp_knode_to(&m_pNodes[1], DVP_Transform_t)->input = *pImage; + } + else if (m_graphtype == TI_GRAPH_TYPE_TEST11) + { + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = *pImage; + dvp_knode_to(&m_pNodes[3], DVP_Transform_t)->input = *pImage; + dvp_knode_to(&m_pNodes[4], DVP_Transform_t)->input = *pImage; + } + else if (m_graphtype == TI_GRAPH_TYPE_BOUNDARY) + { + memset(m_buffers[0].pData, 0, m_buffers[0].numBytes); + memset(m_buffers[1].pData, 0, m_buffers[1].numBytes); + memset(m_buffers[2].pData, 0, m_buffers[2].numBytes); + memset(m_buffers[3].pData, 0, m_buffers[3].numBytes); + } +#if defined(DVP_USE_VLIB) && defined(DVP_USE_YUV) + else if (m_graphtype == TI_GRAPH_TYPE_DISPARITY) + { + // construct the left and right images from the camera input + DVP_Image_t left = *pImage; + DVP_Image_t right = *pImage; + + // we're assuming LEFT/RIGHT NV12 + left.width >>= 1; + right.width >>= 1; + + // y stride should be the same + right.pData[0] = left.pData[0] + (left.width*left.x_stride); + right.pData[1] = left.pData[1] + ((left.width/2)*left.x_stride*2); + + dvp_knode_to(&m_pNodes[0], DVP_Disparity_t)->left = left; + dvp_knode_to(&m_pNodes[0], DVP_Disparity_t)->right = right; + } +#endif +#if defined(DVP_USE_TISMO) + else if (m_graphtype == TI_GRAPH_TYPE_TISMO) + { + // construct the left and right images from the camera input + DVP_Image_t left = *pImage; + DVP_Image_t right = *pImage; + DVP_Image_t disp = *pImage; + + left.width = dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->output.width; + left.height = dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->output.height; + right.width = dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->output.width; + right.height = dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->output.height; + disp.width = dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->output.width; + disp.height = dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->output.height; + + // y stride should be the same +#if TOPBOTTOM + right.pData[0] = left.pBuffer[0] + left.height*left.y_stride; +#if DISPLAY_DISPARITY + disp.pData[0] = left.pBuffer[0] + left.width*left.x_stride; + disp.pData[1] = left.pBuffer[1] + left.width*left.x_stride; + dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->output = disp; +#endif +#else + right.pData[0] = left.pBuffer[0] + left.width*left.x_stride; +#endif + dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->left = left; + //WORKAROUND + //DVP_Image_Copy(&m_images[m_dispMax+2], &right); + dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->right = right; + + if (m_imgdbg_enabled){ + memcpy(&m_dbgImage, pImage, sizeof(DVP_Image_t));//Copy image structure + + m_imgdbg[0].pImg = &m_dbgImage; +#if TOPBOTTOM +#if DISPLAY_DISPARITY + m_imgdbg[0].pImg->width *= 2; +#endif + m_imgdbg[0].pImg->height = m_height; +#else + m_imgdbg[0].pImg->width = m_width; +#endif + m_imgdbg[3].pImg = &dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->left; + m_imgdbg[4].pImg = &dvp_knode_to(&m_pNodes[0], DVP_Tismo_t)->right; + } + } +#endif // defined(DVP_USE_TISMO) +#if defined(DVP_USE_ORB) + else if(m_graphtype == TI_GRAPH_TYPE_ORBHARRIS) + { + DVP_Image_Copy(&m_images[1], pImage); + memcpy(dvp_knode_to(&m_pNodes[m_numNodes-1], DVP_Orb_t)->orbOutput.outImage.pData[0], m_images[1].pData[0] , m_width*m_height*sizeof(DVP_U08)); + //dvp_knode_to(&m_pNodes[0], DVP_HarrisCorners_t)->input = *pImage; + //dvp_knode_to(&m_pNodes[m_numNodes-2], DVP_Transform_t)->input = *pImage; + //dvp_knode_to(&m_pNodes[m_numNodes-1], DVP_Orb_t)->inputImage = *pImage; + } +#endif + else + dvp_knode_to(&m_pNodes[0], DVP_Transform_t)->input = *pImage; + + // find the camera buffer and point the display index to it. + for (i = m_camMin; i < m_camMax; i++) + if (pImage == &m_images[i]) + m_dispIdx = i; + + } + return STATUS_SUCCESS; +} + + +void TestVisionEngine::GraphSectionComplete(DVP_KernelGraph_t *graph, uint32_t sectionIndex, uint32_t numNodesExecuted) +{ + graph = graph; // warnings + sectionIndex = sectionIndex; // warnings + numNodesExecuted = numNodesExecuted; // warnings + DVP_PRINT(DVP_ZONE_ENGINE, "Graph %p Section %u Completed %u nodes!\n", graph, sectionIndex, numNodesExecuted); +} diff --git a/source/dvp/dvp_test/TestVisionEngine.h b/source/dvp/dvp_test/TestVisionEngine.h new file mode 100644 index 0000000..6849c5a --- /dev/null +++ b/source/dvp/dvp_test/TestVisionEngine.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +/*! \brief The list of supported Graphs in TestVisionEngine. + * \ingroup group_tests + */ +typedef enum _vision_engine_tests_e +{ + TI_GRAPH_TYPE_EDGE, //0 + TI_GRAPH_TYPE_RVM, //1 + TI_GRAPH_TYPE_X, //2 + TI_GRAPH_TYPE_TEST1, //3 + TI_GRAPH_TYPE_TEST2, //4 + TI_GRAPH_TYPE_TEST3, //5 + TI_GRAPH_TYPE_TEST4, //6 + TI_GRAPH_TYPE_TEST5, //7 All Simcop (plus some support fns from A9 & DSP) + TI_GRAPH_TYPE_TEST6, //8 Same as TEST5, with DSP affinity + TI_GRAPH_TYPE_TEST7, //9 Same as TEST5, with A9 affinity + TI_GRAPH_TYPE_TEST8, //10 Tesla Only (histogram) + TI_GRAPH_TYPE_TEST9, //11 NV12 Camera Input + TI_GRAPH_TYPE_TEST10, //12 UYVY Input, Half and Quarter Scale UYVY Output + TI_GRAPH_TYPE_TEST11, //13 UYVY Capture, IYUV Convert, Rotate90 and Rotate270 + TI_GRAPH_TYPE_DISPARITY,//14 NV12 Stereo Capture, SAD8 To Produce a final image. + TI_GRAPH_TYPE_TISMO, //15 NV12 Stereo Capture, TISMO To Produce a disparity map. + TI_GRAPH_TYPE_IMGLIB, //16 Various Imglib functions. + TI_GRAPH_TYPE_LDC, //17 Simcop LDC functions. + TI_GRAPH_TYPE_AR, //18 AR test functions. + TI_GRAPH_TYPE_BOUNDARY, //19 Border/perimeter test functions. + TI_GRAPH_TYPE_HARRIS, //20 Harris Corner test function. + TI_GRAPH_TYPE_ORBHARRIS,//21 ORB+HarrisCorner test function. + TI_GRAPH_TYPE_TESLA, //22 Tesla only. + TI_GRAPH_TYPE_IMGLIB_TESLA, //23 Imglib on Tesla + TI_GRAPH_TYPE_DSPLIB_TESLA, //24 Dsplib on Tesla + TI_GRAPH_TYPE_VLIB_CPU, //25 Dsplib on Tesla + TI_GRAPH_TYPE_IMGLIB_CPU, //26 Dsplib on Tesla + VENDOR_GRAPH_TYPE_BASE = 0x1000, // Put vendor specific graph tests after here + +} TI_GraphType_e; + +/*! \brief The Kernel Regression Test Class. + * \ingroup group_tests + */ +class TestVisionEngine : public VisionEngine +{ +protected: + TI_GraphType_e m_graphtype; /*!< Which graph is being run */ + DVP_Core_e m_testcore; /*!< Which core to run the graph on */ + DVP_Image_t m_dbgImage; +public: + TestVisionEngine(uint32_t width, uint32_t height, uint32_t fps, fourcc_t color, char *camName, uint32_t numFrames, int32_t graph, DVP_Core_e affinity); + ~TestVisionEngine(); + + // Implemenation over BaseClass + status_e GraphSetup(); + status_e GraphUpdate(VisionCamFrame *cameraFrame); + void GraphSectionComplete(DVP_KernelGraph_t *graph, uint32_t sectionIndex, uint32_t numNodesExecuted); + virtual status_e PostProcessImage(VisionCamFrame* pFrame, uint32_t numSections); + + // Different Graph Setups + status_e CalibrationGraph(); + status_e CarGraph(); + status_e EdgeGraphSetup(); + status_e Test_MorphGraphSetup(); + status_e Test_NonmaxImgconvGraphSetup(); + status_e Test_CannyGraphSetup(); + status_e Test_MiscGraphSetup(); + status_e Test_SimcopGraphSetup(); + status_e Test_HistGraphSetup(); + status_e Test_NV12GraphSetup(); + status_e Test_UYVYScalingGraph(); + status_e Test_Rotate(); + status_e Test_Disparity(); + status_e Test_Tismo(); + status_e Test_Imglib(); + status_e Test_Ldc(); + status_e Test_AR(); + status_e Test_Boundary(); + status_e Test_ORBnHarris(); + status_e Test_HarrisCorner(); + status_e Test_TeslaGraphSetup(); + status_e Test_RVM(); + status_e Test_DSPLIB(); +}; + diff --git a/source/dvp/dvp_test/concerto.mak b/source/dvp/dvp_test/concerto.mak new file mode 100644 index 0000000..0713e25 --- /dev/null +++ b/source/dvp/dvp_test/concerto.mak @@ -0,0 +1,82 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(PRELUDE) +TARGET=dvp_test +TARGETTYPE=exe +DEFS+=$(DVP_FEATURES) +IDIRS+=$(DVP_INC) +CPPSOURCES=dvp_test.cpp TestVisionEngine.cpp +STATIC_LIBS+=VisionEngine sosal imgdbg vcam cthreaded +SHARED_LIBS+=dvp +IDIRS+=$(IPC_INCS) $(MEM_INCS) $(OMX_INCS) +SYS_SHARED_LIBS+=$(IPC_LIBS) $(MEM_LIBS) $(OMX_LIBS) $(PLATFORM_LIBS) +ifeq ($(TARGET_OS),LINUX) + STATIC_LIBS+=v4l2 +endif +include $(FINALE) + +ifneq (,$(findstring dsplib,$(VISION_LIBRARIES))) +_MODULE=dvp_dsplib +include $(PRELUDE) +TARGET=dvp_dsplib +TARGETTYPE=exe +IDIRS+=$(DVP_INC) $(DVP_INT_INC) $(SOSAL_INC) +DEFS+=$(DVP_FEATURES) +CSOURCES=dvp_dsplib.c +SHARED_LIBS+=dvp +STATIC_LIBS+=imgdbg sosal +IDIRS += $(IPC_INCS) $(MEM_INCS) +SYS_SHARED_LIBS += $(IPC_LIBS) $(MEM_LIBS) $(PLATFORM_LIBS) +include $(FINALE) +endif + +_MODULE=dvp_simple +include $(PRELUDE) +TARGET=dvp_simple +TARGETTYPE=exe +IDIRS+=$(DVP_INC) $(DVP_INT_INC) $(SOSAL_INC) +DEFS+=$(DVP_FEATURES) +CSOURCES=dvp_simple.c +SHARED_LIBS+=dvp +STATIC_LIBS+=imgdbg sosal +IDIRS += $(IPC_INCS) $(MEM_INCS) +SYS_SHARED_LIBS += $(IPC_LIBS) $(MEM_LIBS) $(PLATFORM_LIBS) +include $(FINALE) + +_MODULE=dvp_info +include $(PRELUDE) +TARGET=dvp_info +TARGETTYPE=exe +IDIRS+=$(DVP_INC) $(DVP_INT_INC) $(SOSAL_INC) +DEFS+=$(DVP_FEATURES) +CSOURCES=dvp_info.c +SHARED_LIBS+=dvp +STATIC_LIBS+=imgdbg sosal +IDIRS += $(IPC_INCS) $(MEM_INCS) +SYS_SHARED_LIBS += $(IPC_LIBS) $(MEM_LIBS) $(PLATFORM_LIBS) +include $(FINALE) + +_MODULE=dvp_unittest +include $(PRELUDE) +TARGET=dvp_unittest +TARGETTYPE=exe +IDIRS+=$(DVP_INC) $(DVP_INT_INC) $(SOSAL_INC) +DEFS+=$(DVP_FEATURES) +CSOURCES=dvp_unittest.c +SHARED_LIBS+=dvp +STATIC_LIBS+=imgdbg sosal +IDIRS += $(IPC_INCS) $(MEM_INCS) +SYS_SHARED_LIBS += $(IPC_LIBS) $(MEM_LIBS) $(PLATFORM_LIBS) +include $(FINALE) diff --git a/source/dvp/dvp_test/dvp_crash_test.c b/source/dvp/dvp_test/dvp_crash_test.c new file mode 100644 index 0000000..01de870 --- /dev/null +++ b/source/dvp/dvp_test/dvp_crash_test.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +static int dvp_process(bool_e wait) +{ + DVP_PRINT(DVP_ZONE_ALWAYS, "Initializing DVP...\n"); + DVP_Handle handle = DVP_KernelGraph_Init(); + if (!handle) { + DVP_PRINT(DVP_ZONE_ERROR, "Failed initializing DVP!\n"); + return 1; + } + if (wait == true_e) { + DVP_PRINT(DVP_ZONE_ALWAYS, "Waiting to be killed...\n"); + sleep(1000); + } + DVP_KernelGraph_Deinit(handle); + DVP_PRINT(DVP_ZONE_ALWAYS, "Tore down DVP!\n"); + return 0; +} + +static int wait_for_dvp(pid_t pid, bool_e killdvp) +{ + int status = -1; + int count = 10; + if (killdvp == true_e) { + DVP_PRINT(DVP_ZONE_ALWAYS, "Wait for DVP to initialize...\n"); + //give dvp proccess a chance to initialize + sleep(2); + DVP_PRINT(DVP_ZONE_ALWAYS, "killing process %d...\n", pid); + if(kill(pid, SIGKILL) != 0) { + DVP_PRINT(DVP_ZONE_ERROR, "Error trying to kill process %d\n", pid); + } + } + DVP_PRINT(DVP_ZONE_ALWAYS, "Waiting for DVP process(%d) to exit...\n", pid); + do { + pid_t wpid = waitpid(pid, &status, WNOHANG); + if (wpid == -1) { + DVP_PRINT(DVP_ZONE_ERROR, "error waiting for pid(%d)\n", status); + break; + } + if (wpid == 0) { + if (--count > 0) { + sleep(1); + DVP_PRINT(DVP_ZONE_ALWAYS, "Waiting for DVP process(%d) to exit...\n", pid); + continue; + } else { + DVP_PRINT(DVP_ZONE_ALWAYS, "Timed out waiting for DVP process (%d)\n", pid); + return -1; + } + } + if (WIFEXITED(status)) { + DVP_PRINT(DVP_ZONE_ALWAYS, "DVP process exited, status=%d\n", WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + DVP_PRINT(DVP_ZONE_ALWAYS, "DVP process exited due to signal %d)\n", WTERMSIG(status)); + } else if (WIFSTOPPED(status)) { + DVP_PRINT(DVP_ZONE_ALWAYS, "DVP process stopped (signal %d)\n", WSTOPSIG(status)); + } + } while (!WIFEXITED(status) && !WIFSIGNALED(status)); + return status; +} + +int main() +{ + int exitCode = 0; + pid_t pid; + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + +#if defined(DVP_RUNTIME_DEBUG) + debug_get_zone_mask("DVP_ZONE_MASK", &dvp_zone_mask); +#endif + + pid = fork(); + if (pid == 0) { + exitCode = dvp_process(true_e); + } else { + //kill it to test if dvp can recover on a second try + wait_for_dvp(pid, true_e); + pid = fork(); + if (pid == 0) { + //instantiate dvp again, but let it teardown normally + exitCode = dvp_process(false_e); + } else { + int status = wait_for_dvp(pid, false_e); + if (!WIFEXITED(status) || (WIFEXITED(status) && status != 0)) { + DVP_PRINT(DVP_ZONE_ERROR, "Failed DVP teardown test! (%d)\n", status); + } else { + DVP_PRINT(DVP_ZONE_ALWAYS, "Passed DVP teardown test! (%d)\n", status); + } + } + } + return exitCode; +} diff --git a/source/dvp/dvp_test/dvp_dsplib.c b/source/dvp/dvp_test/dvp_dsplib.c new file mode 100644 index 0000000..e200f1b --- /dev/null +++ b/source/dvp/dvp_test/dvp_dsplib.c @@ -0,0 +1,686 @@ +/* + * Copyright (C) 2009-2012 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#if defined(LINUX) +#include +#include +#endif + +#if defined(DVP_USE_DSPLIB) +#include +#define TEST_DSPLIB +#include +#endif + +typedef struct _dvp_buffer_params_t { + DVP_Buffer_t *pBuffer; + DVP_U32 elemSize; + DVP_U32 numElems; + DVP_MemType_e type; +} DVP_Buffer_Params_t; + +DVP_BOOL DVP_Buffer_Construct(DVP_Handle handle, DVP_Buffer_Params_t *params, DVP_U32 numParams) +{ + DVP_BOOL ret = DVP_TRUE; + DVP_U32 i = 0; + for (i = 0; i < numParams; i++) + { + DVP_Buffer_Init(params[i].pBuffer, params[i].elemSize, params[i].numElems); + if (DVP_Buffer_Alloc(handle, params[i].pBuffer, params[i].type) == DVP_FALSE) { + ret = DVP_FALSE; + goto failed; + } + } +failed: + return ret; +} + +void DVP_KernelGraphCompleted(void *cookie, DVP_KernelGraph_t *graph, DVP_U32 sectionIndex, DVP_U32 numNodesExecuted) +{ + cookie = cookie; // warnings + graph = graph; // warnings + sectionIndex = sectionIndex; // warnings + numNodesExecuted = numNodesExecuted; // warnings + DVP_PRINT(DVP_ZONE_ALWAYS, "TEST: {%p} Graph %p Section [%u] completed %u of %u nodes\n", cookie, graph, sectionIndex, numNodesExecuted, graph->sections[sectionIndex].numNodes); +} + +uint32_t width; +uint32_t height; +uint32_t type; +uint32_t elemSize; +uint32_t numElems; + +uint32_t capacity; +uint32_t iterations; +bool_e serial; +option_t opts[] = { + {OPTION_TYPE_INT, &width, sizeof(width), "-w", "--width", "Image Width"}, + {OPTION_TYPE_INT, &height, sizeof(height), "-h", "--height", "Image Height"}, + {OPTION_TYPE_INT, &type, sizeof(type), "-t", "--type", "Memory Type see DVP_MemType_e"}, + {OPTION_TYPE_INT, &capacity, sizeof(capacity), "-c", "--capacity", "Limit Mhz on all cores to this cap"}, + {OPTION_TYPE_INT, &iterations, sizeof(iterations), "-i", "--iterations", "The number of times the graph is executed"}, + {OPTION_TYPE_BOOL, &serial, sizeof(serial), "-s", "--serial", "Forces the execution of the graph in serial"}, +}; +uint32_t numOpts = dimof(opts); + +int main(int argc, char *argv[]) +{ + const DVP_U32 numNodes = 44; + DVP_Buffer_t buffers[123]; + + DVP_Handle hDVP = 0; + DVP_KernelNode_t *pNodes = NULL; + DVP_U32 numSections = 0; + DVP_U32 i; + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + +#if defined(DVP_RUNTIME_DEBUG) + debug_get_zone_mask("DVP_ZONE_MASK", &dvp_zone_mask); +#endif + + // default values... + DVP_U32 noNodes = 0; + elemSize = sizeof(DVP_U16); + numElems = 128; + + + type = DVP_MTYPE_DEFAULT; + capacity = 100; + iterations = 1; + serial = true_e; + + // get the user values... + option_process(argc, argv, opts, numOpts); + +#if defined(LINUX) + { + int p = getpriority(PRIO_PROCESS, 0); // get our priority + setpriority(PRIO_PROCESS, 0, p-1); + } +#endif + + +#if (defined(DVP_USE_DSPLIB)) + // get the handle (will implicitly load .so/.dll and initialize RPC). + hDVP = DVP_KernelGraph_Init(); + if (hDVP) + { +#if 0 + DVP_Image_Params_t params[] = { + {&images[0], width, height, FOURCC_UYVY, type}, + {&images[1], width, height, FOURCC_RGBP, DVP_MTYPE_DEFAULT}, + {&images[2], width, height, FOURCC_Y800, DVP_MTYPE_DEFAULT}, + {&images[3], width, height, FOURCC_IYUV, DVP_MTYPE_DEFAULT}, + }; +#endif + DVP_Buffer_Params_t params_buffer[] = { + {&buffers[0], elemSize, numElems, type}, + {&buffers[1], elemSize, numElems, type}, + {&buffers[2], elemSize, numElems, type}, + {&buffers[3], elemSize, numElems, type}, + {&buffers[4], elemSize, numElems, type}, + {&buffers[5], elemSize, numElems, type}, + {&buffers[6], elemSize, numElems, type}, + {&buffers[7], elemSize, (numElems)>>1,type}, + {&buffers[8], elemSize, numElems, type}, +#if 1 + {&buffers[9], elemSize, numElems, type}, + {&buffers[10], elemSize, numElems, type}, + {&buffers[11], elemSize, numElems, type}, + {&buffers[12], elemSize, numElems, type}, + {&buffers[13], elemSize, numElems, type}, + {&buffers[14], elemSize, numElems, type}, + {&buffers[15], elemSize, numElems, type}, + {&buffers[16], elemSize, numElems, type}, + {&buffers[17], elemSize, numElems, type}, + {&buffers[18], elemSize, numElems, type}, + {&buffers[19], elemSize, numElems, type}, + {&buffers[20], elemSize, numElems, type}, + {&buffers[21], elemSize, numElems, type}, + {&buffers[22], elemSize, numElems, type}, + {&buffers[23], elemSize, sizeof(FFT_x)/sizeof(DVP_U16), type}, + {&buffers[24], elemSize, sizeof(FFT_x)/sizeof(DVP_U16), type}, + {&buffers[25], elemSize, sizeof(FFT_x)/sizeof(DVP_U16), type}, + {&buffers[26], elemSize, numElems, type}, + {&buffers[27], elemSize, numElems, type}, + {&buffers[28], elemSize, numElems, type}, + {&buffers[29], elemSize, numElems, type}, + {&buffers[30], elemSize, numElems, type}, + {&buffers[31], elemSize, numElems, type}, + {&buffers[32], elemSize, numElems, type}, + {&buffers[33], elemSize, numElems, type}, + {&buffers[34], elemSize, numElems, type}, + {&buffers[35], elemSize, numElems, type}, + {&buffers[36], elemSize, numElems, type}, + {&buffers[37], elemSize, numElems, type}, + {&buffers[38], elemSize, numElems, type}, + {&buffers[39], elemSize, numElems, type}, + {&buffers[40], elemSize, numElems, type}, + {&buffers[41], elemSize, sizeof(FIR_x)/sizeof(DVP_U16),type}, + {&buffers[42], elemSize, sizeof(FIR_h)/sizeof(DVP_U16),type}, + {&buffers[43], elemSize, sizeof(FIR_x)/sizeof(DVP_U16),type}, + {&buffers[44], elemSize, sizeof(FIR_x)/sizeof(DVP_U16),type}, + {&buffers[45], elemSize, sizeof(FIR_h)/sizeof(DVP_U16),type}, + {&buffers[46], elemSize, sizeof(FIR_x)/sizeof(DVP_U16),type}, + {&buffers[47], elemSize, sizeof(FIR_x)/sizeof(DVP_U16),type}, + {&buffers[48], elemSize, sizeof(FIR_h)/sizeof(DVP_U16),type}, + {&buffers[49], elemSize, numElems, type}, + {&buffers[50], elemSize, sizeof(FIR_x)/sizeof(DVP_U16),type}, + {&buffers[51], elemSize, sizeof(FIR_h)/sizeof(DVP_U16),type}, + {&buffers[52], elemSize, numElems, type}, + {&buffers[53], elemSize, sizeof(FIR_x)/sizeof(DVP_U16),type}, + {&buffers[54], elemSize, sizeof(FIR_x)/sizeof(DVP_U16),type}, + {&buffers[55], elemSize, numElems, type}, + {&buffers[56], elemSize, sizeof(FIR_Rx)/sizeof(DVP_U16),type}, + {&buffers[57], elemSize, sizeof(FIR_Rh)/sizeof(DVP_U16), type}, + {&buffers[58], elemSize, numElems, type}, + {&buffers[59], elemSize, sizeof(FIR_Rx)/sizeof(DVP_U16), type}, + {&buffers[60], elemSize, sizeof(FIR_Rh)/sizeof(DVP_U16), type}, + {&buffers[61], elemSize, numElems, type}, + {&buffers[62], elemSize, sizeof(FIR_Rx)/sizeof(DVP_U16), type}, + {&buffers[63], elemSize, sizeof(FIR_Rh)/sizeof(DVP_U16), type}, + {&buffers[64], elemSize, numElems, type}, + {&buffers[65], elemSize, sizeof(FIR_xS)/sizeof(DVP_U16), type}, + {&buffers[66], elemSize, sizeof(FIR_hs)/sizeof(DVP_U16), type}, + {&buffers[67], elemSize, numElems, type}, + {&buffers[68], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16), type}, + {&buffers[69], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16), type}, + {&buffers[70], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16), type}, + {&buffers[71], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16), type}, + {&buffers[72], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16), type}, + {&buffers[73], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16), type}, + {&buffers[74], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16), type}, + {&buffers[75], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16), type}, + {&buffers[76], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16), type}, + {&buffers[77], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16), type}, + {&buffers[78], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16), type}, + {&buffers[79], elemSize, sizeof(IFFT_x)/sizeof(DVP_U16), type}, + {&buffers[80], elemSize, numElems, type}, + {&buffers[81], elemSize, numElems, type}, + {&buffers[82], elemSize, numElems, type}, + {&buffers[83], elemSize, numElems, type}, + {&buffers[84], elemSize, numElems, type}, + {&buffers[85], elemSize, sizeof(x_IIR)/sizeof(DVP_U16), type}, + {&buffers[86], elemSize, sizeof(k_IIR)/sizeof(DVP_U16), type}, + {&buffers[87], elemSize, sizeof(b_c_IIR)/sizeof(DVP_U16), type}, + {&buffers[88], elemSize, numElems, type}, + {&buffers[89], elemSize, sizeof(ptr_Coefs)/sizeof(DVP_U16), type}, + {&buffers[90], elemSize, (N_IIRSS + PAD_IIRSS), type}, + {&buffers[91], elemSize, 256, type}, + {&buffers[92], elemSize, 256, type}, + {&buffers[93], elemSize, 256, type}, + {&buffers[94], elemSize, 256, type}, + {&buffers[95], elemSize, 256, type}, + {&buffers[96], elemSize, 256, type}, + {&buffers[97], elemSize, 256, type}, + {&buffers[98], elemSize, 256, type}, + {&buffers[99], elemSize, sizeof(buffer_x)/sizeof(DVP_U16), type}, + {&buffers[100], elemSize, sizeof(buffer_x)/sizeof(DVP_U16), type}, + {&buffers[101], elemSize, sizeof(buffer_x)/sizeof(DVP_U16), type}, + {&buffers[102], elemSize, 256*9, type}, + {&buffers[103], elemSize, 9, type}, + {&buffers[104], elemSize, numElems, type}, + {&buffers[105], elemSize, numElems, type}, + {&buffers[106], elemSize, numElems, type}, + {&buffers[107], elemSize, numElems, type}, + {&buffers[108], elemSize, numElems, type}, + {&buffers[109], elemSize, numElems, type}, + {&buffers[110], elemSize, numElems, type}, + {&buffers[111], elemSize, numElems, type}, + {&buffers[112], elemSize, sizeof(FIR_x)/sizeof(DVP_U16), type}, + {&buffers[113], elemSize, sizeof(a_W_VEC)/sizeof(DVP_U16), type}, + {&buffers[114], elemSize, sizeof(a_W_VEC)/sizeof(DVP_U16), type}, + {&buffers[115], elemSize, sizeof(a_W_VEC)/sizeof(DVP_U16), type}, + {&buffers[116], elemSize, numElems, type}, + {&buffers[117], elemSize, numElems, type}, + {&buffers[118], elemSize, numElems, type}, + {&buffers[119], elemSize, numElems, type}, + {&buffers[120], elemSize, numElems, type}, + {&buffers[121], elemSize, 256, type}, + {&buffers[122], elemSize, 256, type}, +#endif + }; + + if (DVP_Buffer_Construct(hDVP, params_buffer, dimof(params_buffer)) == DVP_FALSE) + goto teardown; + + + + + memcpy(params_buffer[0].pBuffer->pData,buffer_x,sizeof(buffer_x)); + memcpy(params_buffer[1].pBuffer->pData,buffer_x,sizeof(buffer_y)); + memcpy(params_buffer[3].pBuffer->pData,buffer_x,sizeof(buffer_x)); + memcpy(params_buffer[4].pBuffer->pData,buffer_x,sizeof(buffer_y)); + memcpy(params_buffer[8].pBuffer->pData,buffer_x,sizeof(buffer_x)); + memcpy(params_buffer[9].pBuffer->pData,buffer_x,sizeof(buffer_y)); + memcpy(params_buffer[11].pBuffer->pData,buffer_x,sizeof(buffer_x)); + memcpy(params_buffer[13].pBuffer->pData,buffer_x,sizeof(buffer_x)); + memcpy(params_buffer[15].pBuffer->pData,buffer_x,sizeof(buffer_x)); + memcpy(params_buffer[17].pBuffer->pData,buffer_x,sizeof(buffer_x)); + memcpy(params_buffer[18].pBuffer->pData,buffer_x,sizeof(buffer_y)); + memcpy(params_buffer[20].pBuffer->pData,buffer_x,sizeof(buffer_x)); + memcpy(params_buffer[21].pBuffer->pData,buffer_x,sizeof(buffer_y)); + memcpy(params_buffer[23].pBuffer->pData,FFT_x,sizeof(FFT_x)); + memcpy(params_buffer[24].pBuffer->pData,FFT_x,sizeof(FFT_x)); + memcpy(params_buffer[26].pBuffer->pData,buffer_x,sizeof(buffer_x)); + memcpy(params_buffer[27].pBuffer->pData,buffer_x,sizeof(buffer_y)); + memcpy(params_buffer[29].pBuffer->pData,buffer_x,sizeof(buffer_x)); + memcpy(params_buffer[30].pBuffer->pData,buffer_x,sizeof(buffer_y)); + memcpy(params_buffer[32].pBuffer->pData,buffer_x,sizeof(buffer_x)); + memcpy(params_buffer[33].pBuffer->pData,buffer_x,sizeof(buffer_y)); + memcpy(params_buffer[35].pBuffer->pData,buffer_x,sizeof(buffer_x)); + memcpy(params_buffer[36].pBuffer->pData,buffer_x,sizeof(buffer_y)); + memcpy(params_buffer[38].pBuffer->pData,buffer_x,sizeof(buffer_x)); + memcpy(params_buffer[39].pBuffer->pData,buffer_x,sizeof(buffer_y)); + + memcpy(params_buffer[41].pBuffer->pData,FIR_x,sizeof(FIR_x)); + memcpy(params_buffer[42].pBuffer->pData,FIR_h,sizeof(FIR_h)); + memcpy(params_buffer[44].pBuffer->pData,FIR_x,sizeof(FIR_x)); + memcpy(params_buffer[45].pBuffer->pData,FIR_h,sizeof(FIR_h)); + memcpy(params_buffer[47].pBuffer->pData,FIR_x,sizeof(FIR_x)); + memcpy(params_buffer[48].pBuffer->pData,FIR_h,sizeof(FIR_h)); + memcpy(params_buffer[50].pBuffer->pData,FIR_x,sizeof(FIR_x)); + memcpy(params_buffer[51].pBuffer->pData,FIR_h,sizeof(FIR_h)); + memcpy(params_buffer[53].pBuffer->pData,FIR_x,sizeof(FIR_x)); + memcpy(params_buffer[54].pBuffer->pData,FIR_x,sizeof(FIR_x)); + + memcpy(params_buffer[56].pBuffer->pData,FIR_Rx,sizeof(FIR_Rx)); + memcpy(params_buffer[57].pBuffer->pData,FIR_Rh,sizeof(FIR_Rh)); + memcpy(params_buffer[59].pBuffer->pData,FIR_Rx,sizeof(FIR_Rx)); + memcpy(params_buffer[60].pBuffer->pData,FIR_Rh,sizeof(FIR_Rh)); + memcpy(params_buffer[62].pBuffer->pData,FIR_Rx,sizeof(FIR_Rx)); + memcpy(params_buffer[63].pBuffer->pData,FIR_Rh,sizeof(FIR_Rh)); + + memcpy(params_buffer[65].pBuffer->pData,FIR_xS,sizeof(FIR_xS)); + memcpy(params_buffer[66].pBuffer->pData,FIR_hs,sizeof(FIR_hs)); + + memcpy(params_buffer[68].pBuffer->pData,IFFT_x,sizeof(IFFT_x)); + memcpy(params_buffer[69].pBuffer->pData,IFFT_x,sizeof(IFFT_x)); + memcpy(params_buffer[71].pBuffer->pData,IFFT_x,sizeof(IFFT_x)); + memcpy(params_buffer[72].pBuffer->pData,IFFT_x,sizeof(IFFT_x)); + memcpy(params_buffer[74].pBuffer->pData,IFFT_x,sizeof(IFFT_x)); + memcpy(params_buffer[75].pBuffer->pData,IFFT_x,sizeof(IFFT_x)); + memcpy(params_buffer[77].pBuffer->pData,IFFT_x,sizeof(IFFT_x)); + memcpy(params_buffer[78].pBuffer->pData,IFFT_x,sizeof(IFFT_x)); + + memcpy(params_buffer[85].pBuffer->pData,x_IIR,sizeof(x_IIR)); + memcpy(params_buffer[86].pBuffer->pData,k_IIR,sizeof(k_IIR)); + memcpy(params_buffer[87].pBuffer->pData,b_c_IIR,sizeof(b_c_IIR)); + memcpy(params_buffer[89].pBuffer->pData,ptr_Coefs,sizeof(ptr_Coefs)); + + memcpy(params_buffer[91].pBuffer->pData,MAT_x,sizeof(MAT_x)); + memcpy(params_buffer[92].pBuffer->pData,MAT_y,sizeof(MAT_y)); + memcpy(params_buffer[94].pBuffer->pData,MAT_x,sizeof(MAT_x)); + memcpy(params_buffer[95].pBuffer->pData,MAT_y,sizeof(MAT_y)); + memcpy(params_buffer[97].pBuffer->pData,MAT_x,sizeof(MAT_x)); + memcpy(params_buffer[99].pBuffer->pData,buffer_x,sizeof(buffer_x)); + memcpy(params_buffer[100].pBuffer->pData,buffer_x,sizeof(buffer_x)); + memcpy(params_buffer[101].pBuffer->pData,buffer_x,sizeof(buffer_x)); + memcpy(params_buffer[102].pBuffer->pData,GSP0_TABLE,sizeof(GSP0_TABLE)); + memcpy(params_buffer[103].pBuffer->pData,errCoefs,sizeof(errCoefs)); + memcpy(params_buffer[112].pBuffer->pData,FIR_x,sizeof(FIR_x)); + memcpy(params_buffer[113].pBuffer->pData,a_W_VEC,sizeof(a_W_VEC)); + memcpy(params_buffer[114].pBuffer->pData,a_W_VEC,sizeof(a_W_VEC)); + memcpy(params_buffer[121].pBuffer->pData,MAT_x,sizeof(MAT_x)/sizeof(DVP_U16)); + // create the nodes (will implicitly map to other cores) + pNodes = DVP_KernelNode_Alloc(hDVP, numNodes); + if (pNodes) + { + DVP_KernelGraphSection_t ssections[] = { + {&pNodes[0], 44, DVP_PERF_INIT, DVP_CORE_LOAD_INIT, DVP_FALSE}, + }; + + DVP_U32 orders[] = {0}; + DVP_KernelGraph_t graph = { + ssections, + dimof(ssections), + orders, + DVP_PERF_INIT, + }; + + // DSP Processing + pNodes[noNodes].header.kernel = DVP_KN_DSP_ADD16; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[0]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input1 = buffers[1]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[2]; + pNodes[noNodes].header.affinity = DVP_CORE_DSP; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_ADD32; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[3]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input1 = buffers[4]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[5]; + pNodes[noNodes].header.affinity = DVP_CORE_DSP; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_AUTOCORR16; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[6]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[7]; + pNodes[noNodes].header.affinity = DVP_CORE_DSP; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_BITEXP32; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[8]; + pNodes[noNodes].header.affinity = DVP_CORE_DSP; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_BLKESWAP16; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[9]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[10]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_BLKESWAP32; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[11]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[12]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_BLKESWAP64; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[13]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[14]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_BLKMOVE; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[15]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[16]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_DOTPRODSQR; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[17]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input1 = buffers[18]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[19]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = 2;//Needs attn + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_DOTPROD; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[20]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input1 = buffers[21]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[22]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_FFT_16x16; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[23]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[24]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[25]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_FFT_16x16R; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[26]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[27]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[28]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = 2; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val2 = 2; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val3 = 8; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_FFT_16x16_IMRE; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[29]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[30]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[31]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_FFT_16x32; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[32]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[33]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[34]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_FFT_32x32; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[35]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[36]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[37]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_FFT_32x32s; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[38]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[39]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[40]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_CPLX; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[41]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[42]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[43]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = sizeof(FIR_h)>>1; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val2 = sizeof(FIR_x)>>1; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_HM4x4; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[44]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[45]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[46]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = sizeof(FIR_h)>>1; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val2 = sizeof(FIR_x)>>1; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_GEN; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[47]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[48]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[49]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_HM17_RA8x8; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[50]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[51]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[52]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_LMS2; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[53]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[54]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[55]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = 0x1000; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_R4; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[56]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[57]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[58]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_R8; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[59]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[60]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[61]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_HM16_RM8A8x8; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[62]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[63]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[64]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_FIR_SYM; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[65]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[66]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[67]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = 0; + noNodes++; //25 + + + pNodes[noNodes].header.kernel = DVP_KN_DSP_IFFT_16x16; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[68]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[69]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[70]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = (sizeof(IFFT_x)/sizeof(DVP_U16))>>1; // Size of coefficient array = 2*nx + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_IFFT_16x16_IMRE; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[71]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[72]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[73]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = (sizeof(IFFT_x)/sizeof(DVP_U16))>>1; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_IFFT_16x32; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[74]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[75]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[76]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = (sizeof(IFFT_x)/sizeof(DVP_U16))>>1; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_IFFT_32x32; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[77]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[78]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[79]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = (sizeof(IFFT_x)/sizeof(DVP_U16))>>1; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_IIR; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[80]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input1 = buffers[81]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[82]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[83]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output1 = buffers[84]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = numElems; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_IIR_LAT; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[85]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input1 = buffers[86]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[87]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[88]; + noNodes++;//3 //31 + + pNodes[noNodes].header.kernel = DVP_KN_DSP_IIR_SS; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = 0; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[89]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input1 = buffers[90]; + noNodes++; + + + pNodes[noNodes].header.kernel = DVP_KN_DSP_MUL; + dvp_knode_to(&pNodes[noNodes], DVP_DSP_MatMul)->input0 = buffers[91]; + dvp_knode_to(&pNodes[noNodes], DVP_DSP_MatMul)->input1 = buffers[92]; + dvp_knode_to(&pNodes[noNodes], DVP_DSP_MatMul)->output0 = buffers[93]; + dvp_knode_to(&pNodes[noNodes], DVP_DSP_MatMul)->r1 = 16; + dvp_knode_to(&pNodes[noNodes], DVP_DSP_MatMul)->c1 = 16; + dvp_knode_to(&pNodes[noNodes], DVP_DSP_MatMul)->r2 = 16; + dvp_knode_to(&pNodes[noNodes], DVP_DSP_MatMul)->c2 = 16; + dvp_knode_to(&pNodes[noNodes], DVP_DSP_MatMul)->qs = 1; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_MUL_CPLX; + dvp_knode_to(&pNodes[noNodes], DVP_DSP_MatMul)->input0 = buffers[94]; + dvp_knode_to(&pNodes[noNodes], DVP_DSP_MatMul)->input1 = buffers[95]; + dvp_knode_to(&pNodes[noNodes], DVP_DSP_MatMul)->output0 = buffers[96]; + dvp_knode_to(&pNodes[noNodes], DVP_DSP_MatMul)->r1 = 16; + dvp_knode_to(&pNodes[noNodes], DVP_DSP_MatMul)->c1 = 16; + dvp_knode_to(&pNodes[noNodes], DVP_DSP_MatMul)->r2 = 16; + dvp_knode_to(&pNodes[noNodes], DVP_DSP_MatMul)->c2 = 16; + dvp_knode_to(&pNodes[noNodes], DVP_DSP_MatMul)->qs = 1; + noNodes++; + + + pNodes[noNodes].header.kernel = DVP_KN_DSP_W_VEC; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[113]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input1 = buffers[114]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[115]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = 16384; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_MAXVAL; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[99]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_MINVAL; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[100]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_MAXIDX; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[101]; + noNodes++; + + + pNodes[noNodes].header.kernel = DVP_KN_DSP_MINERROR; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[102]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input1 = buffers[103]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_MUL32; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[104]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input1 = buffers[105]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[106]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = numElems; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_NEG32; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[107]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[108]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = numElems; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_RECIP16; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[109]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->twoway = buffers[110]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[111]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = numElems; + noNodes++; + + + pNodes[noNodes].header.kernel = DVP_KN_DSP_VECSUMSQ; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[112]; + noNodes++; + + pNodes[noNodes].header.kernel = DVP_KN_DSP_MAT_TRANS; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->input0 = buffers[121]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->output0 = buffers[122]; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val1 = 16; + dvp_knode_to(&pNodes[noNodes], DVP_DSPFunc)->val2 = 16; + noNodes++; + + + for (i = 0; i < DVP_CORE_MAX; i++) + { + DVP_U32 cap2, cap1 = DVP_GetCoreCapacity(hDVP, i); + DVP_SetCoreCapacity(hDVP, i, capacity); + cap2 = DVP_GetCoreCapacity(hDVP, i); + DVP_PRINT(DVP_ZONE_ALWAYS, "Core[%u] was set to limit at %u capacity, now at %u\n", i, cap1, cap2); + cap1 = cap1; // warnings + } + + do { + DVP_PRINT(DVP_ZONE_ALWAYS, "Iteration %u\n", iterations); + // perform the graph processing + numSections = DVP_KernelGraph_Process(hDVP, &graph, NULL, DVP_KernelGraphCompleted); + DVP_PRINT(DVP_ZONE_ALWAYS, "%u Sections Completed!\n", numSections); + } while (iterations-- && numSections > 0); + // show us the results + DVP_PrintPerformanceGraph(hDVP, &graph); + teardown: + // free the nodes + DVP_KernelNode_Free(hDVP, pNodes, numNodes); + } + + // free the image memory + for (i = 0; i < dimof(buffers); i++) + DVP_Buffer_Free(hDVP, &buffers[i]); + + } + // tear down the graph resources + DVP_KernelGraph_Deinit(hDVP); +#else + DVP_PRINT(DVP_ZONE_ERROR, "Required VISION libraries are not present in the build!\n"); +#endif + return 0; +} diff --git a/source/dvp/dvp_test/dvp_info.c b/source/dvp/dvp_test/dvp_info.c new file mode 100644 index 0000000..7093e21 --- /dev/null +++ b/source/dvp/dvp_test/dvp_info.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + + +/*! Use \ref DVP_Core_e to index */ +char cores[DVP_CORE_MAX][20] = { + "DSP", // DVP_CORE_DSP + "SIMCOP", // DVP_CORE_SIMCOP + "MCU0", // DVP_CORE_MCU0 + "MCU1", // DVP_CORE_MCU1 + "GPU", // DVP_CORE_GPU + "EVE", // DVP_CORE_EVE + "CPU", // DVP_CORE_CPU +}; + +/*! use \ref DVP_KernelLibrary_e to index */ +char libs[DVP_KL_LIBRARY_MAX][20] = { + "INVALID", + "YUV", + "IMGFILTER", + "OCL", + "VLIB", + "IMGLIB", + "RVM", + "VRUN", + "TISMO", + "ORB", + "ARTI", + "POINTCLOUD", + "DSPLIB" +}; + +void dvp_core_info(void) +{ + DVP_Handle hDVP = DVP_KernelGraph_Init(); + DVP_CoreInfo_t info[DVP_CORE_MAX]; + DVP_Core_e c; + DVP_KernelLibrary_e lib; + + memset(info, 0, sizeof(info)); + for (lib = DVP_KL_INVALID; lib < DVP_KL_LIBRARY_MAX; lib++) + if (libs[lib][0] == '0') + strcpy(libs[lib],"UNKNOWN"); + + DVP_QuerySystem(hDVP, info); + + for (c = DVP_CORE_MIN+1; c < DVP_CORE_MAX; c++) + { + DVP_U32 k = 0; + char libraries[MAX_PATH]; + memset(libraries, 0, sizeof(libraries)); + + for (lib = DVP_KL_INVALID; lib < DVP_KL_LIBRARY_MAX; lib++) + if (info[c].libraries[lib] == DVP_TRUE) + sprintf(libraries, "%s %s", libraries, libs[lib]); + + DVP_PRINT(DVP_ZONE_ALWAYS, "DVP Core[%6s] is %s, has %3u kernels from these libraries: %s\n", + cores[c], + info[c].enabled?" ENABLED":"DISABLED", + info[c].numKernels, + libraries); + + for (k = 0; k < info[c].numKernels; k++) + { + DVP_PRINT(DVP_ZONE_ALWAYS, "\tKernel[%08x] = %s\n", info[c].kernels[k].kernel, info[c].kernels[k].name); + } + } + + DVP_KernelGraph_Deinit(hDVP); +} + +void dvp_kernel_info(DVP_KernelNode_e kernel) +{ + DVP_BOOL present[DVP_CORE_MAX]; + char string[MAX_PATH]; + DVP_U32 c = 0; + DVP_Handle hDVP = DVP_KernelGraph_Init(); + + memset(present, 0, sizeof(present)); + DVP_QueryKernel(hDVP, kernel, present); + memset(string, 0, sizeof(string)); + + for (c = 0; c < dimof(present); c++) + if (present[c] == DVP_TRUE) + sprintf(string, "%s %s", string, cores[c]); + + DVP_PRINT(DVP_ZONE_ALWAYS, "Kernel %d (%x) is supported on: %s\n", kernel, kernel, string); + + DVP_KernelGraph_Deinit(hDVP); +} + +int main(int argc, char *argv[]) +{ +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + +#if defined(DVP_RUNTIME_DEBUG) + debug_get_zone_mask("DVP_ZONE_MASK", &dvp_zone_mask); +#endif + + if (strcmp("kernel", argv[1]) == 0) + { + if (argc == 3) + { + DVP_KernelNode_e nodeEnum; + sscanf(argv[2], "%x", &nodeEnum); + dvp_kernel_info(nodeEnum); + } + else + { + printf("$ %s kernel 0x\n", argv[0]); + DVP_PRINT(DVP_ZONE_ALWAYS, "$ %s kernel 0x\n", argv[0]); + } + } + else + dvp_core_info(); + return 0; +} diff --git a/source/dvp/dvp_test/dvp_share.cpp b/source/dvp/dvp_test/dvp_share.cpp new file mode 100644 index 0000000..154822b --- /dev/null +++ b/source/dvp/dvp_test/dvp_share.cpp @@ -0,0 +1,432 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +#ifdef ANDROID +#include +using namespace android; +#endif + +struct Image { + DVP_Image_t image; + DVP_S32 fds[DVP_MAX_PLANES]; + DVP_VALUE hdls[DVP_MAX_PLANES]; +}; + +struct Buffer { + DVP_Buffer_t buf; + DVP_S32 fd; + DVP_VALUE handle; +}; + +#ifdef ANDROID +namespace android { + +class IDVPService: public IInterface +{ +public: + DECLARE_META_INTERFACE(DVPService); + virtual bool allocate(DVP_Image_t *pImage, DVP_S32 *fds) = 0; + virtual bool allocate(DVP_Buffer_t *pBuffer, DVP_S32 *fd) = 0; + virtual void teardown() = 0; +}; + +class DVPService : + public BnInterface, + public BinderService +{ +public: + enum { + ALLOCATEIMG, + ALLOCATEBUFFER, + TEARDOWN + }; + static char const* getServiceName() { return "DVPService"; } + DVPService(); + virtual ~DVPService(); + virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); + virtual bool allocate(DVP_Image_t *pImage, DVP_S32 *fds); + virtual bool allocate(DVP_Buffer_t *pBuffer, DVP_S32 *fd); + virtual void teardown(); + +private: + DVP_Handle mDvp; + Vector mImageList; + Vector mBufferList; +}; + +class BpDVPService : public BpInterface +{ +public: + BpDVPService(const sp& impl) : BpInterface(impl) {} + bool allocate(DVP_Image_t *pImage, DVP_S32 *fds) + { + Parcel data, reply; + data.writeInterfaceToken(IDVPService::getInterfaceDescriptor()); + data.writeInt32(pImage->width); + data.writeInt32(pImage->height); + data.writeInt32(pImage->color); + data.writeInt32(pImage->memType); + remote()->transact(DVPService::ALLOCATEIMG, data, &reply); + bool ret = reply.readInt32(); + if (ret == true) { + for (DVP_U32 i = 0; i < pImage->planes; i++) { + if (pImage->memType == DVP_MTYPE_MPUCACHED_VIRTUAL_SHARED) { + fds[i] = reply.readInt32(); + } else { + fds[i] = dup(reply.readFileDescriptor()); + } + DVP_PRINT(DVP_ZONE_ALWAYS, "Client: unmarshaled fd:%d\n", fds[i]); + } + } + return ret; + } + + bool allocate(DVP_Buffer_t *pBuffer, DVP_S32 *fd) + { + Parcel data, reply; + data.writeInterfaceToken(IDVPService::getInterfaceDescriptor()); + data.writeInt32(pBuffer->numBytes); + data.writeInt32(pBuffer->memType); + remote()->transact(DVPService::ALLOCATEBUFFER, data, &reply); + bool ret = reply.readInt32(); + if (ret == true) { + if (pBuffer->memType == DVP_MTYPE_MPUCACHED_VIRTUAL_SHARED) { + *fd = reply.readInt32(); + } else { + int mfd = reply.readFileDescriptor(); + DVP_PRINT(DVP_ZONE_ALWAYS, "Client: unmarshaled raw fd:%d\n", mfd); + *fd = dup(mfd); + } + DVP_PRINT(DVP_ZONE_ALWAYS, "Client: unmarshaled dup fd:%d\n", *fd); + } + return ret; + } + + void teardown() + { + Parcel data, reply; + data.writeInterfaceToken(IDVPService::getInterfaceDescriptor()); + remote()->transact(DVPService::TEARDOWN, data, &reply); + } +}; + +IMPLEMENT_META_INTERFACE(DVPService, "com.ti.test.IDVPService"); + +DVPService::DVPService() +{ + DVP_PRINT(DVP_ZONE_ALWAYS, "Created %s\n", __FUNCTION__); + mDvp = 0; +} + +DVPService::~DVPService() +{ + DVP_PRINT(DVP_ZONE_ALWAYS, "Destroying %s\n", __FUNCTION__); + teardown(); +} + +void DVPService::teardown() +{ + if (mDvp) { + + for (size_t i = 0; i < mImageList.size(); i++) { + Image *img = mImageList.itemAt(i); + for (DVP_U32 i = 0; i < img->image.planes; i++) { + close(img->fds[i]); + } + DVP_Image_Free(mDvp, &img->image); + } + + for (size_t i = 0; i < mBufferList.size(); i++) { + Buffer *buffer = mBufferList.itemAt(i); + close(buffer->fd); + DVP_Buffer_Free(mDvp, &buffer->buf); + } + + DVP_KernelGraph_Deinit(mDvp); + mDvp = 0; + } +} + +bool DVPService::allocate(DVP_Image_t *pImage, DVP_S32 *fds) +{ + DVP_PRINT(DVP_ZONE_ALWAYS, "DVPService: %s\n", __FUNCTION__); + if (mDvp == 0) { + mDvp = DVP_KernelGraph_Init(); + } + if (DVP_Image_Alloc(mDvp, pImage, static_cast(pImage->memType))) + { + DVP_PRINT(DVP_ZONE_ALWAYS, "Allocated image!\n"); + DVP_PrintImage(DVP_ZONE_ALWAYS, pImage); + if (DVP_Image_Share(mDvp, pImage, fds)) + { + DVP_PRINT(DVP_ZONE_ALWAYS, "Shared image - shared_fd:%d\n", fds[0]); + return true; + } else { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: could not share image!\n"); + DVP_Image_Free(mDvp, pImage); + } + } + DVP_PRINT(DVP_ZONE_ERROR, "Failed to allocate image!\n"); + return false; +} + +bool DVPService::allocate(DVP_Buffer_t *pBuffer, DVP_S32 *fd) +{ + DVP_PRINT(DVP_ZONE_ALWAYS, "DVPService: %s\n", __FUNCTION__); + if (mDvp == 0) { + mDvp = DVP_KernelGraph_Init(); + } + if (DVP_Buffer_Alloc(mDvp, pBuffer, static_cast(pBuffer->memType))) + { + DVP_PRINT(DVP_ZONE_ALWAYS, "Allocated buffer!\n"); + DVP_PrintBuffer(DVP_ZONE_ALWAYS, pBuffer); + if (DVP_Buffer_Share(mDvp, pBuffer, fd)) + { + DVP_PRINT(DVP_ZONE_ALWAYS, "Shared buffer - shared_fd:%d\n", *fd); + return true; + } else { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: could not share buffer!\n"); + DVP_Buffer_Free(mDvp, pBuffer); + } + } + DVP_PRINT(DVP_ZONE_ERROR, "Failed to allocate buffer!\n"); + return false; +} + +status_t DVPService::onTransact(uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) +{ + status_t status = NO_ERROR; + switch (code) { + case ALLOCATEIMG: + { + CHECK_INTERFACE(IDVPService, data, reply); + Image *img = (Image *)calloc(1, sizeof(Image)); + + uint32_t w = data.readInt32(); + uint32_t h = data.readInt32(); + uint32_t fourcc = data.readInt32(); + uint32_t memType = data.readInt32(); + DVP_Image_Init(&img->image, w, h, fourcc); + img->image.memType = memType; + + bool ret = allocate(&img->image, img->fds); + reply->writeInt32(ret); + + if (ret == true) { + for (DVP_U32 i = 0; i < img->image.planes; i++) { + DVP_PRINT(DVP_ZONE_ALWAYS, "DVPService: marshaling fd:%d\n", img->fds[i]); + if (img->image.memType == DVP_MTYPE_MPUCACHED_VIRTUAL_SHARED) { + reply->writeInt32(img->fds[i]); + } else { + reply->writeFileDescriptor(img->fds[i]); + } + } + mImageList.add(img); + } else { + free(img); + } + + break; + } + case ALLOCATEBUFFER: + { + CHECK_INTERFACE(IDVPService, data, reply); + Buffer *buffer = (Buffer *)calloc(1, sizeof(Buffer)); + + uint32_t size = data.readInt32(); + uint32_t memType = data.readInt32(); + DVP_Buffer_Init(&buffer->buf, 1, size); + buffer->buf.memType = memType; + + bool ret = allocate(&buffer->buf, &buffer->fd); + reply->writeInt32(ret); + if (ret == true) { + DVP_PRINT(DVP_ZONE_ALWAYS, "DVPService: marshaling fd:%d\n", buffer->fd); + if (buffer->buf.memType == DVP_MTYPE_MPUCACHED_VIRTUAL_SHARED) { + reply->writeInt32(buffer->fd); + } else { + reply->writeFileDescriptor(buffer->fd); + } + mBufferList.add(buffer); + } else { + free(buffer); + } + break; + } + case TEARDOWN: + teardown(); + break; + default : + return (BBinder::onTransact(code, data, reply, flags)); + } + return status; +} + +} // namespace +#endif + +static void server() +{ +#ifdef ANDROID + DVP_PRINT(DVP_ZONE_ALWAYS, "Starting DVPService!\n"); + DVPService::publishAndJoinThreadPool(); +#endif +} + +static uint32_t num_tests = 0; +static uint32_t num_tests_passed = 0; + +static void test_image_import(const sp& srv, DVP_Handle hDvp, fourcc_t fourcc, DVP_MemType_e type) +{ + num_tests++; + + Image img; + DVP_Image_Init(&img.image, 320, 240, fourcc); + img.image.memType = type; + + DVP_PRINT(DVP_ZONE_ALWAYS, "\n=============="); + DVP_PRINT(DVP_ZONE_ALWAYS, "Testing importing type:%d FOURCC:(0x%08x)\n", type, fourcc); + if (srv->allocate(&img.image, img.fds)) + { + DVP_PRINT(DVP_ZONE_ALWAYS, "Importing memory...\n"); + if (DVP_Image_Import(hDvp, &img.image, img.fds, img.hdls)) { + DVP_PrintImage(DVP_ZONE_ALWAYS, &img.image); + DVP_PRINT(DVP_ZONE_ALWAYS, "Success testing import!\n"); + if(!DVP_Image_Free_Import(hDvp, &img.image, img.hdls)) { + DVP_PRINT(DVP_ZONE_ERROR, "error freeing imported image!\n"); + } else { + num_tests_passed++; + } + } else { + DVP_PRINT(DVP_ZONE_ERROR, "Failed importing memory!\n"); + } + for (DVP_U32 i = 0; i < img.image.planes; i++) { + close(img.fds[i]); + } + } else { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: service failed to allocate image!\n"); + } + DVP_PRINT(DVP_ZONE_ALWAYS, "==============\n"); +} + +static void test_buffer_import(const sp& srv, DVP_Handle hDvp, DVP_MemType_e type) +{ + num_tests++; + + Buffer b; + DVP_Buffer_Init(&b.buf, 1, 1024); + b.buf.memType = type; + + DVP_PRINT(DVP_ZONE_ALWAYS, "\n=============="); + DVP_PRINT(DVP_ZONE_ALWAYS, "Testing importing buffer type:%d\n", type); + if (srv->allocate(&b.buf, &b.fd)) + { + DVP_PRINT(DVP_ZONE_ALWAYS, "Importing buffer memory fd:%d\n", b.fd); + if (DVP_Buffer_Import(hDvp, &b.buf, b.fd, &b.handle)) { + DVP_PrintBuffer(DVP_ZONE_ALWAYS, &b.buf); + DVP_PRINT(DVP_ZONE_ALWAYS, "Success testing buffer import!\n"); + if(!DVP_Buffer_Free_Import(hDvp, &b.buf, b.handle)) { + DVP_PRINT(DVP_ZONE_ERROR, "error freeing imported buffer!\n"); + } else { + num_tests_passed++; + } + } else { + DVP_PRINT(DVP_ZONE_ERROR, "Failed importing buffer memory!\n"); + } + close(b.fd); + } else { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: service failed to allocate buffer!\n"); + } + DVP_PRINT(DVP_ZONE_ALWAYS, "==============\n"); +} + +static void client(pid_t srv_pid) +{ + DVP_PRINT(DVP_ZONE_ALWAYS, "Started DVPService client...\n"); +#ifdef ANDROID + { //scope for srv strong pointer + sp srv; + status_t err = getService(String16("DVPService"), &srv); + if (err != NO_ERROR) { + DVP_PRINT(DVP_ZONE_ERROR, "ERROR: failed getting DVPService interface with error=0x%x\n", err); + return; + } + + DVP_Handle hDvp = DVP_MemImporter_Create(); + if (hDvp) { + test_image_import(srv, hDvp, FOURCC_Y800, DVP_MTYPE_DEFAULT); + test_image_import(srv, hDvp, FOURCC_NV12, DVP_MTYPE_DEFAULT); + + test_image_import(srv, hDvp, FOURCC_Y800, DVP_MTYPE_MPUCACHED_VIRTUAL_SHARED); + test_image_import(srv, hDvp, FOURCC_NV12, DVP_MTYPE_MPUCACHED_VIRTUAL_SHARED); +#if defined(DVP_USE_ION) + test_image_import(srv, hDvp, FOURCC_Y800, DVP_MTYPE_MPUNONCACHED_1DTILED); + test_image_import(srv, hDvp, FOURCC_NV12, DVP_MTYPE_MPUNONCACHED_1DTILED); + + test_image_import(srv, hDvp, FOURCC_Y800, DVP_MTYPE_MPUNONCACHED_2DTILED); + test_image_import(srv, hDvp, FOURCC_NV12, DVP_MTYPE_MPUNONCACHED_2DTILED); +#endif + test_buffer_import(srv, hDvp, DVP_MTYPE_DEFAULT); + test_buffer_import(srv, hDvp, DVP_MTYPE_MPUCACHED_VIRTUAL_SHARED); +#if defined(DVP_USE_ION) + test_buffer_import(srv, hDvp, DVP_MTYPE_MPUNONCACHED_1DTILED); +#endif + DVP_MemImporter_Free(hDvp); + } else { + DVP_PRINT(DVP_ZONE_ERROR, "Client failed creating dvp handle!\n"); + } + + srv->teardown(); + } +#endif + if(kill(srv_pid, SIGTERM) != 0) { + DVP_PRINT(DVP_ZONE_ERROR, "Error trying to kill DVPService\n"); + } + DVP_PRINT(DVP_ZONE_ERROR, "Client: Waiting for DVPService to exit...\n"); + int status; + waitpid(srv_pid, &status, 0); + + DVP_PRINT(DVP_ZONE_ERROR, "Client: DVPService exit_status(%d)\n", status); + + DVP_PRINT(DVP_ZONE_ALWAYS, "==============="); + DVP_PRINT(DVP_ZONE_ALWAYS, "Passed: %d/%d\n", num_tests_passed, num_tests); + DVP_PRINT(DVP_ZONE_ALWAYS, "Failed: %d/%d\n", num_tests-num_tests_passed, num_tests); + DVP_PRINT(DVP_ZONE_ALWAYS, "===============\n"); +} + +int main() +{ +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + +#if defined(DVP_RUNTIME_DEBUG) + debug_get_zone_mask("DVP_ZONE_MASK", &dvp_zone_mask); +#endif + + pid_t pid; + pid = fork(); + if (pid == 0) + server(); + else + client(pid); + return 0; +} diff --git a/source/dvp/dvp_test/dvp_simple.c b/source/dvp/dvp_test/dvp_simple.c new file mode 100644 index 0000000..2d2c581 --- /dev/null +++ b/source/dvp/dvp_test/dvp_simple.c @@ -0,0 +1,272 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include + +#if defined(LINUX) +#include +#include +#endif + +typedef struct _dvp_image_params_t { + DVP_Image_t *pImage; + DVP_U32 width; + DVP_U32 height; + fourcc_t color; + DVP_MemType_e type; +} DVP_Image_Params_t; + +DVP_BOOL DVP_Image_Construct(DVP_Handle handle, DVP_Image_Params_t *params, DVP_U32 numParams) +{ + DVP_BOOL ret = DVP_TRUE; + DVP_U32 i = 0; + for (i = 0; i < numParams; i++) + { + DVP_Image_Init(params[i].pImage, params[i].width, params[i].height, params[i].color); + params[i].pImage->skipCacheOpFlush = DVP_TRUE; + params[i].pImage->skipCacheOpInval = DVP_TRUE; + if (DVP_Image_Alloc(handle, params[i].pImage, params[i].type) == DVP_FALSE) { + ret = DVP_FALSE; + goto failed; + } + } +failed: + return ret; +} + +void DVP_KernelGraphCompleted(void *cookie, DVP_KernelGraph_t *graph, DVP_U32 sectionIndex, DVP_U32 numNodesExecuted) +{ + cookie = cookie; // warnings + graph = graph; // warnings + sectionIndex = sectionIndex; // warnings + numNodesExecuted = numNodesExecuted; // warnings + DVP_PRINT(DVP_ZONE_ALWAYS, "TEST: {%p} Graph %p Section [%u] completed %u of %u nodes\n", cookie, graph, sectionIndex, numNodesExecuted, graph->sections[sectionIndex].numNodes); +} + + +uint32_t width; +uint32_t height; +uint32_t type; +uint32_t capacity; +uint32_t iterations; +bool_e serial; +option_t opts[] = { + {OPTION_TYPE_INT, &width, sizeof(width), "-w", "--width", "Image Width"}, + {OPTION_TYPE_INT, &height, sizeof(height), "-h", "--height", "Image Height"}, + {OPTION_TYPE_INT, &type, sizeof(type), "-t", "--type", "Memory Type see DVP_MemType_e"}, + {OPTION_TYPE_INT, &capacity, sizeof(capacity), "-c", "--capacity", "Limit Mhz on all cores to this cap"}, + {OPTION_TYPE_INT, &iterations, sizeof(iterations), "-i", "--iterations", "The number of times the graph is executed"}, + {OPTION_TYPE_BOOL, &serial, sizeof(serial), "-s", "--serial", "Forces the execution of the graph in serial"}, +}; +uint32_t numOpts = dimof(opts); + +int main(int argc, char *argv[]) +{ + const DVP_U32 numNodes = 10; + DVP_Image_t images[11]; + DVP_Handle hDVP = 0; + DVP_KernelNode_t *pNodes = NULL; + DVP_U32 numSections = 0; + DVP_U32 i; + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + +#if defined(DVP_RUNTIME_DEBUG) + debug_get_zone_mask("DVP_ZONE_MASK", &dvp_zone_mask); +#endif + + // default values... + width = 320; + height = 240; + type = DVP_MTYPE_DEFAULT; + capacity = 100; + iterations = 1; + serial = false_e; + + // get the user values... + option_process(argc, argv, opts, numOpts); + +#if defined(LINUX) + { + int p = getpriority(PRIO_PROCESS, 0); // get our priority + setpriority(PRIO_PROCESS, 0, p-1); + } +#endif + + +#if (defined(DVP_USE_VLIB) || defined(DVP_USE_YUV)) + // get the handle (will implicitly load .so/.dll and initialize RPC). + hDVP = DVP_KernelGraph_Init(); + if (hDVP) + { + DVP_Image_Params_t params[] = { + {&images[0], width, height, FOURCC_UYVY, type}, + {&images[1], width, height, FOURCC_RGBP, DVP_MTYPE_DEFAULT}, + {&images[2], width, height, FOURCC_Y800, DVP_MTYPE_DEFAULT}, + {&images[3], width, height, FOURCC_YU24, DVP_MTYPE_DEFAULT}, + {&images[4], width, height, FOURCC_RGBP, DVP_MTYPE_DEFAULT}, + {&images[5], width, height, FOURCC_Y800, DVP_MTYPE_DEFAULT}, + {&images[6], width, height, FOURCC_IYUV, DVP_MTYPE_DEFAULT}, + {&images[7], width, height, FOURCC_RGBP, DVP_MTYPE_DEFAULT}, + {&images[8], width, height, FOURCC_Y800, DVP_MTYPE_DEFAULT}, + {&images[9], width, height, FOURCC_IYUV, DVP_MTYPE_DEFAULT}, + {&images[10], width, height, FOURCC_Y800, DVP_MTYPE_DEFAULT}, + }; + if (DVP_Image_Construct(hDVP, params, dimof(params)) == DVP_FALSE) + goto teardown; + + DVP_PRINT(DVP_ZONE_ALWAYS, "DVP_SIMPLE IMAGES:\n"); + for (i = 0; i < dimof(images); i++) + { + DVP_PrintImage(DVP_ZONE_ALWAYS, &images[i]); + } + + // create the nodes (will implicitly map to other cores) + pNodes = DVP_KernelNode_Alloc(hDVP, numNodes); + if (pNodes) + { + DVP_KernelGraphSection_t psections[] = { + {&pNodes[0], 3, DVP_PERF_INIT, DVP_CORE_LOAD_INIT, DVP_FALSE}, + {&pNodes[3], 3, DVP_PERF_INIT, DVP_CORE_LOAD_INIT, DVP_FALSE}, + {&pNodes[6], 3, DVP_PERF_INIT, DVP_CORE_LOAD_INIT, DVP_FALSE}, + {&pNodes[9], 1, DVP_PERF_INIT, DVP_CORE_LOAD_INIT, DVP_FALSE}, + }; + DVP_KernelGraphSection_t ssections[] = { + {&pNodes[0], 10, DVP_PERF_INIT, DVP_CORE_LOAD_INIT, DVP_FALSE}, + }; + + DVP_U32 orders[] = {0, 0, 0, 1}; + DVP_KernelGraph_t pgraph = { + psections, // make 3 parallel sections of the graph, then a serial section + dimof(psections), + orders, + DVP_PERF_INIT, + }; + DVP_KernelGraph_t sgraph = { + ssections, + dimof(ssections), + orders, + DVP_PERF_INIT, + }; + DVP_KernelGraph_t *graph = NULL; + DVP_Transform_t *io = NULL; + if (serial == true_e) + graph = &sgraph; + else + graph = &pgraph; + + // A9 processing + pNodes[0].header.kernel = DVP_KN_UYVY_TO_RGBp; + io = dvp_knode_to(&pNodes[0],DVP_Transform_t); + DVP_Image_Dup(&io->input, &images[0]); + DVP_Image_Dup(&io->output, &images[1]); + pNodes[0].header.affinity = DVP_CORE_CPU; + + pNodes[1].header.kernel = DVP_KN_XYXY_TO_Y800; + io = dvp_knode_to(&pNodes[1],DVP_Transform_t); + DVP_Image_Dup(&io->input, &images[0]); + DVP_Image_Dup(&io->output, &images[2]); + pNodes[1].header.affinity = DVP_CORE_CPU; + + pNodes[2].header.kernel = DVP_KN_UYVY_TO_YUV444p; + io = dvp_knode_to(&pNodes[2],DVP_Transform_t); + DVP_Image_Dup(&io->input, &images[0]); + DVP_Image_Dup(&io->output, &images[3]); + pNodes[2].header.affinity = DVP_CORE_CPU; + + // DSP Processing + pNodes[3].header.kernel = DVP_KN_UYVY_TO_RGBp; + io = dvp_knode_to(&pNodes[3],DVP_Transform_t); + DVP_Image_Dup(&io->input, &images[0]); + DVP_Image_Dup(&io->output, &images[4]); + pNodes[3].header.affinity = DVP_CORE_DSP; + + pNodes[4].header.kernel = DVP_KN_XYXY_TO_Y800; + io = dvp_knode_to(&pNodes[4],DVP_Transform_t); + DVP_Image_Dup(&io->input, &images[0]); + DVP_Image_Dup(&io->output, &images[5]); + pNodes[4].header.affinity = DVP_CORE_DSP; + + pNodes[5].header.kernel = DVP_KN_UYVY_TO_YUV420p; + io = dvp_knode_to(&pNodes[5],DVP_Transform_t); + DVP_Image_Dup(&io->input, &images[0]); + DVP_Image_Dup(&io->output, &images[6]); + pNodes[5].header.affinity = DVP_CORE_DSP; + + // SIMCOP Processing + pNodes[6].header.kernel = DVP_KN_UYVY_TO_RGBp; + io = dvp_knode_to(&pNodes[6],DVP_Transform_t); + DVP_Image_Dup(&io->input, &images[0]); + DVP_Image_Dup(&io->output, &images[7]); + pNodes[6].header.affinity = DVP_CORE_SIMCOP; + + pNodes[7].header.kernel = DVP_KN_XYXY_TO_Y800; + io = dvp_knode_to(&pNodes[7],DVP_Transform_t); + DVP_Image_Dup(&io->input, &images[0]); + DVP_Image_Dup(&io->output, &images[8]); + pNodes[7].header.affinity = DVP_CORE_SIMCOP; + + pNodes[8].header.kernel = DVP_KN_UYVY_TO_YUV420p; + io = dvp_knode_to(&pNodes[8],DVP_Transform_t); + DVP_Image_Dup(&io->input, &images[0]); + DVP_Image_Dup(&io->output, &images[9]); + pNodes[8].header.affinity = DVP_CORE_SIMCOP; + + // LAST SECTION + pNodes[9].header.kernel = DVP_KN_SOBEL_8; + io = dvp_knode_to(&pNodes[9],DVP_Transform_t); + DVP_Image_Dup(&io->input, &images[2]); + DVP_Image_Dup(&io->output, &images[10]); + pNodes[9].header.affinity = DVP_CORE_GPU; + + for (i = 0; i < DVP_CORE_MAX; i++) + { + DVP_U32 cap2, cap1 = DVP_GetCoreCapacity(hDVP, i); + DVP_SetCoreCapacity(hDVP, i, capacity); + cap2 = DVP_GetCoreCapacity(hDVP, i); + DVP_PRINT(DVP_ZONE_ALWAYS, "Core[%u] was set to limit at %u capacity, now at %u\n", i, cap1, cap2); + cap1 = cap1; // warnings + } + + do { + DVP_PRINT(DVP_ZONE_ALWAYS, "Iteration %u\n", iterations); + // perform the graph processing + numSections = DVP_KernelGraph_Process(hDVP, graph, NULL, DVP_KernelGraphCompleted); + DVP_PRINT(DVP_ZONE_ALWAYS, "%u Sections Completed!\n", numSections); + } while (iterations-- && numSections > 0); + // show us the results + DVP_PrintPerformanceGraph(hDVP, graph); + teardown: + // free the nodes + DVP_KernelNode_Free(hDVP, pNodes, numNodes); + } + + // free the image memory + for (i = 0; i < dimof(images); i++) + DVP_Image_Free(hDVP, &images[i]); + } + // tear down the graph resources + DVP_KernelGraph_Deinit(hDVP); +#else + DVP_PRINT(DVP_ZONE_ERROR, "Required VISION libraries are not present in the build!\n"); +#endif + return 0; +} diff --git a/source/dvp/dvp_test/dvp_test.cpp b/source/dvp/dvp_test/dvp_test.cpp new file mode 100644 index 0000000..ba7299d --- /dev/null +++ b/source/dvp/dvp_test/dvp_test.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +int main(int argc, char *argv[]) +{ +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + +#if defined(DVP_RUNTIME_DEBUG) + debug_get_zone_mask("DVP_ZONE_MASK", &dvp_zone_mask); +#endif + + if (argc > 1) + { + char name[MAX_PATH]; + + strncpy(name, argv[1], MAX_PATH); + uint32_t width = (argc > 2 ? atoi(argv[2]) : 160); + uint32_t height = (argc > 3 ? atoi(argv[3]) : 120); + uint32_t fps = (argc > 4 ? atoi(argv[4]) : 15); + fourcc_t color = (argc > 5 ? FOURCC_STRING(argv[5]) : (fourcc_t)FOURCC_UYVY); + uint32_t numFrames = (argc > 6 ? atoi(argv[6]) : 100); + uint32_t graph = (argc > 7 ? atoi(argv[7]) : 0); + DVP_Core_e affinity = DVP_CORE_MIN; + + if(argc > 8) + { + if (strcmp(argv[8], "cpu") == 0) affinity = DVP_CORE_CPU; + else if (strcmp(argv[8], "dsp") == 0) affinity = DVP_CORE_DSP; + else if (strcmp(argv[8], "simcop") == 0) affinity = DVP_CORE_SIMCOP; + else if (strcmp(argv[8], "gpu") == 0) affinity = DVP_CORE_GPU; + } + + TestVisionEngine engine(width, height, fps, color, name, numFrames, graph, affinity); + engine.Startup(); + if (engine.WaitForCompletion() == false) + engine.Shutdown(); + } + else + { + printf("$ %s [cpu|dsp|simcop|gpu]\n", argv[0]); + DVP_PRINT(DVP_ZONE_ALWAYS, "$ %s [cpu|dsp|simcop|gpu]\n", argv[0]); + } + return 0; +} diff --git a/source/dvp/dvp_test/dvp_unittest.c b/source/dvp/dvp_test/dvp_unittest.c new file mode 100644 index 0000000..1a43975 --- /dev/null +++ b/source/dvp/dvp_test/dvp_unittest.c @@ -0,0 +1,622 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#if defined(DVP_USE_YUV) +#include +#endif + +uint32_t iterations; +option_t opts[] = { + {OPTION_TYPE_INT, &iterations, sizeof(iterations), "-i", "--iter", "Iterations"}, +}; + +//********************************************************************** +// GLOBAL VARIABLES +//********************************************************************** + +DVP_CoreInfo_t cores[DVP_CORE_MAX]; +DVP_U32 numCoresEnabled; + +//********************************************************************** +// SUPPORT FUNCTIONS +//********************************************************************** + +/*! \brief Returns first error in nodes array */ +static DVP_Error_e dvp_get_error_from_nodes(DVP_KernelNode_t *nodes, + DVP_U32 numNodes) +{ + DVP_U32 n = 0; + DVP_Error_e err = DVP_SUCCESS; + for (n = 0; n < numNodes; n++) + { + err = nodes[n].header.error; + if (err != DVP_SUCCESS) + { + return err; + } + } + return err; +} + +/*! \brief Prints information when a section completes */ +static void dvp_section_complete(void *cookie, DVP_KernelGraph_t *graph, DVP_U32 sectionIndex, DVP_U32 nne) +{ + // just add to the number of nodes executed. + DVP_U32 *pCount = (DVP_U32 *)cookie; + DVP_U32 n = 0; + + for (n = 0; n < graph->sections[sectionIndex].numNodes; n++) + { + DVP_PRINT(DVP_ZONE_ALWAYS, "Section[%u]:Node[%u] Kernel 0x%x Affinity:%d status=%d\n", sectionIndex, n, + graph->sections[sectionIndex].pNodes[n].header.kernel, + graph->sections[sectionIndex].pNodes[n].header.affinity, + graph->sections[sectionIndex].pNodes[n].header.error); + } + *pCount += nne; +} + +/*! \brief Determines if an image is binary equal to another image. + */ +DVP_BOOL DVP_Image_Equal(DVP_Image_t *pDst, DVP_Image_t *pSrc) +{ + DVP_U32 p,y,i,j,l; + DVP_PrintImage(DVP_ZONE_MEM, pSrc); + DVP_PrintImage(DVP_ZONE_MEM, pDst); + + if (pSrc == NULL || pDst == NULL) + return DVP_FALSE; + + for (p = 0; p < pSrc->planes; p++) + if (pSrc->pData[p] == NULL) + return DVP_FALSE; + + for (p = 0; p < pDst->planes; p++) + if (pDst->pData[p] == NULL) + return DVP_FALSE; + + if (pSrc->width != pDst->width || + pSrc->height != pDst->height) + return DVP_FALSE; + + if (pDst->color == pSrc->color) + { + DVP_U32 xscale[DVP_MAX_PLANES] = {1,1,1,1}; + DVP_U32 yscale[DVP_MAX_PLANES] = {1,1,1,1}; + + switch (pSrc->color) + { + case FOURCC_IYUV: // YUV420 planar formats + case FOURCC_YV12: + xscale[1] = yscale[1] = 2; + xscale[2] = yscale[2] = 2; + break; + case FOURCC_YVU9: // YUV411 planar formats + case FOURCC_YUV9: + xscale[1] = yscale[1] = 4; + xscale[2] = yscale[2] = 4; + break; + case FOURCC_YV16: // YUV422 planar formats + case FOURCC_YU16: + xscale[1] = xscale[2] = 2; + yscale[1] = yscale[2] = 1; + break; + case FOURCC_NV12: + case FOURCC_NV21: + // xscale is literally 2 but macro pixel makes it equivalent to 1. + yscale[1] = 2; + break; + case FOURCC_YV24: // 4:4:4 planar formats + case FOURCC_YU24: + case FOURCC_RGBP: + case FOURCC_RGB565: + default: + // default values are fine + break; + } + + for (p = 0; p < pSrc->planes; p++) + { + for (y = 0; y < (pSrc->height/yscale[p]); y++) + { + i = (y * pSrc->y_stride); + j = (y * pDst->y_stride); + l = (pSrc->width * pSrc->x_stride)/xscale[p]; + if (memcmp(&pDst->pData[p][j], &pSrc->pData[p][i], l) != 0) + { + DVP_PRINT(DVP_ZONE_ERROR, "Line %d is not equal!\n", y); + return DVP_FALSE; + } + } + } + return DVP_TRUE; + } + return DVP_FALSE; +} + +//********************************************************************** +// UNITTESTS +//********************************************************************** + +/*! \brief Tests the creation and destruction of a DVP Handle. + * \return Returns status_e + * \retval STATUS_SUCCESS on success. + * \retval STATUS_FAILURE on failure. + * \ingroup group_tests + */ +status_e dvp_context_test(void) +{ + status_e status = STATUS_FAILURE; + DVP_Handle dvp = DVP_KernelGraph_Init(); + if (dvp) + { + status = STATUS_SUCCESS; + DVP_KernelGraph_Deinit(dvp); + } + return status; +} + +/*! \brief Tests the \ref DVP_QuerySystem API. + * \return Returns status_e + * \retval STATUS_SUCCESS on success. + * \retval STATUS_FAILURE on failure. + * \ingroup group_tests + */ +status_e dvp_info_test(void) +{ + status_e status = STATUS_FAILURE; + DVP_Handle dvp = DVP_KernelGraph_Init(); + if (dvp) + { + DVP_U32 c = 0; + memset(cores, 0, sizeof(cores)); + numCoresEnabled = 0; + + DVP_QuerySystem(dvp, cores); + + for (c = DVP_CORE_MIN+1; c < DVP_CORE_MAX; c++) + { + if (cores[c].enabled) + { + status = STATUS_SUCCESS; + numCoresEnabled++; + } + } + DVP_PRINT(DVP_ZONE_ALWAYS, "%u cores enabled!\n", numCoresEnabled); + DVP_KernelGraph_Deinit(dvp); + } + return status; +} + +/*! \brief Tests a single node NO-OP graph on CPU. + * \return Returns status_e + * \retval STATUS_SUCCESS on success. + * \retval STATUS_FAILURE on failure. + * \ingroup group_tests + */ +status_e dvp_cpu_nop_test(void) +{ + status_e status = STATUS_FAILURE; + DVP_Handle dvp = DVP_KernelGraph_Init(); + if (dvp) + { + DVP_U32 numNodes = 1; + DVP_U32 numSections = 1; + DVP_U32 numNodesExecuted = 0; + DVP_KernelNode_t *nodes = DVP_KernelNode_Alloc(dvp, numNodes); + if (nodes) + { + DVP_KernelGraph_t *graph = DVP_KernelGraph_Alloc(dvp, numSections); + if (graph) + { + DVP_Error_e err = DVP_SUCCESS; + err = DVP_KernelGraphSection_Init(dvp, graph, 0, nodes, numNodes); + if (err == DVP_SUCCESS) + { + DVP_U32 numSectionsRun = 0; + + nodes[0].header.kernel = DVP_KN_NOOP; + nodes[0].header.affinity = DVP_CORE_CPU; + + numSectionsRun = DVP_KernelGraph_Process(dvp, graph, &numNodesExecuted, dvp_section_complete); + err = dvp_get_error_from_nodes(nodes, numNodes); + if (numSectionsRun == numSections && numNodesExecuted == numNodes && err == DVP_SUCCESS) + { + status = STATUS_SUCCESS; + } + DVP_PRINT(DVP_ZONE_ALWAYS, "CPU NOP processed %u sections, %u nodes, first DVP_Error_e=%d\n", numSectionsRun, numNodesExecuted, err); + } + DVP_KernelGraph_Free(dvp, graph); + graph = NULL; + } + DVP_KernelNode_Free(dvp, nodes, numNodes); + nodes = NULL; + } + DVP_KernelGraph_Deinit(dvp); + } + return status; +} + + +/*! \brief Tests a serial array of nodes graph on all available cores. + * \return Returns status_e + * \retval STATUS_SUCCESS on success. + * \retval STATUS_FAILURE on failure. + * \ingroup group_tests + */ +status_e dvp_serial_nop_test(void) +{ + status_e status = STATUS_FAILURE; + DVP_Handle dvp = DVP_KernelGraph_Init(); + if (dvp) + { + DVP_U32 numSections = 1; + DVP_U32 numNodes = numCoresEnabled; + DVP_U32 numNodesExecuted = 0; + DVP_KernelNode_t *nodes = DVP_KernelNode_Alloc(dvp, numNodes); + if (nodes) + { + DVP_KernelGraph_t *graph = DVP_KernelGraph_Alloc(dvp, numSections); + if (graph) + { + DVP_Error_e err = DVP_SUCCESS; + err = DVP_KernelGraphSection_Init(dvp, graph, 0, nodes, numNodes); + if (err == DVP_SUCCESS) + { + DVP_U32 n, numSectionsRun = 0; + DVP_Core_e c; + + for (n = 0, c = DVP_CORE_MIN+1; c < DVP_CORE_MAX; c++) + { + if (cores[c].enabled == DVP_TRUE) + { + nodes[n].header.kernel = DVP_KN_NOOP; + nodes[n].header.affinity = (DVP_Core_e)c; + n++; + } + } + + numSectionsRun = DVP_KernelGraph_Process(dvp, graph, &numNodesExecuted, dvp_section_complete); + err = dvp_get_error_from_nodes(nodes, numNodes); + if (numSectionsRun == numSections && numNodesExecuted == numNodes && err == DVP_SUCCESS) + { + status = STATUS_SUCCESS; + } + DVP_PRINT(DVP_ZONE_ALWAYS, "SERIAL NOP processed %u sections, %u nodes, first DVP_Error_e=%d\n", numSectionsRun, numNodesExecuted, err); + } + DVP_KernelGraph_Free(dvp, graph); + graph = NULL; + } + DVP_KernelNode_Free(dvp, nodes, numNodes); + nodes = NULL; + } + DVP_KernelGraph_Deinit(dvp); + dvp = 0; + } + return status; +} + +/*! \brief Tests a "parallel set of nodes" graph on all available cores. + * \return Returns status_e + * \retval STATUS_SUCCESS on success. + * \retval STATUS_FAILURE on failure. + * \ingroup group_tests + */ +status_e dvp_parallel_nop_test(void) +{ + status_e status = STATUS_FAILURE; + DVP_Handle dvp = DVP_KernelGraph_Init(); + if (dvp) + { + DVP_U32 numNodes = numCoresEnabled; + DVP_U32 numSections = numCoresEnabled; + DVP_U32 numNodesExecuted = 0; + DVP_KernelNode_t *nodes = DVP_KernelNode_Alloc(dvp, numNodes); + if (nodes) + { + DVP_KernelGraph_t *graph = DVP_KernelGraph_Alloc(dvp, numSections); + if (graph) + { + DVP_Error_e err = DVP_SUCCESS; + DVP_U32 n, s = 0; + DVP_Core_e c; + + // one node per section... + for (s = 0; s < numSections; s++) + { + err = DVP_KernelGraphSection_Init(dvp, graph, s, &nodes[s], 1); + if (err != DVP_SUCCESS) + { + DVP_KernelGraph_Free(dvp, graph); + DVP_KernelNode_Free(dvp, nodes, numNodes); + return STATUS_NOT_ENOUGH_MEMORY; + } + } + + if (err == DVP_SUCCESS) + { + DVP_U32 numSectionsRun = 0; + + // set the core affinity to all the available cores. + for (n = 0, c = DVP_CORE_MIN+1; c < DVP_CORE_MAX; c++) + { + if (cores[c].enabled == DVP_TRUE) + { + nodes[n].header.kernel = DVP_KN_NOOP; + nodes[n].header.affinity = (DVP_Core_e)c; + n++; + } + } + + numSectionsRun = DVP_KernelGraph_Process(dvp, graph, &numNodesExecuted, dvp_section_complete); + err = dvp_get_error_from_nodes(nodes, numNodes); + if (numSectionsRun == numSections && numNodesExecuted == numNodes && err == DVP_SUCCESS) + { + status = STATUS_SUCCESS; + } + DVP_PRINT(DVP_ZONE_ALWAYS, "PARALLEL NOP processed %u sections, %u nodes, first DVP_Error_e=%d\n", numSectionsRun, numNodesExecuted, err); + } + DVP_KernelGraph_Free(dvp, graph); + graph = NULL; + } + DVP_KernelNode_Free(dvp, nodes, numNodes); + nodes = NULL; + } + DVP_KernelGraph_Deinit(dvp); + } + return status; +} + +/*! \brief Tests a set of copy nodes in series on all available cores. + * \return Returns status_e + * \retval STATUS_SUCCESS on success. + * \retval STATUS_FAILURE on failure. + * \ingroup group_tests + */ +status_e dvp_copy_test(void) +{ + status_e status = STATUS_FAILURE; + DVP_MemType_e mtype = DVP_MTYPE_DEFAULT; + DVP_Handle dvp = DVP_KernelGraph_Init(); +#if defined(DVP_USE_BO) || defined(DVP_USE_ION) + mtype = DVP_MTYPE_MPUCACHED_1DTILED; +#endif + if (dvp) + { + DVP_U32 numSections = 1; + DVP_U32 numNodes = numCoresEnabled; + DVP_U32 numNodesExecuted = 0; + DVP_KernelNode_t *nodes = DVP_KernelNode_Alloc(dvp, numNodes); + if (nodes) + { + DVP_KernelGraph_t *graph = DVP_KernelGraph_Alloc(dvp, numSections); + if (graph) + { + DVP_Error_e err = DVP_SUCCESS; + err = DVP_KernelGraphSection_Init(dvp, graph, 0, nodes, numNodes); + if (err == DVP_SUCCESS) + { +#define width 320 +#define height 240 + DVP_U32 n, numSectionsRun = 0; + DVP_Core_e c; + DVP_U08 ptr[height][width]; + memset(ptr, 0x57, sizeof(ptr)); + + for (n = 0, c = 0; c < DVP_CORE_MAX; c++) + { + if (cores[c].enabled == DVP_TRUE) + { + DVP_Transform_t *pT = dvp_knode_to(&nodes[n], DVP_Transform_t); + nodes[n].header.kernel = DVP_KN_ECHO; + nodes[n].header.affinity = (DVP_Core_e)c; + + DVP_Image_Init(&pT->input, width, height, FOURCC_Y800); + DVP_Image_Alloc(dvp, &pT->input, mtype); + + DVP_Image_Fill(&pT->input, (DVP_S08 *)ptr, width*height*sizeof(DVP_U08)); + + DVP_Image_Init(&pT->output, width, height, FOURCC_Y800); + DVP_Image_Alloc(dvp, &pT->output, mtype); + + n++; + } + } + + numSectionsRun = DVP_KernelGraph_Process(dvp, graph, &numNodesExecuted, dvp_section_complete); + err = dvp_get_error_from_nodes(nodes, numNodes); + + for (n = 0; n < numNodes; n++) + { + DVP_Transform_t *pT = dvp_knode_to(&nodes[n], DVP_Transform_t); + if (DVP_Image_Equal(&pT->output, &pT->input) == DVP_FALSE) + { + DVP_PRINT(DVP_ZONE_ERROR, "Output != Input on Node %d, Affinity %d\n", n, nodes[n].header.affinity); + err = DVP_ERROR_FAILURE; + } + DVP_Image_Free(dvp, &pT->input); + DVP_Image_Free(dvp, &pT->output); + } + + if (numSectionsRun == numSections && numNodesExecuted == numNodes && err == DVP_SUCCESS) + { + status = STATUS_SUCCESS; + } + DVP_PRINT(DVP_ZONE_ALWAYS, "Serial Copy processed %u sections, %u nodes, first DVP_Error_e=%d\n", numSectionsRun, numNodesExecuted, err); + } + DVP_KernelGraph_Free(dvp, graph); + graph = NULL; + } + DVP_KernelNode_Free(dvp, nodes, numNodes); + nodes = NULL; + } + DVP_KernelGraph_Deinit(dvp); + dvp = 0; + } + return status; +#undef width +#undef height +} + + +#if defined(DVP_USE_YUV) +/*! \brief Tests a split image color conversion. + * \return Returns status_e + * \retval STATUS_SUCCESS on success. + * \retval STATUS_FAILURE on failure. + * \ingroup group_tests + */ +status_e dvp_split_cc_test(void) +{ + status_e status = STATUS_FAILURE; + DVP_Handle dvp = DVP_KernelGraph_Init(); + if (dvp) + { + DVP_U32 numNodes = 2; + DVP_U32 numSections = 2; + DVP_U32 numNodesExecuted = 0; + DVP_KernelNode_t *nodes = DVP_KernelNode_Alloc(dvp, numNodes); + if (nodes) + { + DVP_KernelGraph_t *graph = DVP_KernelGraph_Alloc(dvp, numSections); + if (graph) + { + DVP_Error_e err = DVP_SUCCESS; + err = DVP_KernelGraphSection_Init(dvp, graph, 0, nodes, numNodes); + if (err == DVP_SUCCESS) + { + DVP_Image_t images[2]; + DVP_U32 numSectionsRun = 0; + DVP_Transform_t *io[2]; + DVP_Image_t *img[4]; + + DVP_Image_Init(&images[0], 1280, 720, FOURCC_ARGB); + DVP_Image_Init(&images[1], 1280, 720, FOURCC_UYVY); + + DVP_Image_Alloc(dvp, &images[0], DVP_MTYPE_MPUCACHED_VIRTUAL); + DVP_Image_Alloc(dvp, &images[1], DVP_MTYPE_MPUCACHED_VIRTUAL); + + nodes[0].header.kernel = DVP_KN_YUV_ARGB_TO_UYVY; + nodes[0].header.affinity = DVP_CORE_CPU; + io[0] = dvp_knode_to(&nodes[0],DVP_Transform_t); + DVP_Image_Dup(&io[0]->input, &images[0]); + DVP_Image_Dup(&io[0]->output, &images[1]); + + nodes[1].header.kernel = DVP_KN_YUV_ARGB_TO_UYVY; + nodes[1].header.affinity = DVP_CORE_CPU; + io[1] = dvp_knode_to(&nodes[1],DVP_Transform_t); + DVP_Image_Dup(&io[1]->input, &images[0]); + DVP_Image_Dup(&io[1]->output, &images[1]); + + // now perform some arimethic on the pointers to make each + // node cover half the image. + img[0] = &io[0]->input; + img[1] = &io[0]->output; + img[2] = &io[1]->input; + img[3] = &io[1]->output; + + img[0]->height /= 2; + img[1]->height /= 2; + img[2]->height /= 2; + img[3]->height /= 2; + + // move the pointer 1/2 down the image + img[2]->pData[0] = &img[2]->pData[0][img[2]->height * img[2]->y_stride]; + img[3]->pData[0] = &img[3]->pData[0][img[3]->height * img[3]->y_stride]; + + // assign each node to a separate section + DVP_KernelGraphSection_Init(dvp, graph, 0, &nodes[0], 1); + DVP_KernelGraphSection_Init(dvp, graph, 1, &nodes[1], 1); + + numSectionsRun = DVP_KernelGraph_Process(dvp, graph, &numNodesExecuted, dvp_section_complete); + err = dvp_get_error_from_nodes(nodes, numNodes); + if (numSectionsRun == numSections && numNodesExecuted == numNodes && err == DVP_SUCCESS) + { + status = STATUS_SUCCESS; + } + + DVP_Image_Free(dvp, &images[0]); + DVP_Image_Free(dvp, &images[1]); + + DVP_PRINT(DVP_ZONE_ALWAYS, "CPU CC processed %u sections, %u nodes, first DVP_Error_e=%d\n", numSectionsRun, numNodesExecuted, err); + DVP_PrintPerformanceGraph(dvp, graph); + } + DVP_KernelGraph_Free(dvp, graph); + graph = NULL; + } + DVP_KernelNode_Free(dvp, nodes, numNodes); + nodes = NULL; + } + DVP_KernelGraph_Deinit(dvp); + } + return status; +} +#endif + +/*! \brief Local Unit Test Function Pointer */ +typedef status_e (*dvp_unittest_f)(void); + +/*! \brief Unit test meta-data structure used to track result of each function */ +typedef struct _dvp_unittest_t { + status_e status; + char name[MAX_PATH]; + dvp_unittest_f function; +} dvp_unittest_t; + +dvp_unittest_t unittests[] = { + {STATUS_FAILURE, "Framework: Context", dvp_context_test}, + {STATUS_FAILURE, "Framework: QuerySystem", dvp_info_test}, + {STATUS_FAILURE, "Framework: CPU Nop Test", dvp_cpu_nop_test}, + {STATUS_FAILURE, "Framework: SERIAL Nop Test", dvp_serial_nop_test}, + {STATUS_FAILURE, "Framework: PARALLEL Nop Test", dvp_parallel_nop_test}, + {STATUS_FAILURE, "Framework: SERIAL Copy Test", dvp_copy_test}, +#if defined(DVP_USE_YUV) + {STATUS_FAILURE, "Framework: PARALLEL CC Test", dvp_split_cc_test}, +#endif +}; + +int main(int argc, char *argv[]) +{ + uint32_t i,j; + int err = 0; + int passed = 0; + iterations = 1; + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + +#if defined(DVP_RUNTIME_DEBUG) + debug_get_zone_mask("DVP_ZONE_MASK", &dvp_zone_mask); +#endif + + option_process(argc, argv, opts, dimof(opts)); + for (i = 0; i < dimof(unittests); i++) + { + for (j = 0; j < iterations; j++) + { + unittests[i].status = unittests[i].function(); + if (unittests[i].status == STATUS_SUCCESS) + passed++; + } + DVP_PRINT(DVP_ZONE_ALWAYS, "[%s] %s\n", (unittests[i].status == STATUS_SUCCESS?"PASSED":"FAILED"), unittests[i].name); + } + DVP_PRINT(DVP_ZONE_ALWAYS, "Passed %d out of %u\n", passed, dimof(unittests)); + return err; +} + diff --git a/source/omaprpc/Android.mk b/source/omaprpc/Android.mk new file mode 100644 index 0000000..9004ce4 --- /dev/null +++ b/source/omaprpc/Android.mk @@ -0,0 +1,30 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(IPC_TYPE),rpmsg) + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_SRC_FILES := omaprpc.c +LOCAL_CFLAGS := $(DVP_CFLAGS) $(OMAPRPC_DEBUGGING) +LOCAL_C_INCLUDES := $(DVP_TOP)/include $(TI_HW_ROOT)/omap4xxx +LOCAL_STATIC_LIBRARIES := libsosal +LOCAL_SHARED_LIBRARIES := libcutils +LOCAL_MODULE := libomaprpc +include $(BUILD_STATIC_LIBRARY) + +endif diff --git a/source/omaprpc/concerto.mak b/source/omaprpc/concerto.mak new file mode 100644 index 0000000..3b5c9b5 --- /dev/null +++ b/source/omaprpc/concerto.mak @@ -0,0 +1,25 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_CPU),ARM) +ifeq ($(TARGET_OS),LINUX) +include $(PRELUDE) +TARGET=omaprpc +TARGETTYPE=dsmo +IDIRS+=$(DVP_INC) +CSOURCES=omaprpc.c +IDIRS+=$(IPC_INCS) $(MEM_INCS) +include $(FINALE) +endif +endif diff --git a/source/omaprpc/omaprpc.c b/source/omaprpc/omaprpc.c new file mode 100644 index 0000000..8b36734 --- /dev/null +++ b/source/omaprpc/omaprpc.c @@ -0,0 +1,347 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#if defined(ANDROID) +#include +#endif + +#if defined(OMAPRPC_USE_ION) +#include +#if defined(ANDROID) +#include +#endif +#endif + +#define OMAPRPC_RESTART_CONDITION(ret) (ret == -ENXIO || ret == -ENOTCONN) + +//****************************************************************************** +// TYPEDEFS, ENUMS and #DEFINES +//****************************************************************************** + +/*! \brief The local definitions of debugging zones for OMAPRPC. + * \ingroup group_omaprpc + */ +typedef enum _omaprpc_zone_mask_e { + OMAPRPC_ZONE_ERROR = 0, /*!< \brief The error zone */ + OMAPRPC_ZONE_WARNING, /*!< \brief The warning zone for non-critical issues */ + OMAPRPC_ZONE_INFO, /*!< \brief The info zone for general information */ + OMAPRPC_ZONE_API, /*!< \brief The API zone for API tracing */ + OMAPRPC_ZONE_PERF, /*!< \brief The performance information zone */ + + // don't use this, it's only there to count the number of zones + OMAPRPC_ZONE_MAX +} OMAPRPC_ZoneMask_e; + +/*! \brief Used to set the \ref OMAPRPC_ZoneMask_e into a bitfield. */ +#define SET_FLAG(flag) (1<restart) + { + uint32_t retries = rpc->retries; + + // close the current file handle + close(rpc->device); + + // we will try at least once. + if (retries == 0) + retries = 1; + + do { + int ret = 0; +#if defined(POSIX) + struct timespec req, rem; + req.tv_sec = rem.tv_sec = rem.tv_nsec = 0; + req.tv_nsec = 100000; // 1 ms +#endif + // open a new handle + rpc->device = open(rpc->dev_name, O_RDWR); +#if defined(POSIX) + do { + ret = nanosleep(&req, &rem); + if (ret == -1 && errno == EINTR) + { + OMAPRPC_PRINT(OMAPRPC_ZONE_ERROR, "Signal interrupted nanosleep.\n"); + req.tv_nsec = rem.tv_nsec; + } + } while (ret != 0); +#endif + } while (rpc->device <= 0 && --retries > 0); + + if (rpc->device > 0) + { + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, "Re-opened device %s\n", rpc->dev_name); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, "Connecting to Service %s\n", rpc->create.name); + if (ioctl(rpc->device, OMAPRPC_IOC_CREATE, &rpc->create) < 0) + { + OMAPRPC_PRINT(OMAPRPC_ZONE_ERROR, "Failed to connect to remote service %s!\n", rpc->create.name); + omaprpc_close(&rpc); + } + else + { + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, "Opened %s for %s\n", rpc->dev_name, rpc->create.name); + } + + // call the restart function + rpc->restart(rpc, rpc->cookie); + } + } +} + +//****************************************************************************** +// GLOBAL FUNCTIONS +//****************************************************************************** + +void omaprpc_close(omaprpc_t **prpc) +{ + if (prpc) + { + omaprpc_t *rpc = *prpc; + if (rpc) + { + ioctl(rpc->device, OMAPRPC_IOC_DESTROY, 0); + close(rpc->device); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, "Closed OMAPRPC Device!\n"); + free(rpc); + *prpc = NULL; + } + } +} + +omaprpc_t *omaprpc_open(char *device_name, char *server_name, uint32_t numFuncs) +{ + omaprpc_t *rpc = NULL; + +#if defined(OMAPRPC_RUNTIME_DEBUG) + set_zone_mask(); + printf("zone_mask=%x, error=%x is error masked?=%x\n", zone_mask, SET_FLAG(OMAPRPC_ZONE_ERROR), (SET_FLAG(OMAPRPC_ZONE_ERROR) & zone_mask)); +#endif + + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, "Opening OMAPRPC Device %s server: %s\n", device_name, server_name); + rpc = (omaprpc_t *)calloc(1, sizeof(omaprpc_t)); + if (rpc) + { + strncpy(rpc->dev_name, device_name, MAX_PATH); + + rpc->device = open(device_name, O_RDWR); + if (rpc->device < 0) + { + OMAPRPC_PRINT(OMAPRPC_ZONE_ERROR, "Failed to open device %s\n", device_name); + omaprpc_close(&rpc); + } + else + { + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, "Opened %s as FD:%u\n", device_name, rpc->device); + + memset(&rpc->create, 0, sizeof(rpc->create)); + strncpy(rpc->create.name, server_name, sizeof(rpc->create.name)); + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, "Connecting to Service %s\n", rpc->create.name); + if (ioctl(rpc->device, OMAPRPC_IOC_CREATE, &rpc->create) < 0) + { + OMAPRPC_PRINT(OMAPRPC_ZONE_ERROR, "Failed to connect to remote service %s!\n", rpc->create.name); + omaprpc_close(&rpc); + } + else + { + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, "Opened %s for %s\n", rpc->dev_name, rpc->create.name); + rpc->num_funcs = numFuncs; + } + } + } + return rpc; +} + +void omaprpc_restart_callback(omaprpc_t *rpc, void *cookie, omaprpc_endpoint_restarted_f func, uint32_t retries) +{ + if (rpc && func) // don't check cookie, it's ok if it is NULL; + { + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, "Registered Restart Callback %p(%p)\n", func, cookie); + rpc->restart = func; + rpc->cookie = cookie; + rpc->retries = retries; + } +} + +bool_e omaprpc_unregister(omaprpc_t *rpc, int memdevice, void *ptr, void **reserved) +{ + bool_e unregistered = false_e; + if (rpc) + { +#if defined(OMAPRPC_USE_ION) + struct ion_fd_data data; + memdevice = memdevice; // removes warning + ptr = ptr; // removes warning + data.handle = *((struct ion_handle **)reserved); + if (ioctl(rpc->device, OMAPRPC_IOC_IONUNREGISTER, &data) >= 0) + unregistered = true_e; + if (unregistered) { + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, "Unregistered %p with OMAPRPC:%u\n", ptr, rpc->device); + } else { + OMAPRPC_PRINT(OMAPRPC_ZONE_ERROR, "Failed to unregister %p with OMAPRPC:%u\n", ptr, rpc->device); + } +#endif + } + return unregistered; +} + +bool_e omaprpc_register(omaprpc_t *rpc, int memdevice, void *ptr, void **reserved) +{ + bool_e registered = false_e; + if (rpc && memdevice && ptr && reserved) + { +#if defined(OMAPRPC_USE_ION) + struct ion_fd_data data; + struct ion_handle *ih = *((struct ion_handle **)reserved); + int ret = ion_share(memdevice, ih, &data.fd); + if (ret < 0) + { + OMAPRPC_PRINT(OMAPRPC_ZONE_ERROR, "Failed to share ION memory! (err=%d)\n", ret); + } + else + { + ret = ioctl(rpc->device, OMAPRPC_IOC_IONREGISTER, &data); + if (ret < 0) + { + OMAPRPC_PRINT(OMAPRPC_ZONE_ERROR, "Failed to register ION buffer with OMAPRPC:%u! (err=%d)\n", rpc->device, ret); + } + else + { + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, "Registered %p with OMAPRPC:%u!\n", data.handle, rpc->device); + if (data.handle != ih) { + OMAPRPC_PRINT(OMAPRPC_ZONE_ERROR, "ERROR: Handle from registration has changed! Was %p now %p\n", ih, data.handle); + } + *((struct ion_handle **)reserved) = data.handle; + registered = true_e; + } + } +#endif + } + return registered; +} + + +bool_e omaprpc_call(omaprpc_t *rpc, struct omaprpc_call_function_t *function, struct omaprpc_function_return_t *returned) +{ + clock_t start = clock(), end = 0, diff = 0; + bool_e passed = false_e; + int ret = 0; + if (rpc && function->func_index < rpc->num_funcs) + { + size_t func_len = sizeof(struct omaprpc_call_function_t) + (function->num_translations * sizeof(struct omaprpc_param_translation_t)); + + ret = write(rpc->device, function, func_len); + if (ret < 0) + { + passed = false_e; + if (OMAPRPC_RESTART_CONDITION(ret)) + { + omaprpc_restart(rpc); + return passed; + } + } + else if (returned) // provided pointer to get return value... + { + int ret = 0; + end = clock(); + diff = end-start; + OMAPRPC_PRINT(OMAPRPC_ZONE_PERF, "Called function %u, (write on fd %d took %lu ticks CLOCKS_PER_SEC=%lu) waiting on response...\n", function->func_index, rpc->device, diff, (clock_t)CLOCKS_PER_SEC); + start = clock(); + ret = read(rpc->device, returned, sizeof(*returned)); + if (ret >= 0) + passed = true_e; + end = clock(); + diff = end - start; + OMAPRPC_PRINT(OMAPRPC_ZONE_PERF, "read on device fd %u took %lu ticks\n", rpc->device, diff); + if (passed) { + OMAPRPC_PRINT(OMAPRPC_ZONE_INFO, "Function %u return value %d\n", returned->func_index, returned->status); + } else { + OMAPRPC_PRINT(OMAPRPC_ZONE_ERROR, "Failed to read from driver (errno=%d)\n", errno); + } + + if (OMAPRPC_RESTART_CONDITION(ret)) + { + omaprpc_restart(rpc); + passed = false_e; + } + } + else + passed = true_e; + } + return passed; +} diff --git a/source/sosal/Android.mk b/source/sosal/Android.mk new file mode 100644 index 0000000..daf91b9 --- /dev/null +++ b/source/sosal/Android.mk @@ -0,0 +1,111 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(SOSAL_DEBUGGING) $(SOSAL_CFLAGS) +LOCAL_SRC_FILES := $(filter-out shared.c unittest.c,$(call all-c-files-under,.)) +LOCAL_C_INCLUDES := $(SOSAL_TOP)/include +ifeq ($(PLAT_MAJOR),4) # ICS or later + LOCAL_C_INCLUDES += hardware/ti/omap4xxx +else + LOCAL_C_INCLUDES += $(TILER_INC) +endif +LOCAL_MODULE := libsosal +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CPPFLAGS := $(SOSAL_DEBUGGING) $(SOSAL_CPPFLAGS) -DSHARED_MEMORY_CLIENT +LOCAL_SRC_FILES := shared.cpp shared_binder.cpp +LOCAL_C_INCLUDES := $(SOSAL_TOP)/include +LOCAL_MODULE := libsosal_shm +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CPPFLAGS := $(SOSAL_DEBUGGING) $(SOSAL_CPPFLAGS) +LOCAL_SRC_FILES := allocator_binder.cpp +LOCAL_C_INCLUDES := $(SOSAL_TOP)/include +LOCAL_MODULE := liballoc_binder +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(SOSAL_DEBUGGING) $(SOSAL_CFLAGS) -DSOSAL_UNITTEST +LOCAL_SRC_FILES := unittest.c +LOCAL_C_INCLUDES := $(SOSAL_TOP)/include +LOCAL_MODULE := sosal_test +LOCAL_STATIC_LIBRARIES := libsosal libsosal_shm +LOCAL_SHARED_LIBRARIES := libdl libutils libui libcutils libbinder +ifeq ($(PLAT_MAJOR),4) # ICS or later + LOCAL_SHARED_LIBRARIES += libion libhardware + LOCAL_LDLIBS += -lhwcomposer.omap4 +else + LOCAL_SHARED_LIBRARIES += $(TILER_LIB) +endif +include $(BUILD_EXECUTABLE) + +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := tests +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(SOSAL_DEBUGGING) $(SOSAL_CFLAGS) -DUINPUT_TEST +LOCAL_SRC_FILES := event.c mutex.c options.c queue.c ring.c thread.c uinput.c debug.c +LOCAL_C_INCLUDES := $(SOSAL_TOP)/include +LOCAL_MODULE := uinput_test +LOCAL_SHARED_LIBRARIES := libcutils +include $(BUILD_EXECUTABLE) + +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CPPFLAGS := $(SOSAL_DEBUGGING) $(SOSAL_CPPFLAGS) -DSHARED_MEMORY_SERVICE +LOCAL_SRC_FILES := shared_binder.cpp debug.c +LOCAL_C_INCLUDES := $(SOSAL_TOP)/include +LOCAL_MODULE := shm_service +LOCAL_STATIC_LIBRARIES := libsosal +LOCAL_SHARED_LIBRARIES := libdl libcutils libutils libbinder +include $(BUILD_EXECUTABLE) + +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CPPFLAGS := $(SOSAL_DEBUGGING) $(SOSAL_CPPFLAGS) +LOCAL_SRC_FILES := CThreaded.cpp +LOCAL_C_INCLUDES += $(SOSAL_TOP)/include +LOCAL_MODULE := libcthreaded +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm +LOCAL_CFLAGS := $(SOSAL_DEBUGGING) $(SOSAL_CFLAGS) -DMODULE_TEST +LOCAL_SRC_FILES := module.c debug.c +LOCAL_C_INCLUDES := $(SOSAL_TOP)/include +LOCAL_MODULE := modload_test +LOCAL_SHARED_LIBRARIES := libdl libcutils +include $(BUILD_EXECUTABLE) diff --git a/source/sosal/CThreaded.cpp b/source/sosal/CThreaded.cpp new file mode 100644 index 0000000..74dc590 --- /dev/null +++ b/source/sosal/CThreaded.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +extern "C" thread_ret_t ThreadWrapper(void * subclassthis) +{ + thread_ret_t ret = (thread_ret_t)-1; + CThreaded *ct = reinterpret_cast(subclassthis); + SOSAL_PRINT(SOSAL_ZONE_THREAD, "CThreaded::ThreadWrapper Launched Thread in Subclass %p!\n", ct); + ret = ct->RunThread(); + SOSAL_PRINT(SOSAL_ZONE_THREAD, "CThreaded::ThreadWrapper Returned Thread in Subclass %p with code "THREAD_RET_FMT"!\n", ct, ret); + thread_exit(ret); +} + +CThreaded::CThreaded() +{ + m_handle = 0; + m_running = false; + mutex_init(&m_mutex); + SOSAL_PRINT(SOSAL_ZONE_API, "+CThreaded()\n"); +} + +CThreaded::~CThreaded() +{ + StopThread(); + mutex_unlock(&m_mutex); + mutex_deinit(&m_mutex); + SOSAL_PRINT(SOSAL_ZONE_API, "~CThreaded()\n"); +} + +void CThreaded::Lock() +{ + mutex_lock(&m_mutex); +} + +void CThreaded::Unlock() +{ + mutex_unlock(&m_mutex); +} + +bool CThreaded::StartThread(void *subclassthis) +{ + if (m_handle == 0 && m_running == false) + { + SOSAL_PRINT(SOSAL_ZONE_THREAD, "Starting CThreaded Derived Thread %p through Wrapper!\n", subclassthis); + m_running = true; + m_handle = thread_create(ThreadWrapper, subclassthis); + if (m_handle == 0) + { + m_running = false; + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Failed to create thread!\n"); + } + else + { + SOSAL_PRINT(SOSAL_ZONE_THREAD, "CThreaded Thread Started "THREAD_FMT"\n", m_handle); + } + } + else + { + SOSAL_PRINT(SOSAL_ZONE_THREAD, "Thread "THREAD_FMT" is already started or running %s\n", m_handle, (m_running?"TRUE":"FALSE")); + } + return m_running; +} + +bool CThreaded::StopThread() +{ + if (m_running) + { + m_running = false; + if (m_handle) + { + SOSAL_PRINT(SOSAL_ZONE_THREAD, "Stopping CThreaded Derived Thread "THREAD_FMT"\n", m_handle); + Shutdown(); + thread_ret_t err = thread_join(m_handle); + SOSAL_PRINT(SOSAL_ZONE_THREAD, "Derived CThreaded joined with code "THREAD_RET_FMT"!\n",err); + err = err; // warnings + m_handle = 0; + } + } + return !m_running; +} + +void CThreaded::Shutdown() +{ + return; +} + +#ifdef _TEST_ + +class CThreadedTest : public CThreaded { +public: + CThreadedTest() : CThreaded() + { + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "+CThreadedTest()\n"); + } + ~CThreadedTest() + { + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "-CThreadedTest()\n"); + } + + thread_ret_t RunThread() + { + do + { + Lock(); + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "CThreadedTest RunThread!!\n"); + Unlock(); + thread_msleep(100); + } while (m_running); + return 0; + } +}; + +uint32_t sosal_zone_mask; // declare a local mask for testing. + +int main(int argc, char *argv[]) +{ +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + + CThreadedTest *ctt = new CThreadedTest(); + ctt->StartThread(ctt); + thread_msleep(500); + ctt->StopThread(); + delete ctt; +} +#endif diff --git a/source/sosal/allocator.c b/source/sosal/allocator.c new file mode 100644 index 0000000..28562b6 --- /dev/null +++ b/source/sosal/allocator.c @@ -0,0 +1,1280 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#if defined(SOSAL_USE_SHARED_T) +#include +#endif + +#if defined(SOSAL_USE_TILER) // SYSLINK 1.0 to 2.0 Platforms (QNX, Windows, Android GB/FROYO) +#include +#endif + +#if defined(SOSAL_USE_ION) // Android ICS +#include +#endif + +#if defined(SOSAL_USE_GRALLOC) // Android ICS and GB +#include +#endif + +#if defined(SOSAL_USE_BO) // Linux 3.3.0+ +#include +#include +#endif + +#ifndef PAGE_SHIFT +#define PAGE_SHIFT (12) +#else +#if PAGE_SHIFT != 12 +#error "PAGE SHIFT has been defined in an incompatible way!" +#endif +#endif + +#if defined(SOSAL_USE_ION) +typedef struct _ion_fd_hdl_t { + struct ion_handle *handle; + int fd; +} ion_fd_hdl_t; +#endif + +#define _SOSAL_ALLOCATOR_T_DEFINED +typedef struct _allocator_t { +#if defined(TARGET_DVP_OMAP4) || defined(TARGET_DVP_OMAP5) +#if defined(SOSAL_USE_ION) + int32_t device; + list_t fd_list; +#endif +#if defined(SOSAL_USE_GRALLOC) + IMG_gralloc_module_public_t *module; + alloc_device_t *allocator; +#endif +#if defined(SOSAL_USE_BO) + int32_t drm_fd; + struct omap_device *drm_dev; +#endif +#endif + uint32_t reserved; +} allocator_t; + +#include + +#define SOSAL_ALLOCATOR_ALIGN (128) + +#if defined(SOSAL_USE_ION) +static int list_hdl_compare(node_t *a, node_t *b) +{ + ion_fd_hdl_t *ad = (ion_fd_hdl_t *)a->data; + ion_fd_hdl_t *bd = (ion_fd_hdl_t *)b->data; + if (ad->handle > bd->handle) + return 1; + else if (ad->handle < bd->handle) + return -1; + else + return 0; +} +#endif + +#if defined(SOSAL_USE_SHARED_T) +/** Returns a randomly generated unique number */ +static unique_t allocator_rand() +{ + uint32_t n = 0; + unique_t un = 0; + for (n = 0; n < sizeof(unique_t); n++) + { + un |= ((rand()&0xFF) << (n*8)); + } + return un; +} +#endif + +/** This returns the SOSAL_PAGE_SIZE aligned size */ +static size_t allocator_page_align_size(size_t size) +{ + size_t rsize = size; + size_t rem = size & (SOSAL_PAGE_SIZE - 1); + if (rem > 0) + rsize = size + (SOSAL_PAGE_SIZE - rem); + SOSAL_PRINT(SOSAL_ZONE_MEM, "RESIZED "FMT_SIZE_T" to "FMT_SIZE_T"\n", size, rsize); + return rsize; +} + +void allocator_deinit(allocator_t **palloc) +{ + if (palloc) + { + allocator_t *alloc = *palloc; + if (alloc) + { +#if defined(SOSAL_USE_TILER) + // nothing +#elif defined(SOSAL_USE_ION) + if (alloc->device > 0) + ion_close(alloc->device); + alloc->device = 0; +#endif +#if defined(SOSAL_USE_GRALLOC) + if (alloc->allocator) { + gralloc_close(alloc->allocator); + } + alloc->allocator = NULL; + alloc->module = NULL; +#endif +#if defined(SOSAL_USE_BO) + if (alloc->drm_dev) { + omap_device_del(alloc->drm_dev); + alloc->drm_dev = NULL; + close(alloc->drm_fd); + } +#endif + free(alloc); + } + *palloc = NULL; + } +} + + +allocator_t *allocator_init() +{ + allocator_t *alloc = (allocator_t *)calloc(1, sizeof(allocator_t)); + int32_t errors = 0; + if (alloc) + { +#if defined(SOSAL_USE_TILER) + alloc->reserved = 1; +#elif defined(SOSAL_USE_ION) + if (errors == 0) + { + alloc->device = ion_open(); + if (alloc->device < 0) + errors++; + } +#endif +#if defined(SOSAL_USE_GRALLOC) + if (errors == 0) + { + int32_t ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const struct hw_module_t **)&alloc->module); + SOSAL_PRINT(SOSAL_ZONE_MEM, "hw_get_module(%s,...) returned %d\n", GRALLOC_HARDWARE_MODULE_ID, ret); + if (ret < 0) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to open Gralloc HW\n"); + errors++; + } + SOSAL_PRINT(SOSAL_ZONE_MEM, "hw_module_t *%p by %s\n", alloc->module, alloc->module->base.common.author); + ret = gralloc_open((const struct hw_module_t *)alloc->module, &alloc->allocator); + if (ret < 0) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to open Gralloc Allocator!\n"); + errors++; + } + } +#endif +#if defined(SOSAL_USE_BO) + if (errors == 0) + { + alloc->drm_fd = drmOpen("omapdrm", NULL); + if (alloc->drm_fd < 0) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to open OMAPDRM device!\n"); + errors++; + } + else + { + alloc->drm_dev = omap_device_new(alloc->drm_fd); + if (alloc->drm_dev == NULL) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to create new OMAP device structure!\n"); + errors++; + } + } + } +#endif + if (errors > 0) + { + allocator_deinit(&alloc); + } + } + return alloc; +} + +int allocator_get_device(allocator_t *alloc, allocator_memory_type_e mtype) +{ + int fd = 0; + + if (alloc == NULL || + mtype == ALLOCATOR_MEMORY_TYPE_VIRTUAL) + return 0; + +#if defined(SOSAL_USE_ION) + if (mtype == ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED || + mtype == ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED || + mtype == ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED || + mtype == ALLOCATOR_MEMORY_TYPE_TILED_2D_CACHED) + fd = alloc->device; +#endif + return fd; +} + +bool_e allocator_flush(allocator_t *alloc, + allocator_memory_type_e mtype, + int32_t nptrs, + int32_t ndims, + allocator_dimensions_t *dims, + ptr_t *ptrs, + value_t *hdls) +{ + bool_e ret = true_e; // lie to the upper layers if it's not the right type + + if (alloc == NULL || mtype > ALLOCATOR_MEMORY_TYPE_MAX || nptrs <= 0 || ndims <= 0 || dims == NULL || ptrs == NULL) + return false_e; + +#if defined(SOSAL_USE_ION) + if (nptrs > 0 && mtype == ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED && hdls != NULL) + { + int32_t n,p; + uint32_t size; + ret = true_e; + for (p = 0; p < nptrs; p++) + { + if (hdls[p] == 0) + continue; + + // calculate the size of the plane + size = 1; + for (n = 0; n < ndims; n++) + size *= dims[p].dims[n]; +#if defined(SOSAL_USE_ION_CACHING) + SOSAL_PRINT(SOSAL_ZONE_MEM, "Flushing PTR:%p HDL:"FMT_VALUE_T" SIZE:%u\n", ptrs[p], hdls[p], size); + if (ion_flush_cached(alloc->device, (struct ion_handle *)hdls[p], size, ptrs[p]) < 0) + ret = false_e; +#endif + } + } + else + { + SOSAL_PRINT(SOSAL_ZONE_WARNING, "Memory type %d does not need to be flushed!\n", mtype); + } +#endif + return ret; +} + +bool_e allocator_invalidate(allocator_t *alloc, + allocator_memory_type_e mtype, + int32_t nptrs, + int32_t ndims, + allocator_dimensions_t *dims, + ptr_t *ptrs, + value_t *hdls) +{ + bool_e ret = true_e; // lie to the upper layers if it's not the right type + + if (alloc == NULL || mtype > ALLOCATOR_MEMORY_TYPE_MAX || nptrs <= 0 || ndims <= 0 || dims == NULL || ptrs == NULL) + return false_e; + +#if defined(SOSAL_USE_ION) + if (nptrs > 0 && mtype == ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED) + { + int32_t n,p; + uint32_t size; + ret = true_e; + for (p = 0; p < nptrs; p++) + { + if (hdls[p] == 0) + continue; + + // calculate the size of the plane + size = 1; + for (n = 0; n < ndims; n++) + size *= dims[p].dims[n]; + +#if defined(SOSAL_USE_ION_CACHING) + SOSAL_PRINT(SOSAL_ZONE_MEM, "Invalidating PTR:%p HDL:"FMT_VALUE_T" SIZE:%u\n", ptrs[p], hdls[p], size); + if (ion_inval_cached(alloc->device, (struct ion_handle *)hdls[p], size, ptrs[p]) < 0) + ret = false_e; +#endif + } + } + else { + SOSAL_PRINT(SOSAL_ZONE_WARNING, "Memory type %d does not need to be invalidated!\n", mtype); + } +#endif + return ret; +} + +bool_e allocator_free(allocator_t *alloc, + allocator_memory_type_e mtype, + int32_t nptrs, + ptr_t *ptrs, + value_t *hdls) +{ + int32_t err = 0; + bool_e ret = true_e; + int32_t p = 0; + + if (alloc == NULL || nptrs <= 0 || ptrs == NULL) + return false_e; + + switch (mtype) + { +#if defined(SOSAL_USE_TILER) + case ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED: + // hdls can be NULL, but shouldn't be. + + for (p = 0; p < nptrs; p++) { + if (ptrs[p] == NULL) + continue; + SOSAL_PRINT(SOSAL_ZONE_MEM, "TILER: Freeing %p\n", ptrs[p]); + err = MemMgr_Free(ptrs[p]); + if (err != MEMMGR_ERR_NONE) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "%s: Failed to free TILER buffer %p (err=%d)\n", __FUNCTION__, ptrs[p], err); + } + ptrs[p] = NULL; + } + break; +#elif defined(SOSAL_USE_ION) + case ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_2D_CACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED: + if (hdls == NULL) + return false_e; + for (p = 0; p < nptrs; p++) { + node_t node, *tmp; + ion_fd_hdl_t fd_hdl = { + .handle = 0, + .fd = 0, + }; + if (ptrs[p] == NULL || hdls[p] == 0) + continue; + SOSAL_PRINT(SOSAL_ZONE_MEM, "ION: Freeing %p Hdl:"FMT_VALUE_T"\n", ptrs[p],hdls[p]); + if (ion_free(alloc->device, (struct ion_handle *)hdls[p]) < 0) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "%s: Failed to free ION hdl: "FMT_VALUE_T" ptr: %p\n", __FUNCTION__, hdls[p], ptrs[p]); + } + fd_hdl.handle = (struct ion_handle *)hdls[p]; + node.data = (value_t)&fd_hdl; + tmp = list_remove_match(&alloc->fd_list, &node, list_hdl_compare); + if (tmp) + { + ion_fd_hdl_t *fd_hdl = (ion_fd_hdl_t *)tmp->data; + close(fd_hdl->fd); + free(fd_hdl); + free(tmp); + } + hdls[p] = 0; + ptrs[p] = NULL; + } + break; +#endif +#if defined(SOSAL_USE_GRALLOC) + case ALLOCATOR_MEMORY_TYPE_GFX_2D_UNCACHED: + if (hdls == NULL) + return false_e; + // no unmapping needed for GRALLOC + for (p = 0; p < nptrs; p++) { + if (hdls[p] != 0) { // only try to free valid handles. + SOSAL_PRINT(SOSAL_ZONE_MEM, "GRALLOC: Freeing %p Hdl:"FMT_VALUE_T"\n", ptrs[p], hdls[p]); + err = alloc->module->base.unlock((const struct gralloc_module_t *)alloc->module, (buffer_handle_t)hdls[p]); + ptrs[p] = NULL; + err = alloc->allocator->free((struct alloc_device_t *)alloc->allocator, (buffer_handle_t)hdls[p]); + if (err < 0) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "%s: Failed to free GRALLOC buffer hdl "FMT_VALUE_T"\n", __FUNCTION__, hdls[p]); + ret = false_e; + } + } + hdls[p] = 0; + } + break; +#endif +#if defined(SOSAL_USE_BO) + case ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED: + case ALLOCATOR_MEMORY_TYPE_GFX_2D_UNCACHED: + if (hdls == NULL) + return false_e; + for (p = 0; p < nptrs; p++) { + if (hdls[p]) { + alloc_omap_bo_t *bot = (alloc_omap_bo_t *)hdls[p]; + SOSAL_PRINT(SOSAL_ZONE_MEM, "BO: Freeing %p\n", bot->bo); + close(bot->dmabuf_fd); + omap_bo_del((struct omap_bo *)bot->bo); // this unmaps for us + free(bot); + hdls[p] = 0; + ptrs[p] = NULL; + } + } + break; +#endif +#if defined(SOSAL_USE_TILER) + case ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED: +#endif + case ALLOCATOR_MEMORY_TYPE_VIRTUAL: + for (p = 0; p < nptrs; p++) { + if (ptrs[p] == NULL) + continue; + SOSAL_PRINT(SOSAL_ZONE_MEM, "Freeing %p\n", ptrs[p]); + free(ptrs[p]); + ptrs[p] = NULL; + } + break; +#if defined(SOSAL_USE_SHARED_T) + case ALLOCATOR_MEMORY_TYPE_VIRTUAL_SHARED: + { + for (p = 0; p < nptrs; p++) + { +#if defined(SOSAL_DEBUG) + shared_t *shm = (shared_t *)hdls[p]; + SOSAL_PRINT(SOSAL_ZONE_MEM, "SHM: Freeing %p, UN:0x%08x\n", ptrs[p], shm->un); +#endif + shared_free((shared_t **)&hdls[p]); + ptrs[p] = NULL; + } + break; + } +#endif + default: + SOSAL_PRINT(SOSAL_ZONE_ERROR, "%s: Unknown memory type %d\n", __FUNCTION__, mtype); + ret = false_e; + break; + } + return ret; +} + + +bool_e allocator_calloc(allocator_t *alloc, + allocator_memory_type_e mtype, + int32_t nptrs, + int32_t ndims, + allocator_dimensions_t *dims, + ptr_t *ptrs, + value_t *hdls, + allocator_dimensions_t *strides) +{ + bool_e ret = true_e; + uint32_t size = 0; + int32_t p = 0, n = 0; + uint32_t flags = 0; + + if (alloc == NULL || nptrs <= 0 || ndims <= 0 || dims == NULL || ptrs == NULL) + return false_e; + + SOSAL_PRINT(SOSAL_ZONE_MEM, "%s: Attempting allocation of %d ptrs of type %d\n", __FUNCTION__, nptrs, mtype); + + // Remove warnings about unused variables + flags |= 0; + + switch (mtype) + { +#if defined(SOSAL_USE_TILER) + case ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED: + { + MemAllocBlock *blocks = calloc(nptrs, sizeof(MemAllocBlock)); + if (blocks) + { + for (p = 0; p < nptrs; p++) + { + size = 1; + for (n = 0; n < ndims; n++) + size *= dims[p].dims[n]; + + size = allocator_page_align_size(size); + if (mtype == ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED) + { + blocks[p].dim.area.width = dims[p].img.width; + blocks[p].dim.area.height = dims[p].img.height; + switch (dims[p].img.bpp) + { + case sizeof(uint8_t): + blocks[p].pixelFormat = PIXEL_FMT_8BIT; + break; + case sizeof(uint16_t): + blocks[p].pixelFormat = PIXEL_FMT_16BIT; + break; + case 3: // triples + blocks[p].pixelFormat = PIXEL_FMT_8BIT; + blocks[p].dim.area.width *= 3; + break; + case sizeof(uint32_t): + blocks[p].pixelFormat = PIXEL_FMT_32BIT; + break; + default: + break; + } + } + else + { + blocks[p].dim.len = size; + blocks[p].pixelFormat = PIXEL_FMT_PAGE; + } + SOSAL_PRINT(SOSAL_ZONE_MEM, "%s: Allocating TYPE:%d FMT:%d DIM:%ux%u\n", + __FUNCTION__, + mtype, + blocks[p].pixelFormat, + blocks[p].dim.area.width, + blocks[p].dim.area.height); + + } + hdls[0] = (value_t)MemMgr_Alloc(blocks, nptrs); + if (hdls[0]) + { + for (p = 0; p < nptrs; p++) + { + strides[p].dim.x = dims[p].img.bpp; + if (mtype == ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED) + { + strides[p].dim.y = strides[p].dim.x*dims[p].img.width; + strides[p].dim.z = strides[p].dim.y*dims[p].img.height; + } + else + { + strides[p].dim.y = blocks[p].stride; + strides[p].dim.z = blocks[p].stride*dims[p].img.height; + } + if (p == 0) + ptrs[p] = blocks[p].ptr; + else + ptrs[p] = &((uint8_t *)ptrs[p-1])[strides[p].dim.z]; + } + } + else + { + SOSAL_PRINT(SOSAL_ZONE_MEM, "%s: Failed to allocate from TILER!\n", __FUNCTION__); + ret = false_e; + } + free(blocks); + } + break; + } +#elif defined(SOSAL_USE_ION) + case ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED: + flags = (1<< OMAP_ION_HEAP_SECURE_INPUT); // overload the secure input space + // fall-through + case ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED: + { + int32_t status = 0; + size_t rsize = 0; + for (p = 0; p < nptrs; p++) + { + int fmt = 0; + size_t stride = 0; + switch (dims[p].img.bpp) + { + case 1: + fmt = TILER_PIXEL_FMT_8BIT; + break; + case 2: + fmt = TILER_PIXEL_FMT_16BIT; + break; + case 3: + case 4: + fmt = TILER_PIXEL_FMT_32BIT; + break; + default: + fmt = TILER_PIXEL_FMT_PAGE; + break; + } + size = 1; // reset to a good value + for (n = 0; n < ndims; n++) { + size *= dims[p].dims[n]; + strides[p].dims[n] = size; // initialize to this, but use value from alloc later if 2D + } + rsize = allocator_page_align_size(size); + SOSAL_PRINT(SOSAL_ZONE_MEM, "%s: Allocating ION Buffer FMT:%d DIM:%ux%u FLAGS=%08x SIZE=%zu RSIZE=%zu (div=%lu rem=%lu)\n", + __FUNCTION__, + fmt, + dims[p].img.width, + dims[p].img.height, + flags, + size, rsize, + rsize/SOSAL_PAGE_SIZE, rsize%SOSAL_PAGE_SIZE); + if (mtype == ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED) { +#if defined(SOSAL_USE_ION_TILER) + status = ion_alloc_tiler(alloc->device, dims[p].img.width, dims[p].img.height, fmt, flags, (struct ion_handle **)&hdls[p], &stride); +#else + // when we don't have 2D memory from TILER, simulate it. + stride = dims[p].img.width * dims[p].img.bpp; + status = ion_alloc(alloc->device, rsize, SOSAL_ALLOCATOR_ALIGN, flags, (struct ion_handle **)&hdls[p]); +#endif + strides[p].dim.y = (int32_t)stride; + strides[p].dim.z = strides[p].dim.y*dims[p].img.height; + } else + status = ion_alloc(alloc->device, rsize, SOSAL_ALLOCATOR_ALIGN, flags, (struct ion_handle **)&hdls[p]); + if (status < 0 || hdls[p] == 0) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "%s: ION Allocation failed, status=%d, errno=%d hdl:"FMT_VALUE_T"\n", __FUNCTION__, status, errno, hdls[p]); + ret = false_e; + } else { + ion_fd_hdl_t *fd_hdl = calloc(1, sizeof(ion_fd_hdl_t)); + if (fd_hdl) + { + SOSAL_PRINT(SOSAL_ZONE_MEM, "%s: Allocated ION Buffer HDL:"FMT_VALUE_T"\n", __FUNCTION__, hdls[p]); +#if defined(SOSAL_USE_ION_CACHING) + if (mtype == ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED) // 1D cached + status = ion_map_cacheable(alloc->device, (struct ion_handle*)hdls[p], rsize, PROT_READ|PROT_WRITE, MAP_SHARED, 0, (uint8_t **)&ptrs[p], &fd_hdl->fd); + else // 1D, 2D uncached +#endif + { + if (mtype == ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED) + rsize = dims[p].img.height * strides[p].dim.y; + status = ion_map(alloc->device, (struct ion_handle *)hdls[p], rsize, PROT_READ|PROT_WRITE, MAP_SHARED, 0, (uint8_t **)&ptrs[p], &fd_hdl->fd); + } + if (status < 0) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "%s: ION Mapping Failed, status=%d, errno=%d\n", __FUNCTION__, status, errno); + ret = false_e; + } else { + node_t *node = node_create((value_t)fd_hdl); + if (node) + { + fd_hdl->handle = (struct ion_handle *)hdls[p]; + list_append(&alloc->fd_list, node); + } + else + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to remember fd to hdl relation. LEAK!\n"); + } + /** \note Memset'ing the ION buffer can be a VERY SLOW OPERATION! */ + if (mtype == ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED) { + int32_t y; + uint8_t *tmp = (uint8_t *)ptrs[p]; + for (y = 0; y < dims[p].img.height; y++) + memset(&tmp[y * strides[p].dim.y], 0, strides[p].dim.x*dims[p].img.width); + } else + memset(ptrs[p], 0, rsize); + } + } + else + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR: Failed to create association structure!\n"); + ret = false_e; + } + } + } + break; + } +#endif +#if defined(SOSAL_USE_GRALLOC) + case ALLOCATOR_MEMORY_TYPE_GFX_2D_UNCACHED: + { + int32_t status = 0; + if (hdls == NULL || alloc->module == NULL || alloc->allocator == NULL) + return false_e; + + if (nptrs != 2 || ndims != 3 || dims[0].dim.x != 1 || dims[1].dim.x != 2) // must be allocating NV12 only + return false_e; + + int width = dims[0].img.width; + int height = dims[0].img.height; + int format = 0x100; + int usage = GRALLOC_USAGE_HW_RENDER | + GRALLOC_USAGE_HW_TEXTURE | + GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_SW_WRITE_NEVER; + + memset(strides, 0, nptrs*sizeof(allocator_dimensions_t)); + strides[0].dim.x = dims[0].dim.x; + strides[1].dim.x = dims[0].dim.x; + + SOSAL_PRINT(SOSAL_ZONE_MEM, "%s: Allocating GRALLOC FMT:%x DIM:%ux%u USAGE:%x\n", __FUNCTION__, format, width, height, usage); + + status = alloc->allocator->alloc((struct alloc_device_t *)alloc->allocator, width, height, format, usage, (buffer_handle_t *)&hdls[0], (int *)&strides[0].dim.y); + if (status == 0) + { + // remember the stride for both planes + strides[1].dim.y = strides[0].dim.y; + + // calculate the plane size and store in dim.z + strides[0].dim.z = strides[0].dim.y*dims[0].img.height; + strides[1].dim.z = strides[1].dim.y*dims[1].img.height; + + // fill in the pointers + status = alloc->module->base.lock((const struct gralloc_module_t *)alloc->module, (buffer_handle_t)hdls[0], usage, 0, 0, width, height, ptrs); + if (status != 0) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "%s: Failed to lock GRALLOC buffer (status=%d errno=%d)\n", __FUNCTION__, status, errno); + ret = false_e; + } + } + else + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "%s: Failed to alloc GRALLOC buffer (status=%d errno=%d)\n", __FUNCTION__, status, errno); + ret = false_e; + } + break; + } +#endif +#if defined(SOSAL_USE_BO) + case ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED: + case ALLOCATOR_MEMORY_TYPE_GFX_2D_UNCACHED: + { + flags |= OMAP_BO_SCANOUT; // all memory must be phys contig for SIMCOP to be able to access + if (mtype == ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED) + flags |= (OMAP_BO_CACHED); + else + flags |= (OMAP_BO_WC); // make uncached memory have a better write speed. + for (p = 0; p < nptrs; p++) + { + size_t size = 1; + alloc_omap_bo_t *bot = (alloc_omap_bo_t *)calloc(1, sizeof(alloc_omap_bo_t)); + if (bot == NULL) + break; + + if (mtype == ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED || + mtype == ALLOCATOR_MEMORY_TYPE_GFX_2D_UNCACHED) + { + strides[p].dims[0] = dims[p].img.bpp; + switch (dims[p].img.bpp) + { + case 1: + flags |= OMAP_BO_TILED_8; + break; + case 2: + flags |= OMAP_BO_TILED_16; + break; + case 3: // put 24 bit values in 32 bit plane for easy rotation + strides[p].dims[0] = 4; + // fallthrough + case 4: + flags |= OMAP_BO_TILED_32; + break; + default: + break; + } + bot->bo = omap_bo_new_tiled(alloc->drm_dev, dims[p].img.width, dims[p].img.height, flags); + } + else + { + for (n = 0; n < ndims; n++) + size *= dims[p].dims[n]; + strides[p].dims[0] = dims[p].img.bpp; + bot->bo = omap_bo_new(alloc->drm_dev, size, flags); + } + if (bot->bo) + { + ptrs[p] = omap_bo_map((struct omap_bo *)bot->bo); + if (ptrs[p]) + { + strides[p].dims[1] = dims[p].img.width * dims[p].img.bpp; + if (mtype == ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED || + mtype == ALLOCATOR_MEMORY_TYPE_GFX_2D_UNCACHED) + { + #define ALIGN2(x,n) (((x) + ((1 << (n)) - 1)) & ~((1 << (n)) - 1)) + strides[p].dims[1] = ALIGN2(strides[p].dims[1],PAGE_SHIFT); + } + strides[p].dims[2] = strides[p].dims[1] * dims[p].img.height; + hdls[p] = (value_t)bot; // the returned handle is an (alloc_omap_bo_t *) + bot->dmabuf_fd = omap_bo_dmabuf((struct omap_bo *)bot->bo); + SOSAL_PRINT(SOSAL_ZONE_MEM, "%s: Allocated BO %p MAP %p STRIDE:%u FD:%d\n", __FUNCTION__, bot->bo, ptrs[p], strides[p].dims[1], bot->dmabuf_fd); + ret = true_e; + } + else + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to map OMAP buffer object %p to our space!\n", bot->bo); + omap_bo_del((struct omap_bo *)bot->bo); + ret = false_e; + break; + } + } + else + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to allocate buffer object!\n"); + ret = false_e; + break; + } + } + break; + } +#endif +#if defined(SOSAL_USE_TILER) + case ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED: +#endif + case ALLOCATOR_MEMORY_TYPE_VIRTUAL: + { + uint32_t rsize = 0; + for (p = 0; p < nptrs; p++) { + size = 1; // reset to good value + for (n = 0; n < ndims; n++) { + size *= dims[p].dims[n]; + strides[p].dims[n] = size; + } + // if we're running on an OMAP, the SIMCOP needs page aligned data. + rsize = allocator_page_align_size(size); +#if defined(ANDROID) + ptrs[p] = memalign(SOSAL_PAGE_SIZE, rsize); + if (ptrs[p]) memset(ptrs[p], 0, rsize); +#elif defined(__QNX__) || defined(LINUX) + int32_t err = posix_memalign(&ptrs[p], SOSAL_PAGE_SIZE, rsize); + if (err == ENOMEM) { + ret = false_e; + ptrs[p] = NULL; + return ret; + } else if (err == EINVAL) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "%s: memalign failed due to alignment request!\n", __FUNCTION__); + ret = false_e; + ptrs[p] = NULL; + return ret; + } + if (ptrs[p]) + memset(ptrs[p], 0, size); +#else + ptrs[p] = (ptr_t)calloc(1, size); +#endif + if (ptrs[p] == NULL) { + ret = false_e; + for (p = p-1; p > -1; p--) { + free(ptrs[p]); + ptrs[p] = NULL; + } + break; // exit + } + } + break; + } +#if defined(SOSAL_USE_SHARED_T) + case ALLOCATOR_MEMORY_TYPE_VIRTUAL_SHARED: + { + for (p = 0; p < nptrs; p++) + { + shared_t *shm = NULL; + unique_t un = allocator_rand(); + size = 1; + for (n = 0; n < ndims; n++) + { + size *= dims[p].dims[n]; + strides[p].dims[n] = size; + } + shm = shared_alloc(un, size); + if (shm) + { + SOSAL_PRINT(SOSAL_ZONE_MEM, "SHM: UN:0x%08x SIZE:"FMT_SIZE_T"\n", shm->un, shm->size); + hdls[p] = (value_t)shm; + ptrs[p] = shm->data; + } + else + { + ret = false_e; + break; + } + } + break; + } +#endif + default: + ret = false_e; + break; + } +#if defined(SOSAL_DEBUG) + if (ret == true_e) { + for (p = 0; p < nptrs; p++) { + SOSAL_PRINT(SOSAL_ZONE_MEM, "%s: Callocated type %d [%u] ptr:%p hdl:"FMT_VALUE_T" dim:{%d,%d,%d} strides:{%d,%d,%d}\n", __FUNCTION__, mtype, p, ptrs[p], hdls[p], dims[p].dim.x,dims[p].dim.y,dims[p].dim.z,strides[p].dim.x,strides[p].dim.y,strides[p].dim.z); + } + } +#endif + if (ret == false_e) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "%s: Failed to allocate memory type %u!\n", __FUNCTION__, mtype); + } + return ret; +} + +bool_e allocator_share(allocator_t *alloc, + allocator_memory_type_e memtype, + int32_t nptrs, + value_t *hdls, + int32_t *fds) +{ + int32_t p = 0; + bool_e ret = false_e; + if (alloc == NULL || memtype > ALLOCATOR_MEMORY_TYPE_MAX || nptrs <= 0 || hdls == NULL || fds == NULL) + return false_e; + + switch (memtype) + { +#if defined(SOSAL_USE_ION) + case ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED: + { + int err = 0; + for (p = 0; p < nptrs; p++) + { + err = ion_share(alloc->device, (struct ion_handle *)hdls[p], &fds[p]); + SOSAL_PRINT(SOSAL_ZONE_MEM, "ION_SHARE returned %d, errno=%d, share_fd=%d\n", err, errno, fds[p]); + } + ret = (err == 0) ? true_e : false_e; + break; + } +#endif +#if defined(DVP_USE_BO) + case ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_2D_CACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED: + case ALLOCATOR_MEMORY_TYPE_GFX_2D_UNCACHED: + for (p = 0; p < nptrs; p++) + { + alloc_omap_bo_t *bot = (alloc_omap_bo_t *)hdls[p]; + fds[p] = dup(bot->dmabuf_fd); // pass a duplicate to remote processes. + } + ret = true_e; + break; +#endif +#if defined(SOSAL_USE_SHARED_T) + case ALLOCATOR_MEMORY_TYPE_VIRTUAL_SHARED: + for (p = 0; p < nptrs; p++) + { + shared_t *shm = (shared_t *)hdls[p]; + fds[p] = (int32_t)shm->un; + } + ret = true_e; + break; +#endif + default: + break; + } + return ret; +} + +bool_e allocator_import(allocator_t *alloc, + allocator_memory_type_e memtype, + int32_t nptrs, + int32_t ndims, + allocator_dimensions_t *dims, + ptr_t *ptrs, + value_t *hdls, + allocator_dimensions_t *strides, + int32_t *fds) +{ + int32_t n = 0, p = 0; + uint32_t size = 0; + bool_e ret = false_e; + if (alloc == NULL || memtype > ALLOCATOR_MEMORY_TYPE_MAX || nptrs <= 0 || ndims <= 0 || dims == NULL || ptrs == NULL || hdls == NULL || fds == NULL) + return false_e; + + switch (memtype) + { +#if defined(SOSAL_USE_ION) + case ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED: + { + int err = 0; + for (p = 0; p < nptrs; p++) + { + size_t rsize = 0; + ion_fd_hdl_t *fd_hdl = calloc(1, sizeof(ion_fd_hdl_t)); + if (fd_hdl) + { + err = ion_import(alloc->device, fds[p], (struct ion_handle **)&hdls[p]); + SOSAL_PRINT(SOSAL_ZONE_MEM, "ION_IMPORT returned %d, errno=%d, share_fd=%d\n", ret, errno, fds[p]); + + size = 1; // reset to a good value + for (n = 0; n < ndims; n++) { + size *= dims[p].dims[n]; + strides[p].dims[n] = size; // initialize to this, but use value from alloc later if 2D + } + rsize = allocator_page_align_size(size); +#if defined(SOSAL_USE_ION_CACHING) + if (memtype == ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED) + err = ion_map_cacheable(alloc->device, (struct ion_handle *)hdls[p], rsize, PROT_READ|PROT_WRITE, MAP_SHARED, 0, (uint8_t **)&ptrs[p], &fd_hdl->fd); + else +#endif + err = ion_map(alloc->device, (struct ion_handle *)hdls[p], rsize, PROT_READ|PROT_WRITE, MAP_SHARED, 0, (uint8_t **)&ptrs[p], &fd_hdl->fd); + SOSAL_PRINT(SOSAL_ZONE_MEM, "ION MAP returned %d errno=%d\n", ret, errno); + if (err < 0) + { + SOSAL_PRINT(SOSAL_ZONE_MEM, "ION SHARING Failed! (err=%d errno=%d)\n", err, errno); + ret = false_e; + break; + } + else + { + fd_hdl->handle = (struct ion_handle *)hdls[p]; + node_t *node = node_create((value_t)fd_hdl); + if (node) + list_append(&alloc->fd_list, node); + else + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR: Failed to remember file descriptor. LEAK!\n"); + ret = false_e; + break; + } + } + } + else + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ION Failed to allocate assocation structure.\n"); + ret = false_e; + break; + } + } + if (err == 0) + ret = true_e; + break; + } +#endif +#if defined(DVP_USE_BO) + case ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_2D_CACHED: + case ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED: + case ALLOCATOR_MEMORY_TYPE_GFX_2D_UNCACHED: + for (p = 0; p < nptrs; p++) + { + // not supported... + } + break; +#endif +#if defined(SOSAL_USE_SHARED_T) + case ALLOCATOR_MEMORY_TYPE_VIRTUAL_SHARED: + for (p = 0; p < nptrs; p++) + { + shared_t * shm = NULL; + size = 1; + for (n = 0; n < ndims; n++) + { + size *= dims[p].dims[n]; + strides[p].dims[n] = size; + } + shm = shared_alloc((unique_t)fds[p], size); + if (shm) + { + SOSAL_PRINT(SOSAL_ZONE_MEM, "SHM: UN:0x%08x SIZE:"FMT_SIZE_T"\n", shm->un, shm->size); + hdls[p] = (value_t)shm; + ptrs[p] = shm->data; + } + else + { + ret = false_e; + break; + } + } + ret = true_e; + break; +#endif + default: + break; + } + return ret; +} + +bool_e allocator_memory_calloc(allocator_t *alloc, allocator_memory_t *memory) +{ + if (alloc && memory && memory->allocated == false_e) + { + bool_e ret = allocator_calloc(alloc, + memory->memtype, + memory->nptrs, + memory->ndims, + memory->dims, + memory->ptrs, + memory->hdls, + memory->strides); + memory->allocated = ret; + return ret; + } + return false_e; +} + +bool_e allocator_memory_free(allocator_t *alloc, allocator_memory_t *memory) +{ + if (alloc && memory && memory->allocated == true_e) + { + if (allocator_free(alloc, + memory->memtype, + memory->nptrs, + memory->ptrs, + memory->hdls) == true_e) + { + int32_t f = 0; + memory->allocated = false_e; +#if defined(SOSAL_USE_ION) || defined(SOSAL_USE_BO) || defined(SOSAL_USE_TILER) + for (f = 0; f < memory->nptrs; f++) { + if (memory->memtype == ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED || + memory->memtype == ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED) + { + close(memory->fds[f]); + } + } +#endif + return true_e; + } + } + return false_e; +} + +bool_e allocator_memory_share(allocator_t *alloc, allocator_memory_t *memory) +{ + if (alloc && memory && memory->allocated) + { + return allocator_share(alloc, + memory->memtype, + memory->nptrs, + memory->hdls, + memory->fds); + } + return false_e; +} + +bool_e allocator_memory_import(allocator_t *alloc, allocator_memory_t *memory) +{ + if (alloc && memory && memory->allocated == false_e) + { + memory->allocated = allocator_import(alloc, + memory->memtype, + memory->nptrs, + memory->ndims, + memory->dims, + memory->ptrs, + memory->hdls, + memory->strides, + memory->fds); + return memory->allocated; + } + return false_e; +} + +#include +#include + +bool_e allocator_unittest(int argc, char *argv[]) +{ + uint32_t width = 320; + uint32_t height = 240; + uint32_t numImages = 4; + int32_t errors = 0; + fph_t *handle_hash = fph_init(64,64,NULL); + if (argc > 3) + { + width = atoi(argv[1]); + height = atoi(argv[2]); + numImages = atoi(argv[3]); + } + + if (numImages > 0 && width > 0 && height > 0) + { + uint32_t i, t, p; + allocator_memory_type_e types[] = { + ALLOCATOR_MEMORY_TYPE_VIRTUAL, + ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED, + ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED, + ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED, + ALLOCATOR_MEMORY_TYPE_GFX_2D_UNCACHED, + ALLOCATOR_MEMORY_TYPE_VIRTUAL_SHARED, + }; + image_t **images = (image_t **)calloc(numImages, sizeof(image_t *)); + // these are NV12 dimenions + allocator_dimensions_t dims[2] = {{{{1, width,height}}}, + {{{2, width/2,height/2}}}}; + ptr_t ptrs[2] = {NULL, NULL}; + value_t hdls[2] = {0,0}; + allocator_dimensions_t strides[2] = {{{{0,0,0}}}, + {{{0,0,0}}}}; + allocator_t *alloc = allocator_init(); + uint32_t nptrs = dimof(ptrs); + + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Width=%d Height=%d Num=%d\n", width, height, numImages); + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Alloc=%p Images=%p, Errors=%d\n", alloc, images, errors); + + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "SOSAL_ZONE_MASK=%x\n", SOSAL_ZONE_MASK); + + if (images == NULL) + errors++; + if (alloc == NULL) + errors++; + if (errors > 0) return errors; + + for (t = 0; t < dimof(types); t++) + { + nptrs = dimof(ptrs); // reset value; + +#if !defined(SOSAL_USE_TILER) && !defined(SOSAL_USE_ION) && !defined(SOSAL_USE_BO) + if (types[t] == ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED || + types[t] == ALLOCATOR_MEMORY_TYPE_TILED_2D_UNCACHED) + break; +#endif +#if !defined(SOSAL_USE_GRALLOC) && !defined(SOSAL_USE_BO) + if (types[t] == ALLOCATOR_MEMORY_TYPE_GFX_2D_UNCACHED) + break; +#endif + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "IMAGE ALLOC\n"); + for (i = 0; i < numImages; i++) { + + images[i] = image_allocate(width,height,FOURCC_NV12); + if (images[i] == NULL) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to allocate image %d\n", i); + errors++; + } + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "PTR CALLOC\n"); + if (allocator_calloc(alloc, types[t], nptrs, 3, dims, ptrs, hdls, strides) == false_e) + errors++; + else + { + for (p = 0; p < nptrs; p++) + { + fph_set(handle_hash, ptrs[p], (ptr_t)hdls[p]); + images[i]->plane[p].ptr = ptrs[p]; + images[i]->plane[p].xstride = strides[p].dim.x; + images[i]->plane[p].ystride = strides[p].dim.y; + images[i]->plane[p].numBytes = strides[p].dim.z; + } + } + + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "IMAGE PRINT\n"); + image_print(images[i]); + + } + + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "IMAGE FREE\n"); + for (i = 0; i < numImages; i++) { + + for (p = 0; p < nptrs; p++) + { + ptrs[p] = (ptr_t)images[i]->plane[p].ptr; + fph_get(handle_hash, ptrs[p], (void **)&hdls[p]); + } + +#if defined(SOSAL_USE_TILER) + nptrs = 1; // tiler buffers only need to free first pointer in set +#endif + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "PTR FREE\n"); + if (allocator_free(alloc, types[t], nptrs, ptrs, hdls) == false_e) + errors++; + + image_free(&images[i]); + } + } + + allocator_deinit(&alloc); + } + fph_deinit(handle_hash); + if (errors == 0) + return true_e; + else + { + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "There were %d errors in allocator unittest!\n", errors); + return false_e; + } +} + diff --git a/source/sosal/allocator_binder.cpp b/source/sosal/allocator_binder.cpp new file mode 100644 index 0000000..676348a --- /dev/null +++ b/source/sosal/allocator_binder.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace SOSAL { + +void WriteMemoryToParcel(Parcel &parcel, allocator_memory_t *memory) +{ + int32_t p, n; + parcel.writeInt32(memory->memtype); + parcel.writeInt32(memory->nptrs); + parcel.writeInt32(memory->ndims); + for (p = 0; p < memory->nptrs; p++) { + for(n = 0; n < memory->ndims; n++) { + parcel.writeInt32(memory->dims[p].dims[n]); + } + } + for (p = 0; p < memory->nptrs; p++) { + for(n = 0; n < memory->ndims; n++) { + parcel.writeInt32(memory->strides[p].dims[n]); + } + } + for (p = 0; p < memory->nptrs; p++) { + if (memory->memtype == ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED || + memory->memtype == ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED) + parcel.writeFileDescriptor(memory->fds[p]); + else if (memory->memtype == ALLOCATOR_MEMORY_TYPE_VIRTUAL_SHARED) + parcel.writeInt32(memory->fds[p]); + } +} + +void ReadMemoryFromParcel(const Parcel &parcel, allocator_memory_t *memory) +{ + int32_t p, n; + memory->memtype = (allocator_memory_type_e)parcel.readInt32(); + memory->nptrs = parcel.readInt32(); + memory->ndims = parcel.readInt32(); + for (p = 0; p < memory->nptrs; p++) { + for(n = 0; n < memory->ndims; n++) { + memory->dims[p].dims[n] = parcel.readInt32(); + } + } + for (p = 0; p < memory->nptrs; p++) { + for(n = 0; n < memory->ndims; n++) { + memory->strides[p].dims[n] = parcel.readInt32(); + } + } + for (p = 0; p < memory->nptrs; p++) { + if (memory->memtype == ALLOCATOR_MEMORY_TYPE_TILED_1D_CACHED || + memory->memtype == ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED) + memory->fds[p] = parcel.readFileDescriptor(); + else if (memory->memtype == ALLOCATOR_MEMORY_TYPE_VIRTUAL_SHARED) + memory->fds[p] = parcel.readInt32(); + } +} + +}; + diff --git a/source/sosal/bitfield.c b/source/sosal/bitfield.c new file mode 100644 index 0000000..64dd94b --- /dev/null +++ b/source/sosal/bitfield.c @@ -0,0 +1,128 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#define BIT_TST(field, bit) (((field) >> bit) & 1) +#define BIT_CLR(field, bit) ((field) &= ~(1<max/32); + len += (b->max % 32 == 0?0:1); + return len * 4; +} + +void bitfield_deinit(bitfield_t *b) +{ + if (b) + { + if (b->fields) + { + memset(b->fields, 0, bitfield_length(b)); + free(b->fields); + b->fields = NULL; + } + b->max = 0; + b->count = 0; + } +} + +void bitfield_init(bitfield_t *b, uint32_t max) +{ + if (b) + { + b->count = 0; + b->max = max; + if (b->fields) + { + memset(b->fields, 0, bitfield_length(b)); + } + else + { + b->fields = (uint32_t *)calloc(1, bitfield_length(b)); + } + //printf("Allocated a bitfield of %u bits (%u byte length)\n", max, bitfield_length(b)); + } +} + +bool_e bitfield_rls(bitfield_t *b, uint32_t bit) +{ + if (b && b->fields) + { + uint32_t c = 0; // calculated bit + uint32_t d = 0; // intrafield bit + uint32_t i = 0; // index + uint32_t l = bitfield_length(b) / 4; + for (i = 0; i < l; i++) + { + for (d = 0; d < 32; d++) + { + c = d + (i * 32); + if (c == bit && BIT_TST(b->fields[i], d)) + { + BIT_CLR(b->fields[i], d); + return true_e; + } + } + } + } + return false_e; +} + +bool_e bitfield_get(bitfield_t *b, uint32_t *bit) +{ + *bit = 0xFFFFFFFF; + if (b && b->fields) + { + uint32_t c = 0; // calculated bit + uint32_t d = 0; // intrafield bit + uint32_t i = 0; // index + uint32_t l = bitfield_length(b) / 4; + for (i = 0; i < l; i++) + { + for (d = 0; d < 32; d++) + { + // the calculated bit + c = d + (i * 32); + + // if the bit is higher than is allowed, fail + if (c >= b->max) + return false_e; + + if (!BIT_TST(b->fields[i], d)) + { + BIT_SET(b->fields[i], d); + *bit = c; + return true_e; + } + } + } + } + return false_e; +} + +uint32_t bitfield_count(bitfield_t *b) +{ + if (b) + return b->max; + else + return 0; +} + + diff --git a/source/sosal/btreelist.c b/source/sosal/btreelist.c new file mode 100644 index 0000000..63eb7ac --- /dev/null +++ b/source/sosal/btreelist.c @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +static btreelistnode_t *btreelist_rebtree(btreelist_t *btl, int32_t center, int32_t count) +{ + btreelistnode_t *node = NULL; + + if (count == btl->count) + { + if (btl->array) free(btl->array); + btl->array = (btreelistnode_t **)calloc(count, sizeof(btreelistnode_t *)); + SOSAL_PRINT(SOSAL_ZONE_BTREE, "Re-allocaing array to %p for %u pointers\n", btl->array, btl->count); + if (btl->array) + { + btreelistnode_t *node = btl->head; + int32_t i = 0; + SOSAL_PRINT(SOSAL_ZONE_BTREE, "Root=%p\n",btl->root); + SOSAL_PRINT(SOSAL_ZONE_BTREE, "Head=%p\n",btl->head); + while (node) { + SOSAL_PRINT(SOSAL_ZONE_BTREE, "[%u] = %p (%s) prev=%p next=%p left=%p right=%p\n", i, node, btl->print(node), node->prev, node->next, node->left, node->right); + btl->array[i++] = node; + node = node->next; + } + SOSAL_PRINT(SOSAL_ZONE_BTREE, "Tail=%p\n",btl->tail); + } + } + + if (center < 0) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Center should never be negative! (%d)\n", center); + return NULL; + } + + if (count > 0) + { + SOSAL_PRINT(SOSAL_ZONE_BTREE, "Re-BTREE from center %d for %u nodes\n", center, count); + node = btl->array[center]; + switch(count) + { + case 0: + break; // just to be safe + case 1: + node->left = NULL; + node->right = NULL; + break; + case 2: + node->left = btreelist_rebtree(btl, center-1, 1); + node->right = NULL; + break; + case 3: + node->left = btreelist_rebtree(btl, center-1, 1); + node->right = btreelist_rebtree(btl, center+1, 1); + break; + case 4: + node->left = btreelist_rebtree(btl, center-1, 2); + node->right = btreelist_rebtree(btl, center+1, 1); + break; + default: + { + uint32_t ll, lc; // left length and count + uint32_t rl, rc; // right length and count + if (count & 1) // odd, both sides are balanced + { + ll = rl = count/2; + } + else // left side will be odd, right side will be even + { + ll = count/2; + rl = ll-1; + } + lc = center - ll/2; + if (ll & 1) + lc -= 1; + rc = center + rl/2 + 1; // ever or odd + node->left = btreelist_rebtree(btl, lc, ll); + node->right = btreelist_rebtree(btl, rc, rl); + break; + } + } + } + return node; +} + +static void btreelist_insert(btreelist_t *btl, btreelistnode_t *node, btreelistnode_t *obj) +{ + int ret = 0; + + if (btl->root == NULL && btl->head == NULL && btl->tail == NULL) // very first insert + { + btl->root = obj; + btl->head = obj; + btl->tail = obj; + btl->count = 1; + memset(obj, 0, sizeof(btreelistnode_t)); + SOSAL_PRINT(SOSAL_ZONE_BTREE, "Creating first item %p in BTREELIST!\n", obj); + return; + } + + if (node == NULL) + return; + + ret = btl->sort(node, obj); + + SOSAL_PRINT(SOSAL_ZONE_BTREE, "Inserting %p into btreelist, node=%p, ret=%d\n", obj, node, ret); + + if (ret == 0) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR: Insert does not overwrite matching nodes!\n"); + return; // we already have one + } + else if (ret == 1) + { + if (node->right) + btreelist_insert(btl, node->right, obj); + else + { + SOSAL_PRINT(SOSAL_ZONE_BTREE, "Inserting %p as next to %p\n", obj, node); + obj->next = node->next; + if (node->next == NULL) + btl->tail = obj; + else + node->next->prev = obj; + node->next = obj; + obj->prev = node; + btl->count++; + } + } + else if (ret == -1) + { + if (node->left) + btreelist_insert(btl, node->left, obj); + else + { + SOSAL_PRINT(SOSAL_ZONE_BTREE, "Inserting %p as prev to %p\n", obj, node); + obj->prev = node->prev; + if (node->prev == NULL) + btl->head = obj; + else + node->prev->next = obj; + node->prev = obj; + obj->next = node; + btl->count++; + } + } +} + +void btreelist_add(btreelist_t *btl, btreelistnode_t *btln) +{ + btreelist_insert(btl, btl->root, btln); + btl->root = btreelist_rebtree(btl, btl->count/2, btl->count); +} + +static btreelistnode_t *btree_find(btreelist_t *btl, btreelistnode_t *btln, value_t value) +{ + int ret = 0; + + if (btln == NULL) + return NULL; + + ret = btl->compare(btln, value); + if (ret == 0) + return btln; + else if (ret == 1) + return btree_find(btl, btln->right, value); + else //if (ret == -1) + return btree_find(btl, btln->left, value); +} + +btreelistnode_t *btreelist_find(btreelist_t *btl, value_t value) +{ + btreelistnode_t *node = NULL; + if (btl && btl->compare) + { + node = btree_find(btl, btl->root, value); + if (node) + { + SOSAL_PRINT(SOSAL_ZONE_BTREE, "Found node %p, value %s\n", node, btl->print(node)); + } + } + return node; +} + +btreelistnode_t *btreelist_remove(btreelist_t *btl, value_t value) +{ + // Find the item then rebtree + btreelistnode_t *node = NULL; + if (btl) + { + node = btreelist_find(btl, value); + if (node) + { + // remove this item from the list + if (node->prev == NULL) //head + btl->head = node->next; + else + node->prev->next = node->next; + if (node->next == NULL) //tail + btl->tail = node->prev; + else + node->next->prev = node->prev; + btl->count--; + memset(node, 0, sizeof(btreelistnode_t)); + btl->root = btreelist_rebtree(btl, btl->count/2, btl->count); + } + } + return node; +} + +void btreelist_destroy(btreelist_t *btl) +{ + btreelistnode_t *node = btl->head; + btreelistnode_t *next = NULL; + while (node) + { + next = node->next; + SOSAL_PRINT(SOSAL_ZONE_BTREE, "Freeing node %p (next=%p) (%s)\n", node, next, btl->print(node)); + memset(node, 0, sizeof(btreelistnode_t)); + free(node); + node = next; + } + memset(btl, 0, sizeof(btreelist_t)); + free(btl); +} + +btreelist_t *btreelist_create(btreelistnode_compare compfunc, btreelistnode_sort sortfunc, btreelistnode_print printfunc) +{ + btreelist_t *btl = (btreelist_t *)calloc(1, sizeof(btreelist_t)); + if (btl) + { + btl->compare = compfunc; + btl->sort = sortfunc; + btl->print = printfunc; + } + return btl; +} + +typedef struct _testvalue_t { + btreelistnode_t node; + value_t value; +} testvalue_t; + +static int value_compare(btreelistnode_t *node, value_t value) +{ + testvalue_t *v = (testvalue_t *)node; + if (v->value == value) + return 0; + else if (v->value < value) + return 1; + else //if (v->value > value) + return -1; +} + +static int value_sort(btreelistnode_t *node, btreelistnode_t *obj) +{ + testvalue_t *a = (testvalue_t *)node; + testvalue_t *b = (testvalue_t *)obj; + if (a->value == b->value) + return 0; + else if (a->value > b->value) + return -1; + else //if (a->value < b->value) + return 1; +} + +static char *value_print(btreelistnode_t *node) +{ + static char values[60]; + testvalue_t *a = (testvalue_t *)node; + sprintf(values, ""FMT_VALUE_T"", a->value); + return values; +} + +int btreelist_unittest(int argc __attribute__((unused)), + char *argv[] __attribute__((unused))) +{ + btreelist_t *btl = btreelist_create(value_compare, value_sort, value_print); + if (btl) + { + uint32_t i,c = 128; + testvalue_t *vs = (testvalue_t *)calloc(c, sizeof(testvalue_t)); + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Adding All Nodes!\n"); + for (i = 0; i < c; i++) + { + vs[i].value = (value_t)rand(); + btreelist_add(btl, (btreelistnode_t *)&vs[i]); + } + + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Removing All Nodes!\n"); + for (i = 0; i < c; i++) + { + btreelist_remove(btl, vs[i].value); + } + btreelist_destroy(btl); + btl = NULL; + } + return 0; +} + diff --git a/source/sosal/cache.c b/source/sosal/cache.c new file mode 100644 index 0000000..bf00a4e --- /dev/null +++ b/source/sosal/cache.c @@ -0,0 +1,411 @@ +/** + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include // just for unittest +#include + +void cache_destroy(cache_t *cache) +{ + size_t i = 0; + for (i = 0; i < cache->numLines; i++) + { + if (cache->line[i].data != NULL) + { + if (cache->line[i].data) + free(cache->line[i].data); + cache->line[i].data = NULL; + } + } + free(cache->line); + mutex_deinit(&cache->mutex); + memset(cache, 0, sizeof(cache_t)); + free(cache); +} + +cache_t *cache_create(size_t lineSize, + size_t numLines, + cache_policy_e policy, + cache_fill_f fill, + cache_commit_f commit, + void *cookie) +{ + cache_t *cache = (cache_t *)calloc(1, sizeof(cache_t)); + if (cache) + { + size_t i = 0; + cache->numLines = numLines; + cache->lineSize = lineSize; + cache->cookie = cookie; + cache->fillLine = fill; + cache->commitLine = commit; + cache->policy = policy; + mutex_init(&cache->mutex); + cache->line = calloc(cache->numLines, sizeof(cache_line_t)); + if (cache->line) + { + for (i = 0; i < cache->numLines; i++) + { + cache->line[i].data = calloc(cache->lineSize, 1); + if (cache->line[i].data == NULL) + { + cache_destroy(cache); + cache = NULL; + break; + } + } + } + else + { + cache_destroy(cache); + cache = NULL; + } + } + return cache; +} + +bool_e cache_index(cache_t *cache, size_t offset, size_t *index) +{ + size_t i; + for (i = 0; i < cache->numLines; i++) + { + if (cache->line[i].valid == true_e && cache->line[i].start_offset <= offset && offset < cache->line[i].end_offset) + { + *index = i; + return true_e; + } + } + return false_e; +} + +static size_t cache_round_offset(cache_t *c, size_t offset) +{ + return (offset / c->lineSize) * c->lineSize; +} + +static size_t cache_next(cache_t *cache) +{ + size_t i = 0; + bool_e found = false_e; + size_t free_index = 0; + size_t oldest_index = 0; + clock_t oldest_clock = clock(); + // find the an empty cache line + for (i = 0; i < cache->numLines; i++) + { + if (cache->line[i].valid == false_e) { + free_index = i; + found = true_e; + } else { + if (cache->line[i].locked == false_e && cache->line[i].age < oldest_clock) { + oldest_clock = cache->line[i].age; + oldest_index = i; + } + } + } + if (found) + return free_index; + else { + // age out the oldest! + if (cache->policy == CACHE_POLICY_WRITE_BACK) + cache->commitLine(cache->cookie, cache->line[i].data, cache->lineSize, cache->line[i].start_offset); + cache->line[i].valid = false_e; + return oldest_index; + } +} + +size_t cache_read(cache_t *cache, uint8_t *data, size_t len, size_t offset) +{ + size_t bytesRead = 0; + + // lock the cache + mutex_lock(&cache->mutex); + do + { + size_t index = 0; + size_t intraOffset = (offset % cache->lineSize); + + // calculate the useful size within this line. + size_t size = cache->lineSize - intraOffset; + if (len < cache->lineSize ) // if the remainder is smaller than the lineSize + size = len; // then use the remainder + + // get the line index for this ptr, if it exists + if (cache_index(cache, offset, &index) == false_e) + { + // find a cache line to fill + index = cache_next(cache); + + // fetch the data and assign the index + cache->fillLine(cache->cookie, cache->line[index].data, cache->lineSize, cache_round_offset(cache, offset)); + } + + // copy the data from this line... + memcpy(data, &cache->line[index].data[intraOffset], size); + + // move the pointers + data += size; + offset += size; + len -= size; + bytesRead += size; + } while(len > 0); + // unlock the cache + mutex_unlock(&cache->mutex); + return bytesRead; +} + +size_t cache_write(cache_t *cache, uint8_t *data, size_t len, size_t offset) +{ + size_t written = 0; + + // lock the cache + mutex_lock(&cache->mutex); + do + { + size_t index = 0; + size_t intraOffset = (offset % cache->lineSize); + + // calculate the useful size within this line. + size_t size = cache->lineSize - intraOffset; + if (len < cache->lineSize) // if the remainder is smaller than the lineSize + size = len; // then use the remainder + + // get the line index for this ptr, if it exists + if (cache_index(cache, offset, &index) == false_e) + { + // find a cache line to fill + // this doesn't fail, if there are no open ones it will age out an + // older line and we'll need to initialize it's data + index = cache_next(cache); + + // initialize the correct start_offset and size + cache->line[index].start_offset = cache_round_offset(cache, offset); + cache->line[index].end_offset = cache->line[index].start_offset + cache->lineSize; + } + + // copy the data from this line... + memcpy(&cache->line[index].data[intraOffset], data, size); + + // update the meta-data + cache->line[index].valid = true_e; + cache->line[index].age = clock(); + + // if it's a write-through policy, go ahead and write + if (cache->policy == CACHE_POLICY_WRITE_THROUGH) + cache->commitLine(cache->cookie, cache->line[index].data, cache->lineSize, cache->line[index].start_offset); + + // move the pointers + data += size; + offset += size; + len -= size; + written += size; + //printf("%u bytes left to write to cache\n", len); + } while(len > 0); + // unlock the cache + mutex_unlock(&cache->mutex); + return written; +} + +void cache_invalidate(cache_t *cache) +{ + size_t i = 0; + mutex_lock(&cache->mutex); + for (i = 0; i < cache->numLines; i++) + { + if (cache->line[i].valid) + { + cache->line[i].age = 0; + cache->line[i].valid = false_e; + } + } + mutex_unlock(&cache->mutex); +} + +void cache_flush(cache_t *cache) +{ + size_t i = 0; + mutex_lock(&cache->mutex); + for (i = 0; i < cache->numLines; i++) + { + if (cache->line[i].valid) + { + cache->commitLine(cache->cookie, cache->line[i].data, cache->lineSize, cache->line[i].start_offset); + cache->line[i].age = 0; + cache->line[i].valid = false_e; + } + } + mutex_unlock(&cache->mutex); +} + +//****************************************************************************** +// INTERNAL TESTING +//****************************************************************************** + +static size_t cache_fill(void *cookie, uint8_t *ptr, size_t size, size_t offset) +{ + FILE *f = (FILE *)cookie; + //fpos_t foffset = (fpos_t)offset; + //fsetpos(f, &foffset); + fseek(f, offset, SEEK_SET); + //printf("Filling Cache Line @ %lu for %lu\n", offset, size); + return fread(ptr, 1, size, f); +} + +static size_t cache_commit(void *cookie, uint8_t *ptr, size_t size, size_t offset) +{ + FILE *f = (FILE *)cookie; + //fpos_t foffset = (fpos_t)offset; + //fsetpos(f, &foffset); + fseek(f, offset, SEEK_SET); + //printf("Committing Cache Line @ %lu for %lu\n", offset, size); + return fwrite(ptr, 1, size, f); +} + +static void countUp(uint8_t *ptr, size_t size, uint32_t start) +{ + size_t i = 0; + uint32_t *p = (uint32_t *)ptr; + for (i = 0; i < (size/sizeof(uint32_t)); i++) + { + p[i] = i + start; + } +} + +bool_e cache_unittest(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) +{ + bool_e ret = true_e; + size_t i; + size_t numBufs = (1<<10); + size_t bufSize = (1<<8); + size_t lineSize = (1<<7); + size_t numLines = (1<<11); + size_t offset = 0; + uint8_t *buffer = (uint8_t *)calloc(bufSize, sizeof(uint8_t)); + FILE *f = fopen("cache.dat", "w+"); + SOSAL_PRINT(SOSAL_ZONE_API, "cache_unittest(%u, %p)\n", argc, argv); + if (f != NULL) + { + cache_t *c = cache_create(lineSize, numLines, CACHE_POLICY_WRITE_THROUGH, cache_fill, cache_commit, f); + if (c) + { + // fill up the cache! + //printf("Created cache!\n"); + for (i = 0; i < numBufs; i++) + { + countUp(buffer, bufSize,i*bufSize); + cache_write(c, buffer, bufSize, offset); + offset += bufSize; + } + //printf("Fill up cache items\n"); + + // commit everything to the file + cache_flush(c); + + // read back the data and verify it + offset = 0; + for (i = 0; i < numBufs; i++) + { + if (cache_read(c, buffer, bufSize, offset) == bufSize) + { + uint32_t *p = (uint32_t *)buffer; + size_t j = 0; + for (j = 0; j < bufSize/sizeof(uint32_t); j++) + { + if (p[j] != j + (i*bufSize)) + { + printf("ERROR! Failed count check on item %u!="FMT_SIZE_T"\n", p[j], j+(i*bufSize)); + ret = false_e; + } + } + offset += bufSize; + } + else + { + printf("ERROR! Failed to read enough bytes!\n"); + } + } + + // toss everything that's in the cache + cache_invalidate(c); + + cache_destroy(c); + c = NULL; + } + else + { + printf("ERROR: Failed to create cache!\n"); + ret = false_e; + } + fclose(f); + f = NULL; + } + else + { + printf("ERROR: Failed to open cache file, probably a permission issue or read-only location?\n"); + ret = false_e; + } + f = fopen("poetry.txt","r"); + if (f) + { + size_t len = 0; + fseek(f, 0, SEEK_END); + len = ftell(f); + //printf("File %p is %s is %lu bytes long\n", f, "test"PATH_DELIM"poetry.txt", len); + + if (len > 0) + { + cache_t *c = cache_create(lineSize, numLines, CACHE_POLICY_WRITE_THROUGH, cache_fill, cache_commit, f); + if (c) + { + const size_t compSize = 200; + uint32_t i,iterations = 10; + uint8_t *cached = malloc(compSize); + uint8_t *uncached = malloc(compSize); + + // read an arbitrary offset in to the file for an arbitrary size + // and compare with what the cache sees + for (i = 0; i < iterations; i++) + { + offset = rand() % (len-compSize); + cache_read(c, cached, compSize, offset); + fseek(f, offset, SEEK_SET); + if (fread(uncached, 1, compSize, f) > 0) + { + //printf("Comparing %lu bytes @ %lu offset\n", compSize, offset); + if (memcmp(cached, uncached, compSize) != 0) + { + printf("Failed seek to "FMT_SIZE_T"!\n", offset); + ret = false_e; + } + } + } + free(cached); + free(uncached); + cache_destroy(c); + } + else + ret = false_e; + } + else + ret = false_e; + fclose(f); + } + //else + // ret = false_e; + return ret; +} + + diff --git a/source/sosal/concerto.mak b/source/sosal/concerto.mak new file mode 100644 index 0000000..b44bffa --- /dev/null +++ b/source/sosal/concerto.mak @@ -0,0 +1,59 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include $(PRELUDE) +TARGET=sosal +TARGETTYPE=library +DEFS += $(SOSAL_FLAGS) +IDIRS += $(SOSAL_INC) $(MEM_INCS) +ifeq ($(TARGET_OS),DARWIN) +IDIRS += /Library/Frameworks/CarbonCore/Headers +endif +CSOURCES=$(filter-out unittest.c,$(all-c-files)) +include $(FINALE) + +_MODULE=sosal_test +include $(PRELUDE) +TARGET=sosal_test +TARGETTYPE=exe +CSOURCES=unittest.c +DEFS+=SOSAL_UNITTEST +SYS_SHARED_LIBS+=$(IPC_LIBS) $(MEM_LIBS) $(PLATFORM_LIBS) +STATIC_LIBS+=sosal +include $(FINALE) + +_MODULE=uinput_test +include $(PRELUDE) +TARGET=uinput_test +TARGETTYPE=exe +CSOURCES=event.c mutex.c options.c queue.c ring.c thread.c uinput.c debug.c +DEFS+=UINPUT_TEST +SYS_SHARED_LIBS+=$(PLATFORM_LIBS) +include $(FINALE) + +_MODULE=CThreaded +include $(PRELUDE) +TARGET=cthreaded +TARGETTYPE=library +CPPSOURCES=CThreaded.cpp +include $(FINALE) + +_MODULE=modload_test +include $(PRELUDE) +TARGET=modload_test +TARGETTYPE=exe +CSOURCES=module.c debug.c +DEFS+=MODULE_TEST +SYS_SHARED_LIBS+=$(PLATFORM_LIBS) +include $(FINALE) diff --git a/source/sosal/debug.c b/source/sosal/debug.c new file mode 100644 index 0000000..d8b2a25 --- /dev/null +++ b/source/sosal/debug.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +/*! \brief The runtime variable which controls which debugging zones are + * enabled. + * \ingroup group_sosal_debug + */ +uint32_t sosal_zone_mask = 0x3; + +#if defined(SOSAL_RUNTIME_DEBUG) +#pragma message("SOSAL Debugging in RUNTIME Mode! export SOSAL_ZONE_MASK to affect.") +#endif + +#if defined(POSIX) +void debug_get_zone_mask(char *mask_name, uint32_t *mask) +{ + char *value = getenv(mask_name); + if (value) + { + sscanf(value, "%x", mask); + } +} +#elif defined(WIN32) +void debug_get_zone_mask(char *mask_name, uint32_t *mask) +{ + char value[MAX_PATH]; + if (GetEnvironmentVariable(mask_name, value, MAX_PATH) > 0) + { + sscanf(value, "%x", mask); + } +} +#endif diff --git a/source/sosal/event.c b/source/sosal/event.c new file mode 100644 index 0000000..318cd86 --- /dev/null +++ b/source/sosal/event.c @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef SYSBIOS +#include +#endif +#include +#include + +#if defined(POSIX) && !defined(ESUCCESS) +#define ESUCCESS 0 +#endif + +#ifdef POSIX +void milliseconds_from_now(struct timespec *time_spec, uint32_t milliseconds) +{ + struct timeval now; + + gettimeofday(&now, NULL); + time_spec->tv_sec = now.tv_sec + (milliseconds / 1000); + time_spec->tv_nsec = (now.tv_usec * 1000) + ((milliseconds%1000) * 1000000); + if (time_spec->tv_nsec > 1000000000) { + time_spec->tv_sec += 1; + time_spec->tv_nsec -= 1000000000; + } +} +#endif + +bool_e event_init(event_t *e, bool_e autoreset) +{ +#ifdef POSIX + int err = 0; + err |= pthread_mutex_init(&e->mutex, NULL); + err |= pthread_condattr_init(&e->attr); + err |= pthread_cond_init(&e->cond, &e->attr); + e->set = false_e; + e->autoreset = autoreset; + if (err == ESUCCESS) +#elif defined(SYSBIOS) + mutex_init(&e->mutex); + e->event_group = Event_create(NULL, NULL); + e->set = false_e; + e->autoreset = autoreset; + if(e->event_group != NULL) +#else + BOOL bManual = TRUE; + if (autoreset) + bManual = FALSE; + *e = CreateEvent(NULL, bManual, FALSE, NULL); + if (*e != NULL) +#endif + return true_e; + else + return false_e; +} + +bool_e event_deinit(event_t *e) +{ +#ifdef POSIX + int err = 0; + do { + err = pthread_cond_destroy(&e->cond); + if (err == EBUSY) { + pthread_mutex_lock(&e->mutex); + e->set = false_e; + pthread_cond_broadcast(&e->cond); + pthread_mutex_unlock(&e->mutex); + } + } while (err != 0); + pthread_condattr_destroy(&e->attr); + pthread_mutex_destroy(&e->mutex); + return true_e; +#elif defined(SYSBIOS) + mutex_deinit(&e->mutex); + Event_delete(&e->event_group); + return true_e; +#else + return CloseHandle(*e); +#endif +} + +#ifdef POSIX +static bool_e event_timed_wait(event_t *e, uint32_t ms) +{ + int retcode = 0; + bool_e ret = false_e; + if (ms < EVENT_FOREVER) + { + struct timespec time_spec; + milliseconds_from_now(&time_spec, ms); + //SOSAL_PRINT(SOSAL_ZONE_EVENT, "Waiting for at least %u ms or until %lu:%lu\n", ms, time_spec.tv_sec, time_spec.tv_nsec); + retcode = pthread_cond_timedwait(&e->cond, &e->mutex, &time_spec); + } + else + { + //SOSAL_PRINT(SOSAL_ZONE_EVENT, "Waiting indefinitely for event!\n"); + retcode = pthread_cond_wait(&e->cond, &e->mutex); + } + if (retcode == ETIMEDOUT && e->set == false_e) { + SOSAL_PRINT(SOSAL_ZONE_WARNING, "WARNING: Event %p Timeout!\n", e); + ret = false_e; + } else if (retcode == ETIMEDOUT && e->set == true_e) { + // this should not have happened (but the signal is set, so we need to return true). + ret = true_e; + } else if (retcode == ESUCCESS && e->set == false_e) { + // the condition was signalled but someone has either lowered or never set the flag. + SOSAL_PRINT(SOSAL_ZONE_WARNING, "WARNING: Kicking out of event %p!\n", e); + ret = false_e; + } else if (retcode == ESUCCESS && e->set == true_e) { + // someone called "set" + //SOSAL_PRINT(SOSAL_ZONE_EVENT, "SOSAL: Event %p set!\n", e); + ret = true_e; + } else { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR: General Error in Event %p code %d\n", e, retcode); + } + return ret; +} +#endif + +bool_e event_wait(event_t *e, uint32_t timeout) +{ + bool_e ret = false_e; +#ifdef POSIX + pthread_mutex_lock(&e->mutex); + SOSAL_PRINT(SOSAL_ZONE_EVENT, "SOSAL: Waiting on Event %p (%s) for %u ms\n", e, ((e->autoreset)?"Auto":"Manual"), timeout); + if (!e->autoreset) + { + if (e->set == false_e) + ret = event_timed_wait(e, timeout); + else + ret = true_e; + } + else // "pulse" mode events + { + ret = event_timed_wait(e, timeout); + // if ret is false_e then timeout + // if ret is true_e and e->set is true_e then signalled (reset the event) + // if ret is true_e and e->set is false_e then we're being kicked out + if (ret == true_e && e->set == true_e) + e->set = false_e; + else if (ret == true_e && e->set == false_e) + ret = false_e; + } + SOSAL_PRINT(SOSAL_ZONE_EVENT, "SOSAL: Event %p ret = %u set = %u!\n", e, ret, e->set); + pthread_mutex_unlock(&e->mutex); + return ret; +#elif defined(SYSBIOS) + unsigned int andMask, orMask; + mutex_lock(&e->mutex); + SOSAL_PRINT(SOSAL_ZONE_EVENT, "SOSAL: Waiting on Event %p (%s) for %u ms\n", e, ((e->autoreset)?"Auto":"Manual"), timeout); + andMask = SYSBIOS_SINGLE_EVENT_FLAG_MASK; + orMask = 0; + if (!e->autoreset) + { + if (e->set == false_e) + ret = (bool_e)Event_pend(e->event_group, andMask, orMask, timeout); + else + ret = true_e; + } + else + { + ret = (bool_e)Event_pend(e->event_group, andMask, orMask, timeout); + // Event_pend() returns number of consumed events or zero if timeout + // if ret is false_e then timeout + // if ret is true_e and e->set is true_e then signalled (reset the event) + // if ret is true_e and e->set is false_e then we're being kicked out + if (ret == true_e && e->set == true_e) + e->set = false_e; + else if (ret == true_e && e->set == false_e) + ret = false_e; + } + SOSAL_PRINT(SOSAL_ZONE_EVENT, "SOSAL: Event %p ret = %u set = %u!\n", e, ret, e->set); + mutex_unlock(&e->mutex); +#else + DWORD status = WaitForSingleObject(*e, timeout); + if (status == WAIT_OBJECT_0) + ret = true_e; +#endif + return ret; +} + +bool_e event_set(event_t *e) +{ +#ifdef POSIX + int err = 0; + pthread_mutex_lock(&e->mutex); + //SOSAL_PRINT(SOSAL_ZONE_EVENT, "Setting Event %p\n", e); + e->set = true_e; + err = pthread_cond_broadcast(&e->cond); + pthread_mutex_unlock(&e->mutex); + if (err == ESUCCESS) + return true_e; + else + return false_e; +#elif defined(SYSBIOS) + //mutex_lock(&e->mutex); + e->set = true_e; + Event_post(e->event_group, SYSBIOS_SINGLE_EVENT_FLAG_MASK); + //mutex_unlock(&e->mutex); + return true_e; +#else + return (bool_e)SetEvent(*e); +#endif +} + +bool_e event_reset(event_t *e) +{ +#ifdef POSIX + pthread_mutex_lock(&e->mutex); + //SOSAL_PRINT(SOSAL_ZONE_EVENT, "Resetting Event %p\n", e); + e->set = false_e; + pthread_mutex_unlock(&e->mutex); + return true_e; +#elif defined(SYSBIOS) + mutex_lock(&e->mutex); + e->set = false_e; + mutex_unlock(&e->mutex); + return true_e; +#else + return (bool_e)ResetEvent(*e); +#endif +} + +bool_e event_unittest(int argc __attribute__((unused)), + char *argv[] __attribute__((unused))) +{ + event_t e; + int numErrors = 0; + uint32_t timeout = 100; + + SOSAL_PRINT(SOSAL_ZONE_API, "event_unittest(%u, %p)\n", argc, argv); + + event_init(&e, false_e); + + // wait on the event, should fail as not signaled. + if (event_wait(&e, timeout) == true_e) + { + numErrors++; + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Failed to wait for timeout!\n"); + } + + // signal the event + event_set(&e); + + // wait on the event forever, should succeed + if (event_wait(&e, EVENT_FOREVER) == false_e) + { + numErrors++; + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Failed to wait for signal!\n"); + } + + // lower the event + event_reset(&e); + + // wait again, should fail + if (event_wait(&e, timeout) == true_e) + { + numErrors++; + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Failed to wait for timeout 2!\n"); + } + + event_deinit(&e); + + if (numErrors > 0) + return false_e; + else + return true_e; +} + diff --git a/source/sosal/fourcc.c b/source/sosal/fourcc.c new file mode 100644 index 0000000..707ce09 --- /dev/null +++ b/source/sosal/fourcc.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +fourcc_t strtofourcc(const char *string) +{ + fourcc_t fourcc = 0; + fourcc |= ((uint8_t)string[0])<<0; + fourcc |= ((uint8_t)string[1])<<8; + fourcc |= ((uint8_t)string[2])<<16; + fourcc |= ((uint8_t)string[3])<<24; + return fourcc; +} + +char *fourcctostr(fourcc_t fcc) +{ + static char code[5]; + strncpy(code, (char *)&fcc, 4); + code[4] = '\0'; + return code; +} + +bool_e fourcc_unittest(int argc, char *argv[]) +{ + int i = 0; + for (i = 0; i < argc; i++) + { + printf("0x%08x == %s\n", strtofourcc(argv[i]), argv[i]); + } + return true_e; +} + diff --git a/source/sosal/fph.c b/source/sosal/fph.c new file mode 100644 index 0000000..a883813 --- /dev/null +++ b/source/sosal/fph.c @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +/*! + * The pre-supplied hashing function for the Fast Pointer Hash. + * \param fph + * \param value + * \see fph_key_f + */ +value_t fph_hash(void *fph, ptr_t value) +{ + value_t hash = (value_t)value; + //hash &= 0xFFFFFF00; + hash >>= 8; +#ifndef FPH_OPTIMIZED + hash %= ((fph_t *)fph)->numBlocks; +#else + hash &= (((fph_t *)fph)->numBlocks - 1); // assumes 2^n numBlocks +#endif + hash *= ((fph_t *)fph)->blockSize; + //SOSAL_PRINT(SOSAL_ZONE_HASH, "%p => %u\n", value, hash); + return hash; +} + +#ifdef FPH_OPTIMIZED +/*! + * Determines if a size_t is a power of two. + * \param a The number to determine if it is a power of two. + * \return bool_e + * \retval true_e It is a power of two. + * \retval false_e It is not a power of two. + */ +static bool_e is_power_two(size_t a) +{ + value_t ones = 0; + uint32_t bit = 0; + for (bit = 0; bit < (8 * sizeof(value_t)); bit++) + { + if (((1 << bit) & a) != 0) + ones++; + } + if (ones > 1 || ones == 0) + return false_e; + else + return true_e; +} +#endif + +fph_t *fph_init(size_t numBlocks, size_t blockSize, fph_key_f keyFunc) +{ + fph_t *fph = (fph_t*)malloc(sizeof(fph_t)); + if (fph) + { + memset(fph, 0, sizeof(fph_t)); +#ifdef FPH_OPTIMIZED + if (!is_power_two(numBlocks)) + { + free(fph); + return NULL; + } +#endif + fph->numBlocks = numBlocks; + fph->blockSize = blockSize; + fph->numElem = fph->numBlocks * fph->blockSize; + if (keyFunc) + fph->keyFunc = keyFunc; + else + fph->keyFunc = fph_hash; + fph->hash = (fph_kv_t *)malloc(fph->numElem * sizeof(fph_kv_t)); + if (fph->hash) + memset(fph->hash, 0, fph->numElem * sizeof(fph_kv_t)); +#ifdef FPH_METRICS + fph->collisions = (uint32_t *)malloc(fph->numBlocks * sizeof(uint32_t)); + if (fph->collisions) + memset(fph->collisions, 0, fph->numBlocks * sizeof(uint32_t)); + fph->length = (uint32_t *)malloc(fph->numBlocks * sizeof(uint32_t)); + if (fph->length) + memset(fph->length, 0, fph->numBlocks * sizeof(uint32_t)); +#endif + } + return fph; +} + +void fph_deinit(fph_t *fph) +{ + if (fph) + { + if (fph->hash) + free(fph->hash); +#ifdef FPH_METRICS + if (fph->collisions) + free(fph->collisions); + if (fph->length) + free(fph->length); +#endif + memset(fph, 0xEF, sizeof(fph_t)); + free(fph); + } + return; +} + +int fph_get(fph_t *fph, ptr_t k, ptr_t *v) +{ + uint32_t i = 0; + uint32_t index = fph->keyFunc(fph, k); + *v = NULL; + for (i = index; i < (index + fph->blockSize); i++) { + if (fph->hash[i].key == k) { + *v = fph->hash[i].value; + return 1; + } + } + return 0; +} + +int fph_clr(fph_t *fph, ptr_t k) +{ + uint32_t i = 0; + uint32_t block, index = fph->keyFunc(fph,k); + for (i = index; i < (index + fph->blockSize); i++) { + if (fph->hash[i].key == k) { + fph->hash[i].key = NULL; + fph->hash[i].value = NULL; +#ifdef FPH_METRICS + block = index / fph->blockSize; + if (fph->length[block] > 1) + fph->collisions[block]--; + else if (fph->length[block] == 1) + fph->collisions[block] = 0; + fph->length[block]--; + fph->numPtrs--; +#endif + return 1; + } + } + return 0; +} + +int fph_set(fph_t *fph, ptr_t k, ptr_t v) +{ + uint32_t index, i, block; + + if (fph == NULL || k == NULL) // this is not valid + return 0; + + // determine the index + index = fph->keyFunc(fph, k); +#ifdef FPH_METRICS + block = index / fph->blockSize; +#endif + for (i = index; i < (index + fph->blockSize); i++) { + if (fph->hash[i].key == k) { // REPLACEMENT + fph->hash[i].key = k; + fph->hash[i].value = v; +#ifdef FPH_METRICS + fph->numReplacements++; + fph->collisions[block]++; +#endif + return 1; + } + if (fph->hash[i].key == NULL) { // NEW FILL + fph->hash[i].key = k; + fph->hash[i].value = v; +#ifdef FPH_METRICS + fph->length[block]++; + if (fph->length[block] > fph->blockSize) + { + SOSAL_PRINT(SOSAL_ZONE_HASH, "ERROR! BlockSize has been exceeded!\n"); + } + fph->numPtrs++; +#endif + return 1; + } + } +#ifdef FPH_METRICS + if (i == (index + fph->blockSize)) + { + SOSAL_PRINT(SOSAL_ZONE_WARNING, "WARNING!! Fell out of hash!\n"); + fph->numMisses++; + } +#endif + return 0; +} + +#ifdef FPH_TEST +#include +#include + +ptr_t rand_ptr() +{ + uint32_t range = 0xFFFFFFFF; + int r = rand(); + ptr_t p = 0; + + if (range > RAND_MAX) + r <<= 8; + p = (ptr_t)r; + return p; +} + +typedef struct _stats_t { + uint32_t sum; + uint32_t avg; + uint32_t cnt; +} Stats_t; + +#define TWO_POW(x) (1<<(x)) + +int main(int argc, char *argv[]) +{ + uint32_t n = (argc > 1 ? atoi(argv[1]) : 15); + uint32_t numPtrs = TWO_POW(n); + rtime_t c_start, c_linear, c_hash; + rtime_t c_lsum = 0, c_hsum = 0; + double c_lavg, c_havg; + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + +#if defined(DVP_RUNTIME_DEBUG) + debug_get_zone_mask("DVP_ZONE_MASK", &dvp_zone_mask); +#endif + + srand((uint32_t)time(NULL)); + + fph_t *fph = fph_init(TWO_POW(n/2 + 1), TWO_POW(n/2 + 1), NULL); + fph_kv_t *linear = (fph_kv_t *)malloc(numPtrs * sizeof(fph_kv_t)); + + if (fph && linear) + { + uint32_t i,j; + ptr_t k,v; + Stats_t collisions; + Stats_t lengths; + + memset(linear, 0, sizeof(fph_kv_t) * numPtrs); + // create bunch of pointers and add them to the hash + for (i = 0; i < numPtrs; i++) + { + // generate a random value pair + k = rand_ptr(); + v = rand_ptr(); + + // add this to the linear array and the hash + c_start = rtimer_now(); + for (j = 0; j < numPtrs; j++) { + if (linear[j].key == NULL && linear[j].value == NULL) { + linear[j].key = k; + linear[j].value = v; + } + } + c_linear = rtime_now() - c_start; + c_start = rtime_now(); + fph_set(fph, k, v); + c_hash = rtime_now() - c_start; + + c_hsum += c_hash; + c_lsum += c_linear; + } + c_lavg = (double)c_lsum / numPtrs; + c_havg = (double)c_hsum / numPtrs; + + memset(&collisions, 0, sizeof(Stats_t)); + memset(&lengths, 0, sizeof(Stats_t)); + +#ifdef FPH_METRICS + // collate data + for (i = 0; i < fph->numBlocks; i++) + { + //SOSAL_PRINT(SOSAL_ZONE_HASH, "[%u] collisions = %u, length = %u\n", i, fph->collisions[i], fph->length[i]); + lengths.sum += fph->length[i]; + collisions.sum += fph->collisions[i]; + } + collisions.cnt = fph->numBlocks; + lengths.cnt = fph->numBlocks; + collisions.avg = collisions.sum / collisions.cnt; + lengths.avg = lengths.sum / lengths.cnt; +#endif + + SOSAL_PRINT(SOSAL_ZONE_HASH, "Num Blocks: %u\n", fph->numBlocks); + SOSAL_PRINT(SOSAL_ZONE_HASH, "Block Size: %u\n", fph->blockSize); +#ifdef FPH_METRICS + SOSAL_PRINT(SOSAL_ZONE_HASH, "Collisions: Sum %u :: Avg %lu\n", collisions.sum, collisions.avg); + SOSAL_PRINT(SOSAL_ZONE_HASH, "Lengths: Sum %u :: Avg %lu\n", lengths.sum, lengths.avg); + SOSAL_PRINT(SOSAL_ZONE_HASH, "Misses: %u\n", fph->numMisses); + SOSAL_PRINT(SOSAL_ZONE_HASH, "Total Hash Ptrs: %u\n", fph->numPtrs); + SOSAL_PRINT(SOSAL_ZONE_HASH, "Replacements: %u\n",fph->numReplacements); + +#endif + SOSAL_PRINT(SOSAL_ZONE_HASH, "Linear Time: Sum %lu :: Avg %lf\n", c_lsum, c_lavg); + SOSAL_PRINT(SOSAL_ZONE_HASH, "Hash Time: Sum %lu :: Avg %lf\n", c_hsum, c_havg); + SOSAL_PRINT(SOSAL_ZONE_HASH, "rtimer_freq()="FMT_RTIMER_T"\n",rtimer_freq()); + + free(linear); + fph_deinit(fph); + } + return 0; +} +#endif diff --git a/source/sosal/hash.c b/source/sosal/hash.c new file mode 100644 index 0000000..b6190e8 --- /dev/null +++ b/source/sosal/hash.c @@ -0,0 +1,504 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static record_t *record_create(value_t key, value_t value) +{ + record_t *record = calloc(1, sizeof(record_t)); + if (record) + { + record->key = key; + record->value = value; + } + return record; +} + +static void record_destroy(record_t *record) +{ + if (record) + free(record); +} + +static int hash_compare_record(node_t *a, node_t *b) +{ + if (a != NULL && b != NULL) + { + record_t *ra = (record_t *)a->data; + record_t *rb = (record_t *)b->data; + if (ra != NULL && rb != NULL) + { + if (ra->key > rb->key) + return 1; + else if (ra->key == rb->key) + return 0; + else if (ra->key < rb->key) + return -1; + } + } + return 0; +} + +static void hash_print_record(node_t *node) +{ + if (node) + { + record_t *record = (record_t *)node->data; + + if (record != NULL) { + SOSAL_PRINT(SOSAL_ZONE_HASH, ""FMT_SIZE_T":"FMT_SIZE_T" ",record->key, record->value); + } + } +} + +static int hash_is_valid_index(hash_t *h, value_t hKey) +{ + if ((h->size == HASH_SIZE_SMALL || + h->size == HASH_SIZE_MEDIUM || + h->size == HASH_SIZE_LARGE) && + (hKey < h->numSlots)) + return 1; + else + return 0; +} + +static uint32_t hash_key_to_index(hash_t *h, value_t hKey) +{ + if ((h->size == HASH_SIZE_SMALL || + h->size == HASH_SIZE_MEDIUM || + h->size == HASH_SIZE_LARGE)) + return (uint32_t)hKey; + else + return 0; +} + +/** + * This is the default keying function. + */ +static value_t hash_key(size_t numElem, value_t keyin) +{ + value_t key = keyin; + uint32_t mask = 0; + + key += (key << 10); + key ^= (key >> 6); + key += (key << 3); + key ^= (key >> 11); + key += (key << 15); + + mask = (1 << numElem) - 1; + key &= mask; + + //SOSAL_PRINT(SOSAL_ZONE_HASH, "Hash Function: %d => %lu\n", keyin, key); + + return key; +} + +/* ============================================================================= + * GLOBAL FUNCTIONS + * ===========================================================================*/ + + +void hash_destroy(hash_t *h) +{ + if (h != NULL) + { + if (h->bucket != NULL) + { + free(h->bucket); + } + free(h); + } +} + +hash_t *hash_create(hash_size_e size, hash_func_f keyFunc) +{ + hash_t *h = NULL; + int hashElem = 1 << size; + + h = (hash_t *)calloc(1, sizeof(hash_t)); + if (h != NULL) + { + h->bucket = (list_t **)calloc(hashElem, sizeof(list_t *)); + if (h->bucket == NULL) + { + free(h); + h = NULL; + } + else + { + h->numSlots = hashElem; + h->numActiveSlots = 0; + h->numTotalElem = 0; + h->size = size; + if (keyFunc == NULL) + h->keyFunc = hash_key; + else + h->keyFunc = keyFunc; + } + } + return h; +} + + + +void hash_set(hash_t *h, value_t key, value_t value) +{ + // is the hash valid? + if (h != NULL) + { + // generate the key + value_t hKey = h->keyFunc(h->size, key); + + // is the key valid? + if (hash_is_valid_index(h, hKey)) + { + uint32_t index = hash_key_to_index(h,hKey); + record_t *record = record_create(key, value); + node_t *node = node_create((value_t)record); + + // do we have a collision? + if (h->bucket[index] == NULL && value != 0) + { + // no, create a list and the first element + //SOSAL_PRINT(SOSAL_ZONE_HASH, "Created new list added node to list\n"); + hash_print_record(node); + h->bucket[index] = list_create(); + list_push(h->bucket[index], node); + h->numActiveSlots++; + h->numTotalElem++; + SOSAL_PRINT(SOSAL_ZONE_HASH, "SET: "FMT_SIZE_T":"FMT_SIZE_T"\n", record->key, record->value); + } + else if (h->bucket[index] != NULL) + { + // there's a key collision + //SOSAL_PRINT(SOSAL_ZONE_HASH, "Collision detected!\n"); + + // are we removing the value or adding a value? + if (value == 0) + { + node_t *removed = NULL; + do { + removed = list_remove_match(h->bucket[index], node, hash_compare_record); + if (removed != NULL) + { +#if defined(SOSAL_DEBUG) + record_t *r = (record_t *)removed->data; +#endif + //SOSAL_PRINT(SOSAL_ZONE_HASH, "Removed Record from List!\n"); + h->numTotalElem--; + if (list_length(h->bucket[index]) == 0) + { + list_destroy(h->bucket[index]); + h->numActiveSlots--; + h->bucket[index] = NULL; + } + SOSAL_PRINT(SOSAL_ZONE_HASH, "CLR: "FMT_SIZE_T":"FMT_SIZE_T"\n", r->key, r->value); + record_destroy((record_t*)node_destroy(removed)); + } + } while (removed != NULL); + } + else // we're adding to a link list + { + // remove existing key/value pair if it exists + node_t *removed = list_remove_match(h->bucket[index], node, hash_compare_record); + if (removed) + { +#if defined(SOSAL_DEBUG) + record_t *r = (record_t *)removed->data; +#endif + //SOSAL_PRINT(SOSAL_ZONE_HASH, "Record already exists in hash, removing!\n"); + h->numTotalElem--; + SOSAL_PRINT(SOSAL_ZONE_HASH, "CLR: "FMT_SIZE_T":"FMT_SIZE_T"\n", r->key, r->value); + record_destroy((record_t*)node_destroy(removed)); + // don't remove the list here, we're about to add to it. + } + + //SOSAL_PRINT(SOSAL_ZONE_HASH, "Adding record to hash...\n"); + // put the items in sorted order + node = list_insert(h->bucket[index], node, hash_compare_record, true_e); + if (node) + { + h->numTotalElem++; + SOSAL_PRINT(SOSAL_ZONE_HASH, "SET: "FMT_SIZE_T":"FMT_SIZE_T"\n", record->key, record->value); + } + else + { + SOSAL_PRINT(SOSAL_ZONE_HASH, "SET: "FMT_SIZE_T":--\n", record->key); + } + } + } + else if (h->bucket[index] == NULL && value == 0) + { + // tried to remove something that wasn't there. + record_destroy((record_t *)node_destroy(node)); + return; + } + } + } + return; +} + +bool_e hash_get(hash_t *h, value_t key, value_t *value) +{ + bool_e found = false_e; + + // is the hash valid and does it have items? + if (h != NULL && h->numActiveSlots > 0) + { + // generate the key + value_t hKey = h->keyFunc(h->size, key); + + // is the key valid? + if (hash_is_valid_index(h, hKey)) + { + // define tmp pointer + uint32_t index = hash_key_to_index(h,hKey); + + // is there something at that index? + if (h->bucket[index] != NULL) + { + record_t *record = record_create(key, 0); + node_t *node = node_create((value_t)record); + node_t *desired = NULL; + + // now get value from the list + desired = list_search(h->bucket[index], node, hash_compare_record); + + // key was found in the list + if (desired != NULL) + { + record_t *match = (record_t *)desired->data; + SOSAL_PRINT(SOSAL_ZONE_HASH, "GET: "FMT_SIZE_T":"FMT_SIZE_T"\n", match->key, match->value); + + // get the value + *value = match->value; + found = true_e; + } + node_destroy(node); + record_destroy(record); + } + } + } + if (found == false_e) { + SOSAL_PRINT(SOSAL_ZONE_HASH, "GET: "FMT_SIZE_T":---\n", key); + } + return found; +} + +/** + * @note If the hash index loops you will get the same count back again and + * your pointer will not be set. Be sure to NULL (and check) your pointer + * between each usage to prevent this scenario. + */ +size_t hash_clean(hash_t *h, value_t *value) +{ + static uint32_t index = 0; + + if (h != NULL && value != NULL && h->numActiveSlots > 0) + { + // move to a non-null section. + while (h->bucket[index] == NULL && index < h->numSlots) { + //SOSAL_PRINT(SOSAL_ZONE_HASH, "Bucket[%u] is empty\n", index); + index++; + } + + if (index >= h->numSlots) + { + // reset the index + index = 0; + } + + // if we are in hash still... + if (index < h->numSlots) + { + // we found a list + list_t *bucket = h->bucket[index]; + node_t *node = list_pop(bucket); + if (node) + { + record_t *record = (record_t *)node->data; + h->numTotalElem--; + *value = record->value; + if (list_length(bucket) == 0) + { + list_destroy(bucket); + h->numActiveSlots--; + h->bucket[index] = NULL; + } + } + } + return h->numTotalElem; + } + else + return 0; +} + +size_t hash_length(hash_t *h) +{ + size_t length = 0; + if (h != NULL) + { + length = h->numTotalElem; + } + return length; +} + +void hash_print(hash_t *h, bool_e printElems) +{ + unsigned int i; + int sum = 0; + int avg = 0; + int num = 0; + int len = 0; + float util = 0.0; + if (h != NULL) + { + util = (float)((float)h->numActiveSlots * 100)/h->numSlots; + printf("[%p] hash_t ["FMT_SIZE_T"/"FMT_SIZE_T"] => %lf%%\n", h, h->numActiveSlots, h->numSlots, util); + if (printElems == true_e) + { + for (i = 0; i < h->numSlots;i++) + { + len = list_length(h->bucket[i]); + if (len > 0) + { + printf("Bucket[%u] has %u records: ",i,len); + sum += len; + num++; + avg = sum/num; + list_print(h->bucket[i], hash_print_record); + printf("\n"); + } + } + printf("Average List Depth is %d\n",avg); + } + printf("\tTotal hash_t Size is "FMT_SIZE_T" elements\n",h->numTotalElem); + printf("\tTotal Collisions is "FMT_SIZE_T"\n",(h->numTotalElem - h->numActiveSlots)); + } +} + +static value_t rand_value() +{ + return (value_t)(rand()<<2); +} + +bool_e hash_unittest(int argc, char *argv[]) +{ + int numElem = 0; + value_t getValue = 0; + value_t setValue = 0; + value_t tmpValue = 0; + value_t key = 0; + int i = 0; + int numErrors = 0; + hash_size_e size = HASH_SIZE_SMALL; + bool_e verbose = false_e; + option_t hash_opts[] = { + {OPTION_TYPE_BOOL, &verbose, sizeof(bool_e), "-v", "--verbose", "Used to print out debugging information"}, + {OPTION_TYPE_INT, &size, sizeof(int), "-hs", "--hash-size", "Used to indicate the hash size"}, + }; + hash_t *h = NULL; + + option_process(argc, argv, hash_opts, 1); + + h = hash_create(size, NULL); + numElem = (1 << (h->size-1)); // half the elements that we could hold... + if (verbose) + printf("Adding %u elements to hash\n",numElem); + for (i = 0; i < numElem; i++) + { + key = rand(); + setValue = rand_value(); + + // set the initial value... + hash_set(h, key, setValue); + + // now remove it + hash_set(h, key, 0); + + // was it there? + if (hash_get(h, key, &getValue) == true_e) + { + numErrors++; + if (verbose) + printf("Found a stale value in hash!\n"); + } + + // re-add the value + hash_set(h, key, setValue); + + // now overwrite it + tmpValue = rand_value(); + hash_set(h, key, tmpValue); + + if (hash_get(h, key, &getValue) && setValue == getValue) + { + numErrors++; + printf("WARNING! Found stale value in hash, should have been overwritten!\n"); + } + + // re-overwrite to final value + hash_set(h, key, setValue); + + // re-get it + if (hash_get(h, key, &getValue) == true_e) + { + if (setValue != getValue) + { + numErrors++; + printf("ERROR: Setting "FMT_SIZE_T" returned "FMT_SIZE_T" on get\n",setValue,getValue); + } + else if (verbose) + { + printf("[%u] Set "FMT_SIZE_T" correctly!\n",i,setValue); + } + } + else + { + numErrors++; + printf("ERROR: Failed to find known value!\n"); + } + } + + if (verbose) + hash_print(h, true_e); + do { + numElem = hash_clean(h, &getValue); + //if (verbose) + //printf("cleaned out %p (%d left)\n", getValue, numElem); + } while (numElem > 0); + + if (hash_length(h) != 0) + { + numErrors++; + printf("ERROR! hash was not cleaned!\n"); + } + + if (verbose) + hash_print(h, false_e); + hash_destroy(h); + + if (numErrors > 0) { + printf("Hashing Unit Test failed with %u errors!\n", numErrors); + return false_e; + } else { + return true_e; + } +} + diff --git a/source/sosal/heap.c b/source/sosal/heap.c new file mode 100644 index 0000000..8a96921 --- /dev/null +++ b/source/sosal/heap.c @@ -0,0 +1,783 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#if SOSAL_ZONE_EXTRA != 0 +#define SOSAL_EXTRA_DEBUG +#endif + +//****************************************************************************** +// INTERNAL FUNCTIONS +//****************************************************************************** + +static bool_e ptr_is_aligned(void *ptr, size_t align) +{ + size_t addr = (size_t)ptr; + if ((addr % align) == 0) + return true_e; + else + return false_e; +} + +static void node_clear(node_t *node) +{ + if (node) + { + node->prev = NULL; + node->next = NULL; + node->data = 0; + } +} + +static void block_clear(block_t *block) +{ + if (block) + { + block->data = 0; + block->size = 0; + } +} + +#ifdef SOSAL_EXTRA_DEBUG +static void block_printer(node_t *node) +{ + block_t *block = (block_t *)node->data; + if (block) { + SOSAL_PRINT(SOSAL_ZONE_EXTRA, "Node %p Block %p Data %p for "FMT_SIZE_T" bytes\n", node, block, block->data, block->size); + } else { + SOSAL_PRINT(SOSAL_ZONE_EXTRA, "Node %p Block %p\n", node, block); + } +} +#endif + +/** This will generate the correct block size for the desired block taking the alignment and possible padding into account. */ +static size_t block_size(size_t align, size_t desired) +{ + size_t remainder = desired % align; + if (remainder != 0) + { + desired += (align - remainder); + } + return desired; +} + + +static int block_compare_ptr(node_t *a, node_t *b) +{ + if (b != NULL) + { + block_t *blockA = (block_t *)a->data; + block_t *blockB = (block_t *)b->data; + + if (blockA->data < blockB->data) + { + return -1; + } + else if (blockA->data == blockB->data) + { + return 0; + } + else if (blockA->data > blockB->data) + { + return 1; + } + } + return (0); +} + +static bool_e block_is_adjacent(block_t *a, block_t *b) +{ + if (a == NULL || b == NULL) + return false_e; + + if ((uint8_t *)a->data + a->size == (uint8_t *)b->data) + return true_e; + else + return false_e; +} + +static score_t block_rate_bestfit(node_t *current, node_t *criteria) +{ + if (current && criteria) + { + block_t *this_block = (block_t *)current->data; + block_t *comp_block = (block_t *)criteria->data; + + if (this_block->size == comp_block->size) + return MAX_SCORE; + else if (this_block->size > comp_block->size) + return MAX_SCORE - (this_block->size - comp_block->size); + else + return MIN_SCORE; + } + else + return MIN_SCORE; +} + +static bool_e block_bestfit_and_remove(list_t *list, node_t **node, block_t **block, size_t size) +{ + block_t searchBlock = {size, NULL}; + node_t searchNode = {NULL, NULL, (value_t)&searchBlock}; + node_t *foundNode; + +#ifdef SOSAL_EXTRA_DEBUG + SOSAL_PRINT(SOSAL_ZONE_HEAP, "Scoring Free List\n"); + list_print(list, block_printer); +#endif + foundNode = list_score(list, &searchNode, block_rate_bestfit); + if (foundNode != NULL) { + *node = list_extract(list, foundNode); + *block = (block_t *)(*node)->data; + return true_e; + } + else + return false_e; +} + +static bool_e block_find_and_remove(list_t *list, node_t **node, block_t **block, void *ptr) +{ + block_t searchBlock; + node_t searchNode; + node_t *foundNode; + + // find the block which controls this pointer + searchBlock.data = ptr; + searchBlock.size = 0; + searchNode.data = (value_t)&searchBlock; + searchNode.prev = NULL; + searchNode.next = NULL; + + // confirm that the block is in the free list + foundNode = list_remove_match(list, &searchNode, block_compare_ptr); + if (foundNode) + { + if (node != NULL) + *node = foundNode; + if (block != NULL) + *block = (block_t *)foundNode->data; + return true_e; + } + else + return false_e; +} + +static bool_e heap_calc_overhead(heap_t *heap) +{ + // this is the cost of keeping track of the allocations + size_t bookkeeping = sizeof(node_t) + sizeof(block_t); + + // this is the ratio of the overhead to the total + // this equation is derived from the design of the heap. + float ratio = ((float)heap->align/bookkeeping) + 1.0f; + + // recast the overhead from a float + size_t overhead = (size_t)((float)heap->bytesTotal/ratio); + + // the number of bookkeeping elements + size_t num = (overhead/bookkeeping); + + // the size of the data region of the heap + size_t data = 0; + + // the number of bytes between the overhead and the data, used to align the data pointer. + size_t pad = 0; + + if (num == 0) + return false_e; + + do { + overhead = num * bookkeeping; + data = num * heap->align; + pad = heap->bytesTotal - data - overhead; + + SOSAL_PRINT(SOSAL_ZONE_HEAP, "Heap: "FMT_SIZE_T" total = "FMT_SIZE_T" overhead + "FMT_SIZE_T" data ("FMT_SIZE_T" pad) ("FMT_SIZE_T" num) ("FMT_SIZE_T" sum)\n", heap->bytesTotal, overhead, data, pad, num, (pad+data+overhead)); + + if (heap->bytesTotal >= (pad+data+overhead)) + { + // setup the block pointer + heap->blocks = (block_t*)heap->raw; + + // setup the node pointer right afterwards + heap->nodes = (node_t *)((uint8_t *)heap->raw + num*sizeof(block_t)); + + // setup the data pointer initially + heap->data = (uint8_t *)heap->raw + overhead; + + // setup the tallies + heap->bytesUsed = 0; + heap->bytesFree = data; + heap->maxBlocks = num; + + // align the data pointer if it is not + if (ptr_is_aligned(heap->data, heap->align) == false_e) + { + // offset the data pointer if it is not aligned (the pad should have enough room) + size_t offset = (heap->align - ((size_t)heap->data % heap->align)); + if (offset > pad) + { + SOSAL_PRINT(SOSAL_ZONE_WARNING, "WARNING! Pad is too small to account for offset for alignment!\n"); + num--; + pad = heap->bytesTotal; + } + else + { + SOSAL_PRINT(SOSAL_ZONE_HEAP, "Offsetting data by "FMT_SIZE_T" bytes\n",offset); + heap->data = (uint8_t *)heap->data + offset; + return true_e; + } + } + } + else + num--; + } while (heap->bytesTotal < (pad+data+overhead)); + return true_e; +} + +/******************************************************************************* + * GLOBAL FUNCTIONS + ******************************************************************************/ + +/** + * This function takes a pointer to a heap and a byte count. + * It will 32bit align both the heap and the number of bytes. + * IE if you give it an odd pointer and an odd number of bytes + * you will have a less effective size of heap. + * Be sure you give this function 32bit aligned pointers and + * byte counts. + * @param heap + * @param buffer The begining of the heap + * @param size The size of buffer in the heap + * @param p2align Pointer to align + */ +bool_e heap_init(heap_t *heap, void *buffer, size_t size, uint32_t p2align) +{ + uint32_t spareIdx = 0; + node_t *first_node; + block_t *first_block; + + if (p2align > 12) + p2align = 12; + if (p2align < 5) + p2align = 5; + // alignments can only be between 32 bytes and 4096 bytes. + + if (heap != NULL) + memset(heap, 0, sizeof(heap_t)); + else + return false_e; + + // initialize our values + heap->bytesTotal = size; + heap->cleanPolicy = true_e; + heap->coalescePolicy = true_e; + heap->align = (1<raw = buffer; + mutex_init(&heap->mutex); + + if (buffer == NULL) + return false_e; + + if (ptr_is_aligned(buffer, 4) == false_e) // we just require 32 bit alignment + return false_e; + + // initialize the entire data space of the heap + memset(buffer, 0, size); + + // calculates and sets up the overhead and data areas + if (heap_calc_overhead(heap) == false_e) + return false_e; + + // initializes the nodes and blocks to the spare list + for (spareIdx = 0; spareIdx < heap->maxBlocks; spareIdx++) + { + node_t *this_node = &heap->nodes[spareIdx]; + block_t *this_block = &heap->blocks[spareIdx]; + + if (spareIdx > 0) + this_node->prev = &heap->nodes[spareIdx - 1]; + else { + heap->spare.head = this_node; + this_node->prev = NULL; + } + if (spareIdx < (heap->maxBlocks - 1)) + this_node->next = &heap->nodes[spareIdx + 1]; + else { + heap->spare.tail = this_node; + this_node->next = NULL; + } + this_node->data = (value_t)this_block; + this_block->data = NULL; + this_block->size = 0; + } + + // get the first node + first_node = list_pop(&heap->spare); + first_block = (block_t *)first_node->data; + + // set the first block to the size of the entire free heap + first_block->size = heap->bytesFree; + first_block->data = heap->data; + + // add this to the free list + list_push(&heap->free, first_node); + + // this block will be chopped up later for smaller allocations. + + SOSAL_PRINT(SOSAL_ZONE_HEAP, "heap_init(): heap_t *%p initialized with "FMT_SIZE_T" bytes at %p\n",heap,heap->bytesTotal,heap->raw); + return true_e; +} + + +/** + * Deconstructor + */ +void heap_deinit(heap_t *heap) +{ + mutex_deinit(&heap->mutex); + memset(heap->raw, 0, heap->bytesTotal); + memset(heap, 0, sizeof(heap_t)); +} + +/** + * Allocates a block of memory. + * @param heap + * @param num_bytes The number of bytes requested (this will be internally rounded up) + * @return Returns the allocated pointer or NULL if not enough memory existed or some internal error prevents allocation. + * NOTE - This will always return an aligned pointer. + */ +void *heap_alloc(heap_t *heap, size_t num_bytes) +{ + void *ptr = NULL; + block_t *block = NULL; + node_t *node = NULL; + + if (heap->raw == NULL) + return NULL; + + if (num_bytes == 0) + return NULL; + + // round up to the actual amount of bytes we'll allocate + num_bytes = block_size(heap->align, num_bytes); + + if (heap->bytesFree < num_bytes) + return NULL; + + mutex_lock(&heap->mutex); + +#ifdef SOSAL_EXTRA_DEBUG + // show current allocations + SOSAL_PRINT(SOSAL_ZONE_EXTRA, "Used List:\n"); + list_print(&heap->used, block_printer); +#endif + + // find the best fitting free block to reuse + if (block_bestfit_and_remove(&heap->free, &node, &block, num_bytes) == false_e) + { + // didn't find one + mutex_unlock(&heap->mutex); + return NULL; + } + else if (node && block) + { + // did the best fit have too many bytes? + if (block->size > num_bytes) + { + // get a node/block to hold the remainder + node_t *spareNode = list_pop(&heap->spare); + block_t *spareBlock = NULL; + + SOSAL_PRINT(SOSAL_ZONE_HEAP, "Fracturing Node %p Block %p\n", node, block); + if (spareNode == NULL) // ran out of meta-data + { + // put the node back on the free list + list_insert(&heap->free, node, block_compare_ptr, true_e); + SOSAL_PRINT(SOSAL_ZONE_ERROR, "FATAL ERROR! Not enough spare nodes to maintain data structures!\n"); + mutex_unlock(&heap->mutex); + return NULL; + } + + // get the block pointer + spareBlock = (block_t *)spareNode->data; + + // fracture the larger block into the spare block + spareBlock->data = ((uint8_t*)block->data + num_bytes); + spareBlock->size = (block->size - num_bytes); + + SOSAL_PRINT(SOSAL_ZONE_HEAP, "Spare Block %p has pointer %p and size "FMT_SIZE_T"\n", spareBlock, spareBlock->data, spareBlock->size); + + // now adjust the block + block->size = num_bytes; + + // put the remainder on the free list + list_insert(&heap->free, spareNode, block_compare_ptr, true_e); + } + + if (ptr_is_aligned(block->data, heap->align) == false_e) { + SOSAL_PRINT(SOSAL_ZONE_WARNING, "WARNING! The block pointer is not aligned!\n"); + } + + // put the allocated node/block on the used list + list_insert(&heap->used, node, block_compare_ptr, true_e); + + // update the global values + heap->bytesFree -= num_bytes; + heap->bytesUsed += num_bytes; + + ptr = block->data; + + mutex_unlock(&heap->mutex); + + return ptr; + } + else + { + mutex_unlock(&heap->mutex); + return NULL; + } +} + +/** + * Frees a buffer within the heap. + * @param heap + * @param pointer The pointer to free + */ +bool_e heap_free(heap_t *heap, void *pointer) +{ + block_t *block; + node_t *node; + + if (pointer == NULL) + return false_e; + + if (heap->raw == NULL) + return false_e; + + if (ptr_is_aligned(pointer, heap->align) == false_e) + return false_e; + + mutex_lock(&heap->mutex); + + // show current allocations + //SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Free List:\n"); + //list_print(&heap->free, block_printer); + + //SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Used List:\n"); + //list_print(&heap->used, block_printer); + + if (block_find_and_remove(&heap->used, &node, &block, pointer) == false_e) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR could not find the node/block/pointer in the used list!\n"); + mutex_unlock(&heap->mutex); + return false_e; + } + + // this is not the pointer we wanted. + if (pointer != block->data) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Block was misidentified!\n"); + mutex_unlock(&heap->mutex); + return false_e; + } + + // insert to the free list (in sorted order) + list_insert(&heap->free, node, block_compare_ptr, true_e); + + SOSAL_PRINT(SOSAL_ZONE_HEAP, "heap_free(): Freed Node %p Block %p Pointer %p for "FMT_SIZE_T" bytes\n", node, block, block->data, block->size); + + // upkeep the global variables + heap->bytesUsed -= block->size; + heap->bytesFree += block->size; + + // clean the block + if (heap->cleanPolicy) + memset(block->data, '0', block->size); + + /// @todo can the free list be coalesced at this point? Yes. There should be at most 2 operations to do. + if (heap->coalescePolicy) + { + node_t *prev_node = node->prev; + node_t *next_node = node->next; + block_t *prev_block = (prev_node?(block_t *)prev_node->data:NULL); + block_t *next_block = (next_node?(block_t *)next_node->data:NULL); + if (block_is_adjacent(prev_block, block) == true_e) + { + block->data = prev_block->data; + block->size += prev_block->size; + block_clear(prev_block); + + prev_node->data = (value_t)block; + prev_node->next = node->next; + if (node->next) + node->next->prev = prev_node; + node_clear(node); + SOSAL_PRINT(SOSAL_ZONE_HEAP, "Coalesced with previous node\n"); + } + else if (block_is_adjacent(block, next_block) == true_e) + { + block->size += next_block->size; + block_clear(next_block); + + node->next = next_node->next; + if (next_node->next) + next_node->next->prev = node; + node_clear(next_node); + SOSAL_PRINT(SOSAL_ZONE_HEAP, "Coalesced with next node\n"); + } + } + mutex_unlock(&heap->mutex); + return true_e; +} + +bool_e heap_valid(heap_t *heap, void *addr) +{ + bool_e ret = false_e; + mutex_lock(&heap->mutex); + if (heap->raw) + { + uint8_t *a = heap->raw; + size_t s = heap->bytesTotal; + uint8_t *b = (uint8_t *)addr; + uint8_t *c = (uint8_t *)(a+s); + if (a <= b && b < c) + ret = true_e; + } + mutex_unlock(&heap->mutex); + return ret; +} + +bool_e heap_unittest_overfill(void *buffer, size_t size) +{ + bool_e ret = true_e; + heap_t h; + uint32_t align = 7; + size_t unitsize = (1< 0) { + ret = false_e; + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "heap fragmentation test; %u faiiures\n", failures); + } + return ret; +} + +bool_e heap_unittest_simple(void *buffer, size_t size) +{ +#define numBufs 10 + bool_e ret = true_e; + heap_t h; + uint32_t i = 0; + void *bufs[numBufs]; + size_t bufSizes[numBufs]; + + if (heap_init(&h, buffer, size, 7) == true_e) // 128 byte align + { + for (i = 0; i < numBufs; i++) + { + // all the allocations should fit + do { + bufSizes[i] = rand() % (size/numBufs); + } while (bufSizes[i] == 0); + bufs[i] = heap_alloc(&h, bufSizes[i]); + if (bufs[i] == NULL) + ret = false_e; + //SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Buf[%u]=%p for %u bytes\n", i, bufs[i], bufSizes[i]); + } + + for (i = 0; i < numBufs; i++) + { + if (bufs[i] != NULL && heap_valid(&h, bufs[i]) == false_e) + { + ret = false_e; + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "FAILED TO VALIDATE KNOWN GOOD BUFFER %p!\n", bufs[i]); + } + } + + for (i = 0; i < numBufs; i++) + { + if (heap_free(&h, bufs[i]) == false_e) + { + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "FAILED to free %p\n", bufs[i]); + ret = false_e; + } + } + + heap_deinit(&h); + } + else + ret = false_e; + return ret; +} + +bool_e heap_unittest(int argc __attribute__((unused)), + char *argv[] __attribute__((unused))) +{ + bool_e ret = true_e; + size_t size = 1<<20; + void *flatbuffer = calloc(1,size); + uint32_t i; + bool_e verbose = false_e; + if (flatbuffer) + { + if (heap_unittest_simple(flatbuffer, size) == false_e) + ret = false_e; + if (heap_unittest_iterations(flatbuffer, size) == false_e) + ret = false_e; + if (heap_unittest_overfill(flatbuffer, size) == false_e) + ret = false_e; + if (heap_unittest_fragmentation(flatbuffer, size) == false_e) + ret = false_e; + free(flatbuffer); + flatbuffer = NULL; + } + if (verbose) + { + size_t sizes[] = {23, 14, 80, 129, 4097, 2304, 9027, 82734}; + for (i = 0; i < dimof(sizes); i++) + { + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "size "FMT_SIZE_T" is rounded to "FMT_SIZE_T"\n", sizes[i], block_size(128, sizes[i])); + } + } + return ret; +} + + +//****************************************************************************** +// END +//****************************************************************************** diff --git a/source/sosal/histogram.c b/source/sosal/histogram.c new file mode 100644 index 0000000..8a8282e --- /dev/null +++ b/source/sosal/histogram.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +bool_e histogram_init(histogram_t *histogram, uint32_t bins, int32_t min, int32_t max) +{ + bool_e ret = true_e; + histogram->binRange = (max - min)/bins; + if (((max-min) % bins) > 0) + histogram->binRange++; + histogram->numBins = bins; + histogram->min = min; + histogram->max = max; + histogram->bins = calloc(sizeof(uint32_t),bins); + if (histogram->bins == NULL) + ret = false_e; + return ret; +} + +void histogram_deinit(histogram_t *histogram) +{ + memset(histogram->bins, 0, histogram->numBins * sizeof(uint32_t)); +} + +void histogram_inc(histogram_t *histogram, int32_t value) +{ + // is it in range? + if (histogram->min <= value && value < histogram->max) + { + // get the index in the bins + uint32_t binIdx = (value - histogram->min)/histogram->binRange; + if (binIdx < histogram->numBins) + { + // increment the frequency + histogram->bins[binIdx]++; + } + } +} + +uint32_t histogram_get(histogram_t *histogram, int32_t value) +{ + uint32_t freq = 0; + // is it in range? + if (histogram->min <= value && value < histogram->max) + { + // get the index in the bins + uint32_t binIdx = (value - histogram->min)/histogram->binRange; + if (binIdx < histogram->numBins) + { + // get the frequency + freq = histogram->bins[binIdx]; + } + } + return freq; +} + +bool_e histogram_unittest(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) +{ + bool_e ret = true_e; + histogram_t histogram; + int32_t min = -100; + int32_t max = 100; + uint32_t bins = 17; + bool_e verbose = false_e; + + SOSAL_PRINT(SOSAL_ZONE_API, "histogram_unittest(%u, %p)\n", argc, argv); + if (histogram_init(&histogram, bins, min, max)) + { + int32_t count = abs(rand()) % 10000; + int32_t i = 0; + + for (i = 0; i < count; i++) + { + int32_t value = (rand()%(max-min)) + min; + histogram_inc(&histogram, value); + } + if (verbose) + { + for (i = min; i <= max; i++) + { + printf("Bin[%d] = %u\n", i, histogram_get(&histogram, i)); + } + } + histogram_deinit(&histogram); + } + + return ret; +} + + diff --git a/source/sosal/image.c b/source/sosal/image.c new file mode 100644 index 0000000..7bf266b --- /dev/null +++ b/source/sosal/image.c @@ -0,0 +1,750 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +//****************************************************************************** +// IMAGE API +//****************************************************************************** + +static fourcc_t supportedColors[] = { + FOURCC_RGB, + FOURCC_BGR, + FOURCC_Y800, + FOURCC_UYVY, + FOURCC_YUY2, + FOURCC_NV12, + FOURCC_RGBP, + FOURCC_YU24, + FOURCC_YV24, +}; + +uint8_t saturate_to_uint8(int32_t a) +{ + if (a > 255) + a = 255; + if (a < 0) + a = 0; + return (uint8_t)a; +} + +bool_e image_query_format(fourcc_t color) +{ + uint32_t i = 0; + for (i = 0; i < dimof(supportedColors); i++) + if (supportedColors[i] == color) + return true_e; + if (i == dimof(supportedColors)) + return false_e; + else + return true_e; +} + +void yuv_to_rgb_pixel(uint8_t y, uint8_t cb, uint8_t cr, uint8_t *r, uint8_t *g, uint8_t *b) +{ + *r = saturate_to_uint8((int32_t)(1.164*(double)((int32_t)y - 16) + 1.596*(double)((int32_t)cb - 128))); + *g = saturate_to_uint8((int32_t)(1.164*(double)((int32_t)y - 16) - 0.813*(double)((int32_t)cr - 128) - 0.391*(double)((int32_t)cb - 128))); + *b = saturate_to_uint8((int32_t)(1.164*(double)((int32_t)y - 16) + 2.018*(double)((int32_t)cr - 128))); +} + +void rgb_to_yuv_pixel(uint8_t r, uint8_t g, uint8_t b, uint8_t *y, uint8_t *u, uint8_t *v) +{ + *y = saturate_to_uint8(((int32_t)(0.257*(double)r + 0.504*(double)g + 0.098*(double)b) + 16)); + *u = saturate_to_uint8(((int32_t)(-0.148*(double)r - 0.291*(double)g + 0.439*(double)b) + 128)); + *v = saturate_to_uint8(((int32_t)(0.439*(double)r - 0.368*(double) - 0.071*(double)b) + 128)); +} + +void image_free(image_t **pimg) +{ + if (pimg) + { + image_t *img = *pimg; + if (img) + { + memset(img, 0, sizeof(image_t)); + free(img); + } + *pimg = NULL; + } +} + +image_t *image_allocate(uint32_t width, uint32_t height, fourcc_t color) +{ + image_t *img = (image_t *)calloc(1, sizeof(image_t)); + if (img) + { + uint32_t p; + img->color = color; + switch (color) + { + // easy planar formats + case FOURCC_RGBP: + case FOURCC_YU24: + case FOURCC_YV24: + img->numPlanes = 3; + for (p = 0; p < img->numPlanes; p++) + { + img->plane[p].xdim = width; + img->plane[p].ydim = height; + img->plane[p].xstep = 1; + img->plane[p].xscale = 1; + img->plane[p].yscale = 1; + img->plane[p].xstride = 1; + img->plane[p].ystride = img->plane[p].xdim * img->plane[p].xstride; + img->plane[p].numBytes = img->plane[p].ydim * img->plane[p].ystride; + //img->plane[p].ptr = calloc(1, img->plane[p].numBytes); + } + break; + case FOURCC_BGR: + case FOURCC_RGB: + img->numPlanes = 1; + img->plane[0].xdim = width; + img->plane[0].ydim = height; + img->plane[0].xstep = 1; + img->plane[0].xscale = 1; + img->plane[0].yscale = 1; + img->plane[0].xstride = 3; + img->plane[0].ystride = img->plane[0].xdim * img->plane[0].xstride; + img->plane[0].numBytes = img->plane[0].ydim * img->plane[0].ystride; + //img->plane[0].ptr = calloc(1, img->plane[0].numBytes); + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + img->numPlanes = 1; + img->plane[0].xdim = width; + img->plane[0].ydim = height; + img->plane[0].xstep = 2; // macro pixel! + img->plane[0].xscale = 1; + img->plane[0].yscale = 1; + img->plane[0].xstride = 2; + img->plane[0].ystride = img->plane[0].xdim * img->plane[0].xstride; + img->plane[0].numBytes = img->plane[0].ydim * img->plane[0].ystride; + //img->plane[0].ptr = calloc(1, img->plane[0].numBytes); + break; + case FOURCC_Y800: + img->numPlanes = 1; + img->plane[0].xdim = width; + img->plane[0].ydim = height; + img->plane[0].xstep = 1; + img->plane[0].xscale = 1; + img->plane[0].yscale = 1; + img->plane[0].xstride = 1; + img->plane[0].ystride = img->plane[0].xdim * img->plane[0].xstride; + img->plane[0].numBytes = img->plane[0].ydim * img->plane[0].ystride; + //img->plane[0].ptr = calloc(1, img->plane[0].numBytes); + break; + case FOURCC_NV12: /// @todo should this remain in a single buffer, just like DVP_Image_t? + img->numPlanes = 2; + img->plane[0].xdim = width; + img->plane[0].ydim = height; + img->plane[0].xstep = 1; + img->plane[0].xscale = 1; + img->plane[0].yscale = 1; + img->plane[0].xstride = 1; + img->plane[0].ystride = img->plane[0].xdim * img->plane[0].xstride; + img->plane[0].numBytes = img->plane[0].ydim * img->plane[0].ystride; + img->plane[1].xdim = width; + img->plane[1].ydim = height; + img->plane[1].xstep = 1; + img->plane[1].xscale = 2; + img->plane[1].yscale = 2; + img->plane[1].xstride = 2; + img->plane[1].ystride = img->plane[1].xdim * img->plane[1].xstride; + img->plane[1].numBytes = img->plane[1].ydim * img->plane[1].ystride; + //img->plane[0].ptr = calloc(1, img->plane[0].numBytes + img->plane[1].numBytes); + //img->plane[1].ptr = &img->plane[0].ptr[img->plane[0].ydim * img->plane[0].ystride]; + break; + case FOURCC_IYUV: + case FOURCC_YV12: + img->numPlanes = 3; + img->plane[0].xdim = width; + img->plane[0].ydim = width; + img->plane[0].xstep = 1; + img->plane[0].xscale = 1; + img->plane[0].yscale = 1; + img->plane[0].xstride = 1; + img->plane[0].ystride = img->plane[0].xdim * img->plane[0].xstride; + img->plane[0].numBytes = img->plane[0].ydim * img->plane[0].ystride; + img->plane[1].xdim = width/2; + img->plane[1].ydim = width/2; + img->plane[1].xstep = 1; + img->plane[1].xscale = 2; + img->plane[1].yscale = 2; + img->plane[1].xstride = 1; + img->plane[1].ystride = img->plane[1].xdim * img->plane[1].xstride; + img->plane[1].numBytes = img->plane[1].ydim * img->plane[1].ystride; + img->plane[2].xdim = width/2; + img->plane[2].ydim = width/2; + img->plane[2].xstep = 1; + img->plane[2].xscale = 2; + img->plane[2].yscale = 2; + img->plane[2].xstride = 1; + img->plane[2].ystride = img->plane[2].xdim * img->plane[2].xstride; + img->plane[2].numBytes = img->plane[2].ydim * img->plane[2].ystride; + break; + } + } + return img; +} + +void image_unback(image_t *img) +{ + if (img) + { + uint32_t p; + if (img->color != FOURCC_NV12) + { + for (p = 0; p < img->numPlanes; p++) + { + free(img->plane[p].ptr); + } + } + else + { + // NV12 has it's second plane as a calcuated pointer from the first + free(img->plane[0].ptr); + } + } +} + +bool_e image_back(image_t *img) +{ + bool_e allocated = true_e; + if (img) + { + uint32_t p; + if (img->color != FOURCC_NV12) + { + for (p = 0; p < img->numPlanes; p++) { + img->plane[p].ptr = calloc(1, img->plane[p].numBytes); + if (img->plane[p].ptr == NULL) + allocated = false_e; + } + } + else + { + img->plane[0].ptr = calloc(1, img->plane[0].numBytes + img->plane[1].numBytes); + if (img->plane[0].ptr == NULL) + allocated = false_e; + else + img->plane[1].ptr = &img->plane[0].ptr[img->plane[0].ydim * img->plane[0].ystride]; + } + } + return allocated; +} + +/** + * If RGB data, a=R, b=G, c=B + * If YUV data, a=Y, b=U, c=V + */ +void image_fill(image_t *img, uint8_t a, uint8_t b, uint8_t c) +{ + uint32_t x,y,p; + uint8_t *ptr = NULL; + if (img->color == FOURCC_BGR) + { + for (p = 0; p < img->numPlanes; p++) + { + for (y = 0; y < img->plane[p].ydim; y++) + { + for (x = 0; x < img->plane[p].xdim; x+=img->plane[p].xstep) + { + ptr = image_pixel(img, p, x, y); + ptr[0] = c; + ptr[1] = b; + ptr[2] = a; + } + } + } + } + else if (img->color == FOURCC_RGB) + { + for (p = 0; p < img->numPlanes; p++) + { + for (y = 0; y < img->plane[p].ydim; y++) + { + for (x = 0; x < img->plane[p].xdim; x+=img->plane[p].xstep) + { + ptr = image_pixel(img, p, x, y); + ptr[0] = a; + ptr[1] = b; + ptr[2] = c; + } + } + } + } + else if (img->color == FOURCC_UYVY) + { + for (p = 0; p < img->numPlanes; p++) + { + for (y = 0; y < img->plane[p].ydim; y++) + { + for (x = 0; x < img->plane[p].xdim; x+=img->plane[p].xstep) + { + ptr = image_pixel(img, p, x, y); + ptr[0] = b; + ptr[1] = a; + ptr[2] = c; + ptr[3] = a; + } + } + } + } + else if (img->color == FOURCC_YUY2) + { + for (p = 0; p < img->numPlanes; p++) + { + for (y = 0; y < img->plane[p].ydim; y++) + { + for (x = 0; x < img->plane[p].xdim; x+=img->plane[p].xstep) + { + ptr = image_pixel(img, p, x, y); + ptr[0] = a; + ptr[1] = b; + ptr[2] = a; + ptr[3] = c; + } + } + } + } + else if (img->color == FOURCC_NV12) + { + for (y = 0; y < img->plane[0].ydim; y++) + { + for (x = 0; x < img->plane[0].xdim; x+=img->plane[0].xstep) + { + ptr = image_pixel(img, 0, x, y); + *ptr = a; + } + } + for (y = 0; y < img->plane[1].ydim; y++) + { + for (x = 0; x < img->plane[1].xdim; x+=img->plane[1].xstep) + { + ptr = image_pixel(img, 1, x, y); + ptr[0] = b; + ptr[1] = c; + } + } + } + else if (img->color == FOURCC_Y800) + { + for (y = 0; y < img->plane[0].ydim; y++) + { + for (x = 0; x < img->plane[0].xdim; x+=img->plane[0].xstep) + { + ptr = image_pixel(img, 0, x, y); + *ptr = a; + } + } + } +} + +uint32_t image_copy(image_t *dst, image_t *src) +{ + if (dst && src && dst->color == src->color) + { + uint32_t p,y,i,l,b=0; + for (p = 0; p < dst->numPlanes && p < src->numPlanes; p++) + { + for (y = 0; y < dst->plane[p].ydim; y++) + { + l = src->plane[p].xstride * src->plane[p].xdim; + i = (y * src->plane[p].ystride); + memcpy(&dst->plane[p].ptr[i], &src->plane[p].ptr[i], l); + b += l; + } + } + return b; + } + else + return 0; +} + +void image_convert(image_t *dst, image_t *src) +{ + if (dst && src) + { + if (dst->color == src->color) + image_copy(dst, src); + else + { + uint32_t x,y; + if (dst->color == FOURCC_BGR && src->color == FOURCC_UYVY) + { + for (y = 0; y < src->plane[0].ydim; y++) { + for (x = 0; x < src->plane[0].xdim; x+=src->plane[0].xstep) { + uint8_t *uyvy = image_pixel(src, 0, x, y); + uint8_t *bgr = image_pixel(dst, 0, x, y); + yuv_to_rgb_pixel(uyvy[1], uyvy[0], uyvy[2], + &bgr[2], &bgr[1], &bgr[0]); + yuv_to_rgb_pixel(uyvy[3], uyvy[0], uyvy[2], + &bgr[5], &bgr[4], &bgr[3]); + + } + } + } + else if (dst->color == FOURCC_BGR && src->color == FOURCC_YUY2) + { + for (y = 0; y < src->plane[0].ydim; y++) { + for (x = 0; x < src->plane[0].xdim; x+=src->plane[0].xstep) { + uint8_t *yuyv = image_pixel(src, 0, x, y); + uint8_t *bgr = image_pixel(dst, 0, x, y); + yuv_to_rgb_pixel(yuyv[0], yuyv[1], yuyv[3], + &bgr[2], &bgr[1], &bgr[0]); + yuv_to_rgb_pixel(yuyv[2], yuyv[1], yuyv[3], + &bgr[5], &bgr[4], &bgr[3]); + } + } + } + else if (dst->color == FOURCC_BGR && src->color == FOURCC_NV12) + { + for (y = 0; y < src->plane[0].ydim; y++) { + for (x = 0; x < src->plane[0].xdim; x+=src->plane[0].xstep) { + uint8_t *luma = image_pixel(src, 0, x, y); + uint8_t *uv = image_pixel(src, 1, x, y); + uint8_t *bgr = image_pixel(dst, 0, x, y); + yuv_to_rgb_pixel(luma[0], uv[0], uv[1], + &bgr[2], &bgr[1], &bgr[0]); + } + } + } + else if (dst->color == FOURCC_UYVY && src->color == FOURCC_NV12) + { + for (y = 0; y < src->plane[0].ydim; y++) { + for (x = 0; x < src->plane[0].xdim; x+=dst->plane[0].xstep) { + uint8_t *luma = image_pixel(src, 0, x, y); + uint8_t *uv = image_pixel(src, 1, x, y); + uint8_t *uyvy = image_pixel(dst, 0, x, y); + uyvy[0] = uv[0]; + uyvy[1] = luma[0]; + uyvy[2] = uv[1]; + uyvy[3] = luma[1]; + } + } + } + else if (dst->color == FOURCC_BGR && (src->color == FOURCC_YU24 || src->color == FOURCC_YV24)) + { + uint32_t p1 = 1, p2 = 2; + if (src->color == FOURCC_YV24) { + p1 = 2; + p2 = 1; + } + for (y = 0; y < src->plane[0].ydim; y++) { + for (x = 0; x < src->plane[0].xdim; x+=src->plane[0].xstep) { + uint8_t *luma = image_pixel(src, 0, x, y); + uint8_t *cb = image_pixel(src, p1, x, y); + uint8_t *cr = image_pixel(src, p2, x, y); + uint8_t *bgr = image_pixel(dst, 0, x, y); + yuv_to_rgb_pixel(luma[0], cb[0], cr[0], + &bgr[2], &bgr[1], &bgr[0]); + } + } + } + else if (dst->color == FOURCC_UYVY && (src->color == FOURCC_YU24 || src->color == FOURCC_YV24)) + { + uint32_t p1 = 1, p2 = 2; + if (src->color == FOURCC_YV24) { + p1 = 2; + p2 = 1; + } + for (y = 0; y < src->plane[0].ydim; y++) { + for (x = 0; x < src->plane[0].xdim; x+=dst->plane[0].xstep) { + uint8_t *luma = image_pixel(src, 0, x, y); + uint8_t *cb = image_pixel(src, p1, x, y); + uint8_t *cr = image_pixel(src, p2, x, y); + uint8_t *uyvy = image_pixel(dst, 0, x, y); + uyvy[0] = (cb[0] + cb[1])/2; + uyvy[1] = luma[0]; + uyvy[2] = (cr[0] + cr[1])/2; + uyvy[3] = luma[1]; + } + } + } + else if (dst->color == FOURCC_BGR && src->color == FOURCC_Y800) + { + for (y = 0; y < src->plane[0].ydim; y++) { + for (x = 0; x < src->plane[0].xdim; x+=src->plane[0].xstep) { + uint8_t *luma = image_pixel(src, 0, x, y); + uint8_t *bgr = image_pixel(dst, 0, x, y); + yuv_to_rgb_pixel(luma[0], 128, 128, + &bgr[2], &bgr[1], &bgr[0]); + } + } + } + else if (dst->color == FOURCC_BGR && src->color == FOURCC_RGB) + { + for (y = 0; y < src->plane[0].ydim; y++) { + for (x = 0; x < src->plane[0].xdim; x+=src->plane[0].xstep) { + uint8_t *rgb = image_pixel(src, 0, x, y); + uint8_t *bgr = image_pixel(dst, 0, x, y); + bgr[0] = rgb[2]; + bgr[1] = rgb[1]; + bgr[2] = rgb[0]; + } + } + } + else if (dst->color == FOURCC_UYVY && src->color == FOURCC_RGB) + { + for (y = 0; y < src->plane[0].ydim; y++) { + for (x = 0; x < src->plane[0].xdim; x+=src->plane[0].xstep*2) { //macro pixel + uint8_t *rgb = image_pixel(src, 0, x, y); + uint8_t *uyvy = image_pixel(dst, 0, x, y); + uint8_t u0,v0,u1,v1; + uint32_t ux, vx; + rgb_to_yuv_pixel(rgb[0], rgb[1], rgb[2], + &uyvy[1], &u0, &v0); + rgb_to_yuv_pixel(rgb[3], rgb[4], rgb[5], + &uyvy[3], &u1, &v1); + ux = (u0&0xFF); ux += (u1&0xFF); ux >>= 1; + vx = (v0&0xFF); vx += (v1&0xFF); vx >>= 1; + uyvy[0] = saturate_to_uint8(ux); + uyvy[2] = saturate_to_uint8(vx); + //printf("u0 = %u u1 = %u ux = %u\n", u0, u1, ux); + //printf("v0 = %u v1 = %u vx = %u\n", v0, v1, vx); + } + } + } + else if (dst->color == FOURCC_NV12 && src->color == FOURCC_RGB) + { + for (y = 0; y < src->plane[0].ydim; y++) { + for (x = 0; x < src->plane[0].xdim; x+=src->plane[0].xstep) { + uint8_t *rgb = image_pixel(src, 0, x, y); + uint8_t *luma = image_pixel(dst, 0, x, y); + uint8_t *uv = image_pixel(dst, 1, x, y); + rgb_to_yuv_pixel(rgb[0], rgb[1], rgb[2], + &luma[0], &uv[0], &uv[1]); + } + } + } + else if (dst->color == FOURCC_UYVY && src->color == FOURCC_BGR) + { + for (y = 0; y < src->plane[0].ydim; y++) { + for (x = 0; x < src->plane[0].xdim; x+=src->plane[0].xstep*2) { //macro pixel + uint8_t *bgr = image_pixel(src, 0, x, y); + uint8_t *uyvy = image_pixel(dst, 0, x, y); + uint8_t u0,v0,u1,v1; + uint32_t ux, vx; + rgb_to_yuv_pixel(bgr[2], bgr[1], bgr[0], + &uyvy[1], &u0, &v0); + rgb_to_yuv_pixel(bgr[5], bgr[4], bgr[3], + &uyvy[3], &u1, &v1); + ux = (u0&0xFF); ux += (u1&0xFF); ux >>= 1; + vx = (v0&0xFF); vx += (v1&0xFF); vx >>= 1; + uyvy[0] = saturate_to_uint8(ux); + uyvy[2] = saturate_to_uint8(vx); + } + } + } + else if (dst->color == FOURCC_NV12 && src->color == FOURCC_BGR) + { + for (y = 0; y < src->plane[0].ydim; y+=2) { + for (x = 0; x < src->plane[0].xdim; x+=2) { + + uint8_t *bgr0 = image_pixel(src, 0, x, y); + uint8_t *bgr1 = image_pixel(dst, 0, x+1, y); + uint8_t *bgr2 = image_pixel(dst, 0, x, y+1); + uint8_t *bgr3 = image_pixel(dst, 0, x+1, y+1); + + uint8_t *l0 = image_pixel(dst, 0, x, y); + uint8_t *l1 = image_pixel(dst, 0, x+1, y); + uint8_t *l2 = image_pixel(dst, 0, x, y+1); + uint8_t *l3 = image_pixel(dst, 0, x+1, y+1); + + uint8_t *uv = image_pixel(dst, 1, x, y); + + uint8_t u[4]; + uint8_t v[4]; + + rgb_to_yuv_pixel(bgr0[2], bgr0[1], bgr0[0], + &l0[0], &u[0], &v[0]); + rgb_to_yuv_pixel(bgr1[2], bgr1[1], bgr1[0], + &l1[0], &u[1], &v[1]); + rgb_to_yuv_pixel(bgr2[2], bgr2[1], bgr2[0], + &l2[0], &u[2], &v[2]); + rgb_to_yuv_pixel(bgr2[2], bgr3[1], bgr3[0], + &l3[0], &u[3], &v[3]); + + uv[0] = (u[0] + u[1] + u[2] + u[3])/4; + uv[1] = (v[0] + v[1] + v[2] + v[3])/4; + + } + } + } + else if (dst->color == FOURCC_IYUV && src->color == FOURCC_BGR) + { + for (y = 0; y < src->plane[0].ydim; y+=2) { + for (x = 0; x < src->plane[0].xdim; x+=2) { + + uint8_t *bgr0 = image_pixel(src, 0, x, y); + uint8_t *bgr1 = image_pixel(dst, 0, x+1, y); + uint8_t *bgr2 = image_pixel(dst, 0, x, y+1); + uint8_t *bgr3 = image_pixel(dst, 0, x+1, y+1); + + uint8_t *l0 = image_pixel(dst, 0, x, y); + uint8_t *l1 = image_pixel(dst, 0, x+1, y); + uint8_t *l2 = image_pixel(dst, 0, x, y+1); + uint8_t *l3 = image_pixel(dst, 0, x+1, y+1); + + uint8_t *us = image_pixel(dst, 1, x, y); + uint8_t *vs = image_pixel(dst, 2, x, y); + + uint8_t u[4]; + uint8_t v[4]; + + rgb_to_yuv_pixel(bgr0[2], bgr0[1], bgr0[0], + &l0[0], &u[0], &v[0]); + rgb_to_yuv_pixel(bgr1[2], bgr1[1], bgr1[0], + &l1[0], &u[1], &v[1]); + rgb_to_yuv_pixel(bgr2[2], bgr2[1], bgr2[0], + &l2[0], &u[2], &v[2]); + rgb_to_yuv_pixel(bgr2[2], bgr3[1], bgr3[0], + &l3[0], &u[3], &v[3]); + + us[0] = (u[0] + u[1] + u[2] + u[3])/4; + vs[1] = (v[0] + v[1] + v[2] + v[3])/4; + + } + } + } + else if (dst->color == FOURCC_YV12 && src->color == FOURCC_BGR) + { + for (y = 0; y < src->plane[0].ydim; y+=2) { + for (x = 0; x < src->plane[0].xdim; x+=2) { + + uint8_t *bgr0 = image_pixel(src, 0, x, y); + uint8_t *bgr1 = image_pixel(dst, 0, x+1, y); + uint8_t *bgr2 = image_pixel(dst, 0, x, y+1); + uint8_t *bgr3 = image_pixel(dst, 0, x+1, y+1); + + uint8_t *l0 = image_pixel(dst, 0, x, y); + uint8_t *l1 = image_pixel(dst, 0, x+1, y); + uint8_t *l2 = image_pixel(dst, 0, x, y+1); + uint8_t *l3 = image_pixel(dst, 0, x+1, y+1); + + uint8_t *us = image_pixel(dst, 2, x, y); + uint8_t *vs = image_pixel(dst, 1, x, y); + + uint8_t u[4]; + uint8_t v[4]; + + rgb_to_yuv_pixel(bgr0[2], bgr0[1], bgr0[0], + &l0[0], &u[0], &v[0]); + rgb_to_yuv_pixel(bgr1[2], bgr1[1], bgr1[0], + &l1[0], &u[1], &v[1]); + rgb_to_yuv_pixel(bgr2[2], bgr2[1], bgr2[0], + &l2[0], &u[2], &v[2]); + rgb_to_yuv_pixel(bgr2[2], bgr3[1], bgr3[0], + &l3[0], &u[3], &v[3]); + + us[0] = (u[0] + u[1] + u[2] + u[3])/4; + vs[1] = (v[0] + v[1] + v[2] + v[3])/4; + + } + } + } + else if (dst->color == FOURCC_YU24 && src->color == FOURCC_NV12) + { + for (y = 0; y < src->plane[0].ydim; y+=2) { + for (x = 0; x < src->plane[0].xdim; x+=src->plane[0].xstep*2) { + int32_t str = src->plane[0].ystride; + uint8_t *l0 = image_pixel(src, 0, x, y); + uint8_t *uv = image_pixel(src, 1, x, y); + uint8_t *lo = image_pixel(dst, 0, x, y); + uint8_t *uo = image_pixel(dst, 1, x, y); + uint8_t *vo = image_pixel(dst, 2, x, y); + lo[0] = (l0[0] + l0[1] + l0[str] + l0[str+1]) >> 2; + uo[0] = uv[0]; + vo[0] = uv[1]; + } + } + } + else if (dst->color == FOURCC_YV24 && src->color == FOURCC_NV12) + { + for (y = 0; y < src->plane[0].ydim; y+=2) { + for (x = 0; x < src->plane[0].xdim; x+=src->plane[0].xstep*2) { + int32_t str = src->plane[0].ystride; + uint8_t *l0 = image_pixel(src, 0, x, y); + uint8_t *uv = image_pixel(src, 1, x, y); + uint8_t *lo = image_pixel(dst, 0, x, y); + uint8_t *uo = image_pixel(dst, 2, x, y); + uint8_t *vo = image_pixel(dst, 1, x, y); + lo[0] = (l0[0] + l0[1] + l0[str] + l0[str+1]) >> 2; + uo[0] = uv[0]; + vo[0] = uv[1]; + } + } + } + else if (dst->color == FOURCC_RGBP && (src->color == FOURCC_YU24 || src->color == FOURCC_YV24)) + { + uint32_t p1 = 1, p2 = 2; + if (src->color == FOURCC_YV24) { + p1 = 2; + p2 = 1; + } + for (y = 0; y < src->plane[0].ydim; y++) { + for (x = 0; x < src->plane[0].xdim; x+=src->plane[0].xstep) { + uint8_t *luma = image_pixel(src, 0, x, y); + uint8_t *cb = image_pixel(src, p1, x, y); + uint8_t *cr = image_pixel(src, p2, x, y); + uint8_t *r = image_pixel(dst, 0, x, y); + uint8_t *g = image_pixel(dst, 1, x, y); + uint8_t *b = image_pixel(dst, 2, x, y); + yuv_to_rgb_pixel(luma[0], cb[0], cr[0], + r, g, b); + } + } + } + else if (dst->color == FOURCC_UYVY && src->color == FOURCC_Y800) + { + for (y = 0; y < dst->plane[0].ydim; y++) { + for (x = 0; x < dst->plane[0].xdim; x+=dst->plane[0].xstep) { + uint8_t *luma = image_pixel(src, 0, x, y); + uint8_t *uyvy = image_pixel(dst, 0, x, y); + uyvy[0] = 0x80; + uyvy[1] = luma[0]; + uyvy[2] = 0x80; + uyvy[3] = luma[1]; + } + } + } + else + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "NO CONVERSION FROM 0x%08x to 0x%08x\n", src->color, dst->color); + } + } + } +} + +void image_print(image_t *img) +{ + uint32_t p = 0; + SOSAL_PRINT(SOSAL_ZONE_IMAGE, "image_t %p %s %u planes\n", img, fourcctostr(img->color), img->numPlanes); + for (p = 0; p < img->numPlanes; p++) + { + SOSAL_PRINT(SOSAL_ZONE_IMAGE, "\t%p %ux%u step:%u, stride:%dx%d\n", + img->plane[p].ptr, + img->plane[p].xdim, + img->plane[p].ydim, + img->plane[p].xstep, + img->plane[p].xstride, + img->plane[p].ystride); + } +} + + diff --git a/source/sosal/ini.c b/source/sosal/ini.c new file mode 100644 index 0000000..13c3050 --- /dev/null +++ b/source/sosal/ini.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +typedef enum _ini_state_e { + INI_NONE, + INI_SEC, + INI_VAR, + INI_VAL, + INI_COM +} ini_state_e; + +int ini_parse(char *buffer, size_t len, ini_callback_f callback, ini_chars_e char_case, void *arg) +{ +#define clear(x) memset(x, 0, sizeof(x)) + ini_state_e last = INI_NONE, state = INI_NONE; + size_t i; + char c; + char section[255]; uint32_t s1 = 0; + char variable[255]; uint32_t s2 = 0; + char value[255]; uint32_t s3 = 0; + + SOSAL_PRINT(SOSAL_ZONE_INI, "Parsing buffer of "FMT_SIZE_T" characters for INI formatted settings\n", len); + + clear(variable); + clear(value); + strcpy(section, "GLOBAL"); + state = INI_SEC; + + for (i = 0; i < len; i++) { + last = state; + c = buffer[i]; + if (char_case == INI_UPPER) + { + if ('a' <= c && c <= 'z') + c = (c - 'a') + 'A'; + } + else if (char_case == INI_LOWER) + { + if ('A' <= c && c <= 'Z') + c = (c - 'A') + 'a'; + } + switch(c) { + case '#': case ';': state = INI_COM; break; + case '[': state = INI_SEC; s1 = 0; clear(section); clear(variable); clear(value); break; + case ']': state = INI_VAR; s2 = 0; clear(variable); clear(value); break; + case '=': state = INI_VAL; s3 = 0; clear(value); break; + case '\t': case ' ': case '\"': break; // do nothings + case '\n': case '\r': case '\0': + if (state == INI_VAL) { + if (section[0] && variable[0] && value[0]) { + callback(arg, section, variable, value); + clear(variable); s2 = 0; + clear(value); s3 = 0; + } + state = INI_VAR; + } + break; + default: + switch(state) { + case INI_NONE: case INI_COM: break; + case INI_SEC: if (s1 < sizeof(section)) section[s1++] = c; break; + case INI_VAR: if (s2 < sizeof(variable)) variable[s2++] = c; break; + case INI_VAL: if (s3 < sizeof(value)) value[s3++] = c; break; + default: break; + } + break; + } + //SOSAL_PRINT(SOSAL_ZONE_INI, "%c => %u (%u) section=%s var=%s val=%s\n", c, state, last, section, variable, value); + } + // if the file didn't end with a newline or linefeed + if (section[0] && variable[0] && value[0]) { + callback(arg, section, variable, value); + clear(variable); s2 = 0; + clear(value); s3 = 0; + } + return 0; +} + +static size_t flen(FILE *f) +{ + size_t cur = ftell(f); + size_t len = 0; + fseek(f, 0, SEEK_END); + len = ftell(f); + fseek(f, cur, SEEK_SET); + return len; +} + +static void print_ini(void *arg, char *section, char *variable, char *value) +{ + printf("%p [%s] %s = %s\n", arg, section, variable, value); +} + +bool_e ini_unittest(int argc, char *argv[]) +{ + if (argc > 1) + { + FILE *f = fopen(argv[1], "r"); + if (f) + { + size_t len = flen(f); + char * buffer = malloc(len); + if (buffer) + { + if (fread(buffer, len, sizeof(char), f) > 0) + { + ini_parse(buffer, len, print_ini, INI_NATURAL, NULL); + } + free(buffer); + } + fclose(f); + } + } else { + char *test = "[SECTION1]\n\rVARIABLE =\t\"VALUE\"\n\r#comment\n\r[section2]\n\rBOB=uncle\n\r"; + ini_parse(test, strlen(test), print_ini, INI_NATURAL, NULL); + } + return true_e; + +} + diff --git a/source/sosal/list.c b/source/sosal/list.c new file mode 100644 index 0000000..6b22f5d --- /dev/null +++ b/source/sosal/list.c @@ -0,0 +1,438 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +node_t *node_create(value_t data) +{ + node_t *node = calloc(1, sizeof(node_t)); + if (node) + node->data = data; + return node; +} + +value_t node_destroy(node_t *node) +{ + value_t data = 0; + if (node) + { + data = node->data; + free(node); + } + return data; +} + +// creates all the nodes, and puts them into the free list +list_t *list_create() +{ + return (list_t *)calloc(1,sizeof(list_t)); +} + +// deletes all the nodes and data structures +void list_destroy(list_t *list) +{ + if (list) + { + // delete all remaining items in the list (head first) + while (list_pop(list) != NULL); + // screw up the data + memset(list, 0xEF, sizeof(list_t)); + free(list); + } +} + +// adds the node to the tail of the list +void list_append(list_t *list, node_t *node) +{ + if (list == NULL || node == NULL) + return; + + if (list->tail != NULL) + { + assert(list->tail != node); + list->tail->next = node; + node->prev = list->tail; + } + else + { + node->prev = NULL; + list->head = node; + } + node->next = NULL; + list->tail = node; +} + +// subtracts from the tail of the list +node_t *list_trim(list_t *list) +{ + node_t *node = NULL; + + if (list == NULL) + return NULL; + + if (list->tail != NULL) + { + node = list->tail; + // try to detect a cycle + assert(node != list->tail->prev); + list->tail = list->tail->prev; + + if (list->tail != NULL) + list->tail->next = NULL; + else // tail is NULL + list->head = NULL; + + if (list->head == NULL) + assert(list->tail == NULL); + + node->prev = NULL; + node->next = NULL; + } + return (node); +} + +// adds to the head of the list +void list_push(list_t *list, node_t *node) +{ + if (list == NULL) + return; + + if (list->head != NULL) + { + assert(list->head != node); + list->head->prev = node; + node->next = list->head; + } + else + { + node->next = NULL; + list->tail = node; + } + node->prev = NULL; + list->head = node; +} + +// subtracts from the head of the list +node_t *list_pop(list_t *list) +{ + node_t *node = NULL; + + if (list == NULL) + return NULL; + + if (list->head != NULL) + { + node = list->head; + // try to detect a cycle + assert(node != list->head->next); + list->head = list->head->next; + + if (list->head != NULL) + list->head->prev = NULL; + else // head is now null + list->tail = NULL; + + if (list->tail == NULL) + assert(list->head == NULL); + + node->next = NULL; + node->prev = NULL; + } + return (node); +} + +// inserts anywhere in the list, based on a comparision algorithm, and an order +node_t *list_insert(list_t *list, + node_t *node, + node_compare_f compare, + bool_e sortAscending) +{ + node_t *n = NULL; + + if (list == NULL) + return NULL; + + if (list->head != NULL) + { + n = list->head; + while(n != NULL) + { + if (sortAscending) + { + // if node < n + if (compare(node, n) < 0) + { + // this can only really happen in the head case + node->next = n; + node->prev = n->prev; + if (n->prev != NULL) + n->prev->next = node; + n->prev = node; + + if (n == list->head) + list->head = node; + + return (node); + } + // if n <= node <= n->next + else if ((compare(n, node) <= 0) && (compare(node, n->next) <= 0)) + { + node->next = n->next; + node->prev = n; + if (n->next != NULL) + n->next->prev = node; + n->next = node; + + if (n == list->tail) + list->tail = node; + + return (node); + } + } + else + { + // if node > n + if (compare(node, n) > 0) + { + // this can only really happen in the head case + node->next = n; + node->prev = n->prev; + if (n->prev != NULL) + n->prev->next = node; + n->prev = node; + + if (n == list->head) + list->head = node; + + return (node); + } + // if n >= node >= n->next + else if ((compare(n, node) >= 0) && (compare(node, n->next) >= 0)) + { + node->next = n->next; + node->prev = n; + if (n->next != NULL) + n->next->prev = node; + n->next = node; + + if (n == list->tail) + list->tail = node; + + return (node); + } + } + + n = n->next; + } + } + else // there is no list + { + list->head = node; + list->tail = node; + node->prev = NULL; + node->next = NULL; + return (node); + } + return (NULL); +} + +node_t *list_extract(list_t *list, node_t *node) +{ + if (list == NULL || node == NULL) + return NULL; + + if (list->head == NULL || list->tail == NULL) + return NULL; // there are no nodes + + if (node->next == NULL && node->prev == NULL) + { + // only node + node = list_pop(list); + } + else if (node->next != NULL && node->prev == NULL) + { + // head + node = list_pop(list); + } + else if (node->next == NULL && node->prev != NULL) + { + // tail + node = list_trim(list); + } + else if (node->next != NULL && node->prev != NULL) + { + // middle + node->next->prev = node->prev; + node->prev->next = node->next; + } + node->next = NULL; + node->prev = NULL; + return node; +} + +// this removes the first node in which the compare function returns 0 +node_t *list_remove_match(list_t *list, + node_t *node, + node_compare_f compare) +{ + if (list != NULL) + { + // find the node + node_t *temp = list_search(list, node, compare); + if (temp != NULL) + { + temp = list_extract(list, temp); + } + return (temp); + } + else + return NULL; +} + + +node_t *list_search(list_t *list, + node_t *node, + node_compare_f compare) +{ + if (list != NULL && node != NULL) + { + node_t *temp = list->head; + while (temp != NULL) + { + if (compare(temp, node) == 0) + break; + temp = temp->next; + } + return (temp); + } + else + return NULL; +} + +node_t *list_score(list_t *list, node_t *node, node_rate_f rate) +{ + if (list != NULL) + { + node_t *temp = list->head; + node_t *best = NULL; + score_t rating = 0; + + if (node == NULL) + return NULL; + while (temp != NULL) + { + score_t this_score = rate(temp, node); + SOSAL_PRINT(SOSAL_ZONE_LIST, "list_score(): Node %p had a score of %08x\n", temp, this_score); + if (rating < this_score) { + rating = this_score; + best = temp; + } + if (temp != temp->next) + temp = temp->next; + else + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! CYCLE IN LIST!\n"); + return NULL; + } + } + SOSAL_PRINT(SOSAL_ZONE_LIST, "list_score(): the best node was %p\n", best); + return best; + } + else + return NULL; +} + +size_t list_length(list_t *list) +{ + if (list != NULL) + { + size_t len = 0; + node_t *temp = list->head; + while (temp != NULL) + { + len++; + temp = temp->next; + } + return len; + } + else + return 0; +} + +void list_print(list_t *list, node_print_f print) +{ + if (list != NULL) + { + node_t *temp = list->head; + while (temp != NULL) + { + print(temp); + temp = temp->next; + } + } +} + +static int node_sorter(node_t *a, node_t *b) +{ + if (a && b) + { + if (a->data < b->data) + return -1; + else if (a->data == b->data) + return 0; + else if (a->data > b->data) + return 1; + } + return 0; +} + +bool_e list_unittest(int argc __attribute__((unused)), + char *argv[] __attribute__((unused))) +{ + bool_e ret = true_e; + uint32_t i; + node_t nodes[10]; + list_t *list = list_create(); + + for (i = 0; i < dimof(nodes); i++) + { + do { + nodes[i].data = (value_t)rand(); + } while (nodes[i].data == 0); + //printf("Inserting %u %p\n", i, nodes[i].data); + list_insert(list, &nodes[i], node_sorter, true_e); + } + + if (list_length(list) != dimof(nodes)) + ret = false_e; + + for (i = 0; i < dimof(nodes); i++) + { + list_pop(list); + } + + if (list->head != NULL || list->tail != NULL) + ret = false_e; + + list_destroy(list); + + return ret; +} + +/******************************************************************************* + * END + ******************************************************************************/ diff --git a/source/sosal/module.c b/source/sosal/module.c new file mode 100644 index 0000000..da44623 --- /dev/null +++ b/source/sosal/module.c @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#if defined(SYSBIOS_SL) + +extern static_module_table_t dvp_kgm_cpu_table; +extern static_module_table_t dvp_kgm_dsp_table; +extern static_module_table_t dvp_kgm_simcop_table; + +static static_module_table_t *static_modules[] = { + &dvp_kgm_cpu_table, + &dvp_kgm_dsp_table, + &dvp_kgm_simcop_table +}; + +#endif + +module_t module_load(const char *filename) +{ + module_t mod = 0; +#if defined(POSIX_DL) + mod = dlopen(filename, RTLD_NOW|RTLD_GLOBAL); +#elif defined(WIN32_DL) + mod = LoadLibrary(filename); +#elif defined(SYSBIOS_SL) + uint32_t m = 0; + for (m = 0; m < dimof(static_modules); m++) + { + if (strncmp(static_modules[m]->name, filename, MAX_PATH) == 0) + { + return static_modules[m]; + } + } +#endif + SOSAL_PRINT(SOSAL_ZONE_MODULE, "Loaded Module %s => %p\n", filename, mod); + return mod; +} + +symbol_t module_symbol(module_t mod, const char *symbol_name) +{ + symbol_t sym = NULL; +#if defined(POSIX_DL) + char *str = NULL; + sym = (symbol_t)dlsym(mod, symbol_name); + str = (char *)dlerror(); + if (str) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "%s %s\n", str, symbol_name); + sym = NULL; + } +#elif defined(WIN32_DL) + sym = (symbol_t)GetProcAddress(mod, symbol_name); +#elif defined(SYSBIOS_SL) + uint32_t s; + static_module_table_t *modtable = mod; + for (s = 0; s < modtable->numFunctions; s++) + { + if (strncmp(modtable->functions[s].name, symbol_name, MAX_PATH) == 0) + { + sym = modtable->functions[s].func_ptr; + break; + } + } +#endif + SOSAL_PRINT(SOSAL_ZONE_MODULE, "SYMBOL:%s => %p\n", symbol_name, sym); + return sym; +} + +char module_error_string[256]; + +char *module_error() +{ +#if defined(POSIX_DL) + return (char *)dlerror(); +#elif defined(WIN32_DL) + sprintf(module_error_string, "Error code %d\n", GetLastError()); + return module_error_string; +#elif defined(SYSBIOS_SL) + sprintf(module_error_string, "Error string unsupported on SYSBIOS\n"); + return module_error_string; +#endif +} + +void module_unload(module_t mod) +{ + SOSAL_PRINT(SOSAL_ZONE_MODULE, "Unloading Module %p\n", mod); +#if defined(POSIX_DL) + dlclose(mod); +#elif defined(WIN32_DL) + FreeLibrary(mod); +#elif defined(SYSBIOS_SL) + // do nothing. +#endif +} + +#ifdef MODULE_TEST +int main(int argc, char *argv[]) +#else +bool_e module_unittest(int argc, char *argv[]) +#endif +{ + bool_e ret = true_e; + module_t mods[20]; + symbol_t syms[20]; + int32_t idxArg = 0; + int32_t idxMod = -1; + int32_t idxSym = -1; + bool_e noClose = false_e; + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + + for (idxArg = 1, idxMod = 0; idxArg < argc && idxMod < (int32_t)dimof(mods); idxArg++) + { + if (strcmp(argv[idxArg], "-m") == 0 || strcmp(argv[idxArg], "-M") == 0) + { + char filename[MAX_PATH]; + if (argv[idxArg][1] == 'M') + sprintf(filename, MODULE_NAME("%s"), argv[idxArg+1]); + else + strcpy(filename, argv[idxArg+1]); + mods[++idxMod] = module_load(filename); + if (mods[idxMod] == NULL) + { + printf("Error loading module, %s\n", module_error()); + ret = false_e; + continue; + } + printf("Loaded %s (%p[%d])\n", argv[idxArg+1], mods[idxMod], idxMod); + } + if (strcmp(argv[idxArg], "-s") == 0) + { + printf("Trying to load symbol %s\n", argv[idxArg+1]); + syms[++idxSym] = module_symbol(mods[idxMod], argv[idxArg+1]); + if (syms[idxSym] == NULL) + { + printf("Error loading Symbol %s\n", argv[idxArg+1]); + ret = false_e; + continue; + } + printf("Loaded %s (%p[%d])\n", argv[idxArg+1], syms[idxSym], idxSym); + } + if (strcmp(argv[idxArg], "-nc") == 0) + noClose = true_e; + } + for ( ; idxMod >= 0; idxMod--) + { + if (noClose == false_e) + { + printf("Attempting unload of %p[%d]\n", mods[idxMod],idxMod); + module_unload(mods[idxMod]); + printf("Unloaded %p[%d]\n", mods[idxMod],idxMod); + } + } + printf("Completed all unloads\n"); + return ret; +} diff --git a/source/sosal/mutex.c b/source/sosal/mutex.c new file mode 100644 index 0000000..df1632c --- /dev/null +++ b/source/sosal/mutex.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +void mutex_init(mutex_t *m) +{ +#ifdef POSIX + pthread_mutex_init(m, NULL); +#elif defined(SYSBIOS) + /* m already allocated */ + m->key = NULL; + /*Creating a gate with default params (NULL)*/ + /* No calling of GateMutexPri_Params_init(¶ms); to prepare them */ + m->gate = GateMutexPri_create(NULL, NULL); +#else + InitializeCriticalSection(m); +#endif +} + +void mutex_deinit(mutex_t *m) +{ +#ifdef POSIX + pthread_mutex_destroy(m); +#elif defined(SYSBIOS) + /* Delete the mutex. */ + GateMutexPri_delete(&(m->gate)); + /* deallocation on the calling level */ +#else + DeleteCriticalSection(m); +#endif +} + +void mutex_lock(mutex_t *m) +{ +#ifdef POSIX + pthread_mutex_lock(m); +#elif defined(SYSBIOS) + m->key = GateMutexPri_enter(m->gate); +#else + EnterCriticalSection(m); +#endif +} + +void mutex_unlock(mutex_t *m) +{ +#ifdef POSIX + pthread_mutex_unlock(m); +#elif defined(SYSBIOS) + /* Release the mutex. */ + GateMutexPri_leave(m->gate, m->key); +#else + LeaveCriticalSection(m); +#endif +} + diff --git a/source/sosal/options.c b/source/sosal/options.c new file mode 100644 index 0000000..a9054f2 --- /dev/null +++ b/source/sosal/options.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +size_t option_process(int argc, char *argv[], option_t *opts, size_t numOpts) +{ + int i; + size_t j,c = 0; + for (i = 0; i < argc; i++) + { + for (j = 0; j < numOpts; j++) + { + if ((opts[j].short_switch && strcmp(opts[j].short_switch, argv[i]) == 0) || + (opts[j].long_switch && strcmp(opts[j].long_switch, argv[i]) == 0)) + { + switch (opts[j].type) + { + case OPTION_TYPE_BOOL: + *(bool_e *)opts[j].datum = true_e; + c++; + break; + case OPTION_TYPE_INT: + if (i+1 < argc && opts[j].size == sizeof(int)) { + i += 1; + sscanf(argv[i],"%d",(int *)opts[j].datum); + c++; + } + break; + case OPTION_TYPE_HEX: + if (i+1 < argc && opts[j].size == sizeof(uint32_t)) { + i += 1; + sscanf(argv[i],"%x",(uint32_t *)opts[j].datum); + c++; + } + break; + case OPTION_TYPE_FLOAT: + if (i+1 < argc && opts[j].size == sizeof(float)) { + i += 1; + sscanf(argv[i],"%f",(float *)opts[j].datum); + c++; + } + break; + case OPTION_TYPE_STRING: + if (i+1 < argc) { + i += 1; + strncpy(opts[j].datum, argv[i], opts[j].size); + c++; + } + break; + } + break; // process next argv + } + } + } + return c; +} + +static bool_e opt_toggle; +static int opt_int; +static uint32_t opt_hex; +static float opt_float; +static char opt_string[256]; +static option_t opts[] = { + {OPTION_TYPE_BOOL, &opt_toggle, sizeof(opt_toggle), "-t", "--toggle", "Toggles a Boolean"}, + {OPTION_TYPE_INT, &opt_int, sizeof(opt_int), "-i", "--integer", "An integer value"}, + {OPTION_TYPE_HEX, &opt_hex, sizeof(opt_hex), "-h", "--hex", "A 32 bit hexidecimal value"}, + {OPTION_TYPE_FLOAT, &opt_float, sizeof(opt_float), "-f", "--float", "A 32 bit floating point value"}, + {OPTION_TYPE_STRING, opt_string, 256, "-s", "--string", "A \"quoted\" character string"}, +}; +static size_t numOpts = dimof(opts); + +bool_e option_unittest(int argc, char *argv[]) +{ + opt_toggle = false_e; + opt_int = -42; + opt_hex = 0xdeadbeef; + opt_float = 3.1415f; + strcpy(opt_string, "This is a test string"); + option_process(argc, argv, opts, numOpts); + printf("opt_toggle = %d\n", opt_toggle); + printf("opt_int = %d\n", opt_int); + printf("opt_hex = %x\n", opt_hex); + printf("opt_float = %lf\n", opt_float); + printf("opt_string = %s\n", opt_string); + return true_e; +} + diff --git a/source/sosal/pipe.c b/source/sosal/pipe.c new file mode 100644 index 0000000..a6f50b7 --- /dev/null +++ b/source/sosal/pipe.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#ifdef POSIX + +void pipe_close(pipe_t **pp) +{ + if (pp) + { + pipe_t *p = *pp; + if (p) + { + close(p->fd[0]); + close(p->fd[1]); + free(p); + *pp = NULL; + } + } +} + +pipe_t *pipe_open(char *name __attribute__((unused))) +{ + pipe_t *p = (pipe_t *)calloc(1, sizeof(pipe_t)); + if (p) + { + SOSAL_PRINT(SOSAL_ZONE_PIPE, "Created pipe %s\n", name); + if (pipe(p->fd) < 0) + pipe_close(&p); + } + return p; +} + +uint32_t pipe_read(pipe_t *p, uint8_t *data, size_t len) +{ + ssize_t bytes = 0; + bytes = read(p->fd[0], data, len); + if (bytes < 0) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to read from pipe (errno=%d)\n", errno); + return 0; + } + else + { + return (uint32_t)bytes; + } +} + +uint32_t pipe_write(pipe_t *p, uint8_t *data, size_t len) +{ + ssize_t bytes = 0; + bytes = write(p->fd[1], data, len); + if (bytes < 0) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to write to pipe (errno=%d)\n", errno); + return 0; + } + else + { + return (uint32_t)bytes; + } + +} + +#endif + diff --git a/source/sosal/profiler.c b/source/sosal/profiler.c new file mode 100644 index 0000000..7499424 --- /dev/null +++ b/source/sosal/profiler.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +void profiler_clear(profiler_t *pprof) +{ + memset(pprof, 0, sizeof(profiler_t)); + pprof->rate = rtimer_freq(); + pprof->minTime = MAX_RTIMER_T; +} + +void profiler_start(profiler_t *pprof) +{ + if (pprof) { + pprof->tmpTime = rtimer_now(); + } +} + +void profiler_stop(profiler_t *pprof) +{ + if (pprof) + { + pprof->tmpTime = (rtimer_now() - pprof->tmpTime); + pprof->numTimes++; + if (pprof->minTime > pprof->tmpTime) + pprof->minTime = pprof->tmpTime; + if (pprof->maxTime < pprof->tmpTime) + pprof->maxTime = pprof->tmpTime; + pprof->sumTime += pprof->tmpTime; + pprof->avgTime = pprof->sumTime/pprof->numTimes; + } +} + diff --git a/source/sosal/pyuv.c b/source/sosal/pyuv.c new file mode 100644 index 0000000..98c42b6 --- /dev/null +++ b/source/sosal/pyuv.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +typedef struct _fourcc_names_t { + fourcc_t fourcc; + char *name; + char *ext; +} FOURCC_Name_t; + +FOURCC_Name_t fourccNames[] = { + {FOURCC_UYVY, "UYVY", "yuv"}, + {FOURCC_YUY2, "YUY2", "yuv"}, + {FOURCC_YVYU, "YVYU", "yuv"}, + //{FOURCC_VYUY, "VYUY", "yuv"}, + {FOURCC_YUV9, "P411", "yuv"}, + {FOURCC_YVU9, "P411", "yuv"}, + {FOURCC_YV12, "P420", "yuv"}, + {FOURCC_IYUV, "IYUV", "yuv"}, + {FOURCC_YU16, "P422", "yuv"}, + {FOURCC_YV16, "P422", "yuv"}, + {FOURCC_YU24, "P444", "yuv"}, + {FOURCC_YV24, "P444", "yuv"}, + {FOURCC_Y800, "P400", "bw"}, + {FOURCC_Y16, "P400_16b", "bw"}, + {FOURCC_Y32, "P400_32b", "bw"}, + {FOURCC_RGBP, "P444", "rgb"}, + {FOURCC_BGR, "I444", "rgb"}, + {FOURCC_HSLP, "P444", "hsl"}, + {FOURCC_RGBA, "I32", "rgba"}, + {FOURCC_NV12, "P400", "bw"}, + {FOURCC_NV21, "P400", "bw"}, + {FOURCC_RGB565, "I565", "rgb"}, + {FOURCC_BGR565, "I565", "rgb"}, +}; +unsigned int numFourccNames = dimof(fourccNames); + +char *PYUV_GetFileExtension(fourcc_t fourcc) +{ + unsigned int i = 0; + for (i = 0; i < numFourccNames; i++) + { + if (fourcc == fourccNames[i].fourcc) + return fourccNames[i].ext; + } + return NULL; +} + +char *PYUV_GetColorSpaceName(fourcc_t fourcc) +{ + unsigned int i = 0; + for (i = 0; i < numFourccNames; i++) + { + if (fourcc == fourccNames[i].fourcc) + return fourccNames[i].name; + } + return NULL; +} + +fourcc_t PYUV_GetColorSpace(char *name, char *ext) +{ + unsigned int i = 0; + for (i = 0; i < numFourccNames; i++) + { + if (strcmp(fourccNames[i].name, name) == 0 && strcmp(fourccNames[i].ext,ext) == 0) + return fourccNames[i].fourcc; + } + return FOURCC_Y800; +} + +void PYUV_GetFilename(char *filename, + char *path, + char *name, + unsigned int width, + unsigned int height, + unsigned int fps, + fourcc_t fourcc) +{ + unsigned int modHeight = height; + if(fourcc == FOURCC_NV12 || fourcc == FOURCC_NV21) + modHeight = height*3/2; + + sprintf(filename, "%s%s_%ux%u_%uHz_%s.%s", path, name, width, modHeight, fps, PYUV_GetColorSpaceName(fourcc), PYUV_GetFileExtension(fourcc)); +} + + diff --git a/source/sosal/queue.c b/source/sosal/queue.c new file mode 100644 index 0000000..efab922 --- /dev/null +++ b/source/sosal/queue.c @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +void queue_destroy(queue_t *q) +{ + if (q) + { + if (q->ringb) + ring_destroy(q->ringb); + event_deinit(&q->readEvent); + event_deinit(&q->writeEvent); + mutex_deinit(&q->access); + free(q); + } +} + +queue_t *queue_create(size_t numMsgs, size_t msgSize) +{ + queue_t *q = (queue_t *)calloc(1, sizeof(queue_t)); + if (q != NULL) + { + q->msgSize = msgSize; + q->numMsgs = numMsgs; + q->active = true_e; + q->popped = false_e; + mutex_init(&q->access); + event_init(&q->readEvent, false_e); + event_init(&q->writeEvent, false_e); + q->ringb = ring_create(msgSize * numMsgs); + if (q->ringb == NULL) + { + queue_destroy(q); + } + else + { + // initialize the events + event_set(&q->writeEvent); + event_reset(&q->readEvent); + } + } + return q; +} + +size_t queue_length(queue_t *q) +{ + size_t length = 0; + mutex_lock(&q->access); + length = q->msgCount; + mutex_unlock(&q->access); + return length; +} + +bool_e queue_write(queue_t *q, bool_e blocking, void *datum) +{ + bool_e ret = false_e; + size_t r = 0; + if (q && datum) + { + if (blocking == true_e) + { + SOSAL_PRINT(SOSAL_ZONE_QUEUE, "Waiting for Space in Queue %p to Write!\n", q); + do { + ret = event_wait(&q->writeEvent, EVENT_FOREVER); + if (ret == false_e) { + SOSAL_PRINT(SOSAL_ZONE_WARNING, "WARNING! Wait for event in queue writting returned false!\n"); + } else { + SOSAL_PRINT(SOSAL_ZONE_QUEUE, "Queue %p has been write signaled!\n",q); + } + } while (ret == false_e); + } + mutex_lock(&q->access); + if (q->active && !q->popped) + { + r = ring_write(q->ringb, datum, q->msgSize); + if (r == q->msgSize) + { + q->msgCount++; + ret = true_e; + } + else + { + ret = false_e; + } + if (q->ringb->numBytesFree > 0) { + event_set(&q->writeEvent); + } else if (q->ringb->numBytesFree == 0) { + event_reset(&q->writeEvent); + } + if (q->ringb->numBytesUsed > 0) { + event_set(&q->readEvent); + } + } + else if (q->popped == true_e) + ret = false_e; + mutex_unlock(&q->access); + } + return ret; +} + +bool_e queue_read(queue_t *q, bool_e blocking, void *datum) +{ + bool_e ret = false_e; + size_t r = 0; + if (q && datum) + { + if (blocking == true_e) + { + SOSAL_PRINT(SOSAL_ZONE_QUEUE, "Waiting for Data in Queue %p to Read!\n", q); + do { + ret = event_wait(&q->readEvent, EVENT_FOREVER); + if (ret == false_e) { + // some one else beat us to the data + SOSAL_PRINT(SOSAL_ZONE_WARNING, "WARNING! Wait for the read event in the queue returned false\n"); + } else { + SOSAL_PRINT(SOSAL_ZONE_QUEUE, "Queue %p has been read signaled!\n",q); + } + } while (ret == false_e); + } + mutex_lock(&q->access); + if (q->active && !q->popped) + { + r = ring_read(q->ringb, datum, q->msgSize); + if (r == q->msgSize) + { + q->msgCount--; + ret = true_e; + } + else + { + ret = false_e; + } + if (q->ringb->numBytesFree > 0) { + event_set(&q->writeEvent); + } + if (q->ringb->numBytesUsed > 0) { + event_set(&q->readEvent); + } else if (q->ringb->numBytesUsed == 0) { + event_reset(&q->readEvent); + } + } + else if (q->popped == true_e) + ret = false_e; + mutex_unlock(&q->access); + } + return ret; +} + +void queue_enable(queue_t *q) +{ + if (q) + { + mutex_lock(&q->access); + if (q->active == false_e) + { + if (q->ringb->numBytesFree > 0) { + event_set(&q->writeEvent); + } + if (q->ringb->numBytesUsed > 0) { + event_set(&q->readEvent); + } + q->active = true_e; + } + mutex_unlock(&q->access); + } +} + +void queue_disable(queue_t *q) +{ + if (q) + { + mutex_lock(&q->access); + if (q->active == true_e) + { + event_reset(&q->readEvent); + event_reset(&q->writeEvent); + q->active = false_e; + } + mutex_unlock(&q->access); + } +} + +void queue_pop(queue_t *q) +{ + if (q) + { + mutex_lock(&q->access); + + q->popped = true_e; + event_set(&q->readEvent); + event_set(&q->writeEvent); + + mutex_unlock(&q->access); + } +} + +queue_t *queue_reset(queue_t *q) +{ + if (q) + { + mutex_lock(&q->access); + q->active = true_e; + q->popped = false_e; + + ring_destroy(q->ringb); + q->ringb = ring_create(q->msgSize * q->numMsgs); + if (q->ringb == NULL) + { + queue_destroy(q); + q = NULL; + } + else + { + // initialize the events + event_set(&q->writeEvent); + event_reset(&q->readEvent); + } + mutex_unlock(&q->access); + } + return q; +} + +void queue_unpop(queue_t *q) +{ + if (q) + { + mutex_lock(&q->access); + q->popped = false_e; + event_reset(&q->readEvent); + event_reset(&q->writeEvent); + if (q->ringb->numBytesFree > 0) { + event_set(&q->writeEvent); + } + if (q->ringb->numBytesUsed > 0) { + event_set(&q->readEvent); + } + mutex_unlock(&q->access); + } +} + +bool_e queue_unittest(int argc __attribute__((unused)), + char *argv[] __attribute__((unused))) +{ + bool_e ret = true_e; + uint32_t i; + uint32_t values1[] = {1,4,8,3,2,0,4,2,99,1028,3393,203,4}; + uint32_t values2[dimof(values1)]; + queue_t *q = queue_create(dimof(values1), sizeof(uint32_t)); + if (q) + { + memset(values2, 0, sizeof(values2)); + for (i = 0; i < dimof(values1); i++) + queue_write(q, true_e, &values1[i]); + for (i = 0; i < dimof(values2); i++) + queue_read(q, true_e, &values2[i]); + + if (memcmp(values1, values2, sizeof(values1)) != 0) + ret = false_e; + + queue_destroy(q); + } + else + ret = false_e; + + return ret; +} + diff --git a/source/sosal/ring.c b/source/sosal/ring.c new file mode 100644 index 0000000..58530a7 --- /dev/null +++ b/source/sosal/ring.c @@ -0,0 +1,416 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#ifdef SYSOSAL +#include //for assert support +#endif + +ring_t *ring_create(size_t totalNumBytes) +{ + ring_t *rb = (ring_t *)calloc(1,sizeof(ring_t)); + if (rb == NULL) + return rb; + + rb->start = (uint8_t *)calloc(totalNumBytes, sizeof(uint8_t)); + if (rb->start == NULL) + { + free(rb); + return NULL; + } + + rb->totalNumBytes = totalNumBytes; + rb->front = rb->start; + rb->back = rb->start; + rb->end = &(rb->start[rb->totalNumBytes]); // this must the point PAST the + // end of the buffer! + rb->numBytesFree = totalNumBytes; + rb->numBytesUsed = 0; + return rb; +} + +void ring_destroy(ring_t *rb) +{ + if (rb == NULL) + return; + + // destroy the raw buffer + if (rb->start != NULL) + free(rb->start); + + // destroy the structure + if (rb != NULL) + free(rb); +} + +size_t ring_write(ring_t *rb, uint8_t *b, size_t len) +{ + size_t numBytesWritten = 0; + + // if I couldn't fit the data, don't write it. + if (len > rb->numBytesFree) { + return 0; + } + if (len == 1) + { + // since we have at least one byte free, we don't have to worry about + // the pointer problems associated with 1+ buffer copies + *rb->back++ = *b; + if (rb->back == rb->end) + rb->back = rb->start; + rb->numBytesUsed++; + rb->numBytesFree--; + return 1; + } + + // non-inverted (back is higher than front) + if (rb->back > rb->front) + { + size_t end_to_back = (rb->end - rb->back); + + if (end_to_back > len) + { + memcpy(rb->back,b,len); + rb->back += len; + rb->numBytesFree -= len; + rb->numBytesUsed += len; + numBytesWritten = len; + } + else + { + // this wraps the ring buffer around + size_t left_over = len - end_to_back; + + memcpy(rb->back,b,end_to_back); + rb->back = rb->start; + rb->numBytesFree -= end_to_back; + rb->numBytesUsed += end_to_back; + + if (left_over > 0) + { + memcpy(rb->back,&(b[end_to_back]),left_over); + rb->back += left_over; + rb->numBytesFree -= left_over; + rb->numBytesUsed += left_over; + } + numBytesWritten = len; + } + } + // inverted pointers (front is higher than back) ring has wrapped + else if (rb->front > rb->back) + { + size_t front_to_back = (rb->front - rb->back); + if(len <= front_to_back ) + { + memcpy(rb->back,b,len); + rb->back += len; + rb->numBytesFree -= len; + rb->numBytesUsed += len; + + numBytesWritten = len; + } + else + { + assert(len <= front_to_back); + } + } + else // they're equal + { + if (rb->numBytesFree == 0) + { + // buffer is full, we shouldn't have arrived here + assert(rb->numBytesFree != 0); + // impossible code path... + } + else if (rb->numBytesUsed == 0) + { + // completely empty + + if (len > rb->totalNumBytes) + { + // buffer can't fit in ring, should not have arrived here. + assert(len <= rb->totalNumBytes); + // impossible code path... + } + else if (len <= rb->totalNumBytes) + { + size_t end_to_back = (size_t)(rb->end - rb->back); + + if (len < end_to_back) + { + memcpy(rb->back,b,len); + rb->back += len; + rb->numBytesFree -= len; + rb->numBytesUsed += len; + numBytesWritten = len; + } + else + { + // this wraps the ring buffer around + size_t left_over = len - end_to_back; + + memcpy(rb->back,b,end_to_back); + rb->back = rb->start; + rb->numBytesFree -= end_to_back; + rb->numBytesUsed += end_to_back; + + if (left_over > 0) + { + memcpy(rb->back,&(b[end_to_back]),left_over); + rb->back += left_over; + rb->numBytesFree -= left_over; + rb->numBytesUsed += left_over; + } + + numBytesWritten = len; + } + } + } + else + { + // error + assert((rb->numBytesFree + rb->numBytesUsed) == rb->totalNumBytes); + // TODO if there is an error in the private data, reinitialize... + } + } + + // LeaveCriticalSection(&rb->cs); + + return numBytesWritten; +} + +size_t ring_read(ring_t *rb, uint8_t *b, size_t len) +{ + size_t numBytesRead = 0; + + if (rb->numBytesUsed == 0) { + // LeaveCriticalSection(&rb->cs); + return numBytesRead; + } + if (len == 1) + { + // since there is at least one byte in the ring, we don't have to worry + // about the complexities of the byte processing + *b = *rb->front++; + if (rb->front == rb->end) + rb->front = rb->start; + rb->numBytesUsed--; + rb->numBytesFree++; + return 1; + } + + // non-inverted + if (rb->back > rb->front) + { + size_t back_to_front = (rb->back - rb->front); + + if(len < back_to_front) + numBytesRead = len; + else + numBytesRead = back_to_front; + + memcpy(b,rb->front,numBytesRead); + rb->front += numBytesRead; + rb->numBytesFree += numBytesRead; + rb->numBytesUsed -= numBytesRead; + } + // inverted case (ring wrapped) + else if (rb->front > rb->back) + { + size_t end_to_front = (rb->end - rb->front); + if (len < end_to_front) + { + memcpy(b,rb->front,len); + rb->front += len; + rb->numBytesFree += len; + rb->numBytesUsed -= len; + numBytesRead = len; + } + else + { + size_t left_over = len - end_to_front; + size_t readLen = 0; + + memcpy(b,rb->front,end_to_front); + rb->front = rb->start; + rb->numBytesFree += end_to_front; + rb->numBytesUsed -= end_to_front; + + if (left_over > 0) + { + size_t back_to_start = (rb->back - rb->start); + if (left_over <= back_to_start) + readLen = left_over; + else + readLen = back_to_start; + if (readLen > 0) + { + memcpy(&(b[end_to_front]),rb->front,readLen); + rb->front += readLen; + rb->numBytesFree += readLen; + rb->numBytesUsed -= readLen; + } + } + numBytesRead = end_to_front + readLen; + } + } + else // they're equal + { + if (rb->numBytesFree == 0) + { + // full buffer + size_t end_to_front = (rb->end - rb->front); + size_t readLen = 0; + if (len < end_to_front) + { + memcpy(b,rb->front,len); + rb->front += len; + rb->numBytesFree += len; + rb->numBytesUsed -= len; + numBytesRead = len; + } + else + { + size_t left_over = len - end_to_front; + memcpy(b,rb->front,end_to_front); + rb->front = rb->start; + rb->numBytesFree += end_to_front; + rb->numBytesUsed -= end_to_front; + if (left_over > 0) + { + size_t back_to_start = (rb->back - rb->start); + if (left_over <= back_to_start) + readLen = left_over; + else + readLen = back_to_start; + + if (readLen > 0) + { + memcpy(&(b[end_to_front]),rb->front,readLen); + rb->front += readLen; + rb->numBytesFree += readLen; + rb->numBytesUsed -= readLen; + } + } + numBytesRead = end_to_front + readLen; + } + } + else if (rb->numBytesUsed == 0) + { + // empty buffer, we should not have gotten here + assert(rb->numBytesUsed != 0); + // impossible code path... + } + else + { + // error + assert((rb->numBytesFree + rb->numBytesUsed) == rb->totalNumBytes); + +#ifdef RINGB_PROACTIVE + // there are bytes left in the array, + // but we don't know how we skipped them. + // we have to assume that start, end and totalNumBytes are ok. + rb->numBytesFree = rb->totalNumBytes; + rb->numBytesUsed = 0; + rb->front = rb->start; + rb->back = rb->front; + numBytesRead = 0; +#endif + } + } + return numBytesRead; +} + +void ring_print(ring_t *rb) +{ + size_t i; + + printf("Ring Buffer:\n"); + printf("================================\n"); + printf("Total Size: "FMT_SIZE_T" byte(s)\n",rb->totalNumBytes); + printf(" Free Size: "FMT_SIZE_T" byte(s)\n",rb->numBytesFree); + printf(" Used Size: "FMT_SIZE_T" byte(s)\n",rb->numBytesUsed); + printf("Start Pointer: %p\n",rb->start); + printf(" End Pointer: %p\n",rb->end); + printf("Front Pointer: %p ["FMT_SIZE_T"]\n",rb->front,(rb->front-rb->start)); + printf(" Back Pointer: %p ["FMT_SIZE_T"]\n",rb->back,(rb->back-rb->start)); + + if (rb->back > rb->front) + { + uint8_t *tmp = rb->start; + for (i = 0; i < rb->totalNumBytes; i++) + { + if (tmp < rb->front) + printf("-- "); + else if (tmp < rb->back) + printf("%02x ",*tmp); + else + printf("-- "); + tmp++; + } + printf("\n"); + + assert(rb->numBytesFree > 0); + assert(rb->numBytesUsed > 0); + } + else if (rb->front > rb->back) + { + uint8_t *tmp = rb->start; + for (i = 0; i < rb->totalNumBytes; i++) + { + if (tmp < rb->back) + printf("%02x ",*tmp); + else if (tmp < rb->front) + printf("-- "); + else + printf("%02x ",*tmp); + tmp++; + } + printf("\n"); + + assert(rb->numBytesFree > 0); + assert(rb->numBytesUsed > 0); + } + else + { + if (rb->numBytesFree == 0) + { + uint8_t *tmp = rb->start; + for (i = 0; i < rb->totalNumBytes; i++) + { + printf("%02x ",*tmp); + tmp++; + } + printf("\n"); + + assert(rb->numBytesUsed == rb->totalNumBytes); + } + else if (rb->numBytesUsed == 0) + { + uint8_t *tmp = rb->start; + for (i = 0; i < rb->totalNumBytes; i++) + { + printf("-- "); + tmp++; + } + printf("\n"); + + assert(rb->numBytesFree == rb->totalNumBytes); + } + } +} + diff --git a/source/sosal/rpc_socket.c b/source/sosal/rpc_socket.c new file mode 100644 index 0000000..163f9e8 --- /dev/null +++ b/source/sosal/rpc_socket.c @@ -0,0 +1,523 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#if defined(SOSAL_RPC_SOCKET_API) + +static void rpc_socket_item_print(uint32_t index, rpc_socket_item_t *item) +{ + char buffer[MAX_PATH]; + if (item->item) + { + switch (item->type) + { + case RPC_SOCKET_TYPE_INT8: + { + int8_t c = *(int8_t *)item->item; + snprintf(buffer, MAX_PATH, "[%u] %d (0x%02x)", index, c, c); + break; + } + case RPC_SOCKET_TYPE_UINT8: + { + uint8_t c = *(uint8_t *)item->item; + snprintf(buffer, MAX_PATH, "[%u] %u (0x%02x)", index, c, c); + break; + } + case RPC_SOCKET_TYPE_INT16: + { + int16_t c = *(int16_t *)item->item; + snprintf(buffer, MAX_PATH, "[%u] %hd (0x%04x)", index, c, c); + break; + } + case RPC_SOCKET_TYPE_UINT16: + { + uint16_t c = *(uint16_t *)item->item; + snprintf(buffer, MAX_PATH, "[%u] %hu (0x%04x)", index, c, c); + break; + } + case RPC_SOCKET_TYPE_INT32: + { + int32_t c = *(int32_t *)item->item; + snprintf(buffer, MAX_PATH, "[%u] %d (0x%08x)", index, c, c); + break; + } + case RPC_SOCKET_TYPE_UINT32: + { + uint32_t c = *(uint32_t *)item->item; + snprintf(buffer, MAX_PATH, "[%u] %u (0x%08x)", index, c, c); + break; + } + case RPC_SOCKET_TYPE_INT64: + { + int64_t c = *(int64_t *)item->item; + snprintf(buffer, MAX_PATH, "[%u] "FMT_INT64_T" ("FMT_HEX64_T")", index, c, c); + break; + } + case RPC_SOCKET_TYPE_UINT64: + { + uint64_t c = *(uint64_t *)item->item; + snprintf(buffer, MAX_PATH, "[%u] "FMT_UINT64_T" ("FMT_HEX64_T")", index, c, c); + break; + } + default: + snprintf(buffer, MAX_PATH, "unknown"); + break; + } + } + else + snprintf(buffer, MAX_PATH, "(nil)"); + SOSAL_PRINT(SOSAL_ZONE_RPC, "\t[%u] Parameter Type %u, size: %u, num: %u, value: %s\n", + index, item->type, item->sizeElement, item->numElements, buffer); +} + +static void rpc_socket_packet_print(char *prefix, uint8_t *packet, uint32_t len) +{ + static char buffer[(RPC_SOCKET_MAX_PACKET*3)+1]; // converting BYTES to NIBBLES+SPACE to print + static char hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + uint32_t i; + // convert each byte into a HEX character + for (i = 0; i < len; i++) + { + uint8_t bn = packet[i]; // bottom nibble + uint8_t tn = packet[i]; // top nibble + tn >>= 4; // adjust + buffer[i*3 + 0] = hex[tn&0xF]; + buffer[i*3 + 1] = hex[bn&0xF]; + buffer[i*3 + 2] = ' '; + } + buffer[i*3] = '\0'; + prefix = prefix; // warnings + SOSAL_PRINT(SOSAL_ZONE_RPC, "%s PACKET[%u] %s\n", prefix, len, buffer); +} + +static bool_e rpc_socket_send(socket_t *socket, uint8_t *packet, size_t len, rpc_socket_header_t *header, rpc_socket_item_t *items) +{ + uint32_t i,offset = 0; + + header->length = sizeof(rpc_socket_header_t); + + // concatenate all the items to the length + for (i = 0; i < header->numItems; i++) + { + rpc_socket_item_length(&items[i]); // fill in the correct length value; + header->length += items[i].length; + } + + // copy all data into the packet. + memcpy(&packet[offset], header, sizeof(rpc_socket_header_t)); + offset += sizeof(rpc_socket_header_t); + for (i = 0; i < header->numItems; i++) + { + if ((offset + items[i].length) <= len) + { + memcpy(&packet[offset], &items[i], RPC_SOCKET_ITEM_HEADER_SIZE); + offset += RPC_SOCKET_ITEM_HEADER_SIZE; + memcpy(&packet[offset], items[i].item, items[i].sizeElement*items[i].numElements); + offset += (items[i].sizeElement*items[i].numElements); + } + else + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR: RPC: Packet Length of "FMT_SIZE_T" is insufficient to hold the needed marshalled data of %u\n", len, offset); + return false_e; // too much info to send over the packet + } + } + + SOSAL_PRINT(SOSAL_ZONE_RPC, "SEND(%u) function: %u numItems: %u\n", offset, header->function, header->numItems); + rpc_socket_packet_print("SEND", packet, offset); + return socket_send(socket, packet, offset); +} + +static bool_e rpc_socket_recv(socket_t *socket, uint8_t *packet, size_t len, rpc_socket_header_t *header, rpc_socket_item_t *items) +{ + uint32_t i,offset = 0; + + if (socket_recv(socket, (uint8_t *)&offset, sizeof(uint32_t)) == true_e) // get the length of the packet + { + if (offset > len) + { + /// @todo we can't read this out, ... error? + SOSAL_PRINT(SOSAL_ZONE_ERROR, "CATASTROPHIC ERROR! PACKET WAS TOO SMALL ("FMT_SIZE_T") TO HOLD INCOMING DATA (%u)\n",len, offset); + return false_e; + } + *(uint32_t *)&packet[0] = offset; // save offset in the packet too. + if (socket_recv(socket, &packet[sizeof(uint32_t)], offset-sizeof(uint32_t)) == true_e) + { + SOSAL_PRINT(SOSAL_ZONE_RPC, "Received a Packet of %u bytes \n", offset); + memcpy(header, &packet[0], sizeof(rpc_socket_header_t)); + header->length = offset; // remember we read this out first... + offset = sizeof(rpc_socket_header_t); // reset the offset + SOSAL_PRINT(SOSAL_ZONE_RPC, "Packet requests Function %u with %u parameters\n", header->function, header->numItems); + for (i = 0; i < header->numItems; i++) + { + uint32_t len = 0; + memcpy(&items[i], &packet[offset], RPC_SOCKET_ITEM_HEADER_SIZE); + offset += RPC_SOCKET_ITEM_HEADER_SIZE; + len = items[i].numElements * items[i].sizeElement; + if (len > 0 && items[i].item == NULL) // server thread + items[i].item = &packet[offset]; // no copy needed! the packet is persistent across the call. + else // client call, where they've already allocated the memory + memcpy(items[i].item, &packet[offset], len); + rpc_socket_item_print(i, &items[i]); + offset += len; + } + rpc_socket_packet_print("RECV",packet,offset); + SOSAL_PRINT(SOSAL_ZONE_RPC, "RECV(%u) function: %u numItems: %u\n", header->length, header->function, header->numItems); + return true_e; + } + else + return false_e; + } + else + return false_e; +} + +//****************************************************************************** +// SERVER SIDE +//****************************************************************************** + +void rpc_socket_server_deinit(rpc_server_t *server) +{ + if (server) + { + //socket_disconnect(server->server); + socket_deinit(server->server); + free(server->functions); + free(server); + } +} + +rpc_server_t *rpc_socket_server_init(char *hostname, uint16_t port, void *arg, rpc_server_function_f *functions, uint32_t numFunctions) +{ + rpc_server_t *server = (rpc_server_t *)calloc(1, sizeof(rpc_server_t)); + if (server) + { + server->server = socket_init(socket_hostname(hostname), port, SOCKET_TCP, true_e); + server->numFunctions = numFunctions; + server->port = port; + server->arg = arg; + server->functions = (rpc_server_function_f *)calloc(numFunctions, sizeof(rpc_server_function_f)); + if (server->functions) + { + memcpy(server->functions, functions, sizeof(rpc_server_function_f)*numFunctions); + } + } + return server; +} + +static thread_ret_t rpc_socket_server_thread(void *arg) +{ + rpc_server_t *server = (rpc_server_t *)arg; + uint8_t packet[RPC_SOCKET_MAX_PACKET]; + rpc_socket_header_t header; + rpc_socket_item_t items[RPC_SOCKET_MAX_ARGS]; + rpc_socket_item_t returns[RPC_SOCKET_MAX_ARGS]; // these fields will be copied from local static data + uint32_t numReturns; + bool_e ret = false_e; + uint32_t i = 0; + + SOSAL_PRINT(SOSAL_ZONE_RPC, "%s started! Packet has "FMT_CONST" bytes\n",__FUNCTION__, RPC_SOCKET_MAX_PACKET); + + while(server->running == true_e) + { + SOSAL_PRINT(SOSAL_ZONE_RPC, "Starting RPC Server on port %u\n", server->port); + // wait for a connection... + if (socket_connect(server->server) == true_e) + { + SOSAL_PRINT(SOSAL_ZONE_RPC, "Server connected to Client on port %u\n", server->port); + do { + // clear out the previous iteration + memset(&header, 0, sizeof(header)); + memset(items, 0, sizeof(items)); + memset(returns, 0, sizeof(returns)); + memset(packet, 0, sizeof(packet)); + + SOSAL_PRINT(SOSAL_ZONE_RPC, "Server waiting for Remote Procedure Call\n"); + ret = rpc_socket_recv(server->server, packet, sizeof(packet), &header, items); + if (ret == true_e && header.function < server->numFunctions && server->functions[header.function] != NULL) + { + SOSAL_PRINT(SOSAL_ZONE_RPC, "Server Calling Function[%u]=%p with %u parameters\n", header.function, server->functions[header.function], header.numItems); + for (i = 0; i < header.numItems; i++) + { + rpc_socket_item_print(i, &items[i]); + } + ret = server->functions[header.function](server->arg, items, header.numItems, returns, &numReturns); + header.direction = RPC_SOCKET_RETURN; + header.numItems = numReturns; + // keep the function ID + // length will be recalculated in send + if (ret == false_e) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR: RPC: Desired function %u did not accept parameter list\n", header.function); + header.numItems = 0; + } + ret = rpc_socket_send(server->server, packet, sizeof(packet), &header, returns); + } + else + { + SOSAL_PRINT(SOSAL_ZONE_RPC, "Server Socket was closed!\n"); + } + } while (ret == true_e); + + // we assume that all items data fields must be freed + for (i = 0; i < dimof(items); i++) + if (items[i].item) + free(items[i].item); + } + else + { + SOSAL_PRINT(SOSAL_ZONE_RPC, "RPC Socket Server could not server on port %u!\n", server->port); + break; + } + } + SOSAL_PRINT(SOSAL_ZONE_RPC, "RPC Socket Server Closing!\n"); + thread_exit(0); +} + +bool_e rpc_socket_server_start(rpc_server_t *server) +{ + if (server && server->handle == 0) + { + server->running = true_e; + server->handle = thread_create(rpc_socket_server_thread, server); + if (server->handle != 0) + return true_e; + else + return false_e; + } + return false_e; +} + +void rpc_socket_server_stop(rpc_server_t *server) +{ + if (server) + { + server->running = false_e; + if (server->server) + socket_disconnect(server->server); + SOSAL_PRINT(SOSAL_ZONE_RPC, "Closed Server Socket\n"); + if (server->handle) + thread_join(server->handle); + } +} + +//****************************************************************************** +// CLIENT SIDE +//****************************************************************************** + +void rpc_socket_client_stop(rpc_client_t *client) +{ + if (client) + { + socket_disconnect(client->server); + socket_deinit(client->server); + free(client); + } +} + +rpc_client_t *rpc_socket_client_start(char *hostname, uint16_t port) +{ + rpc_client_t *client = (rpc_client_t *)calloc(1, sizeof(rpc_client_t)); + if (client) + { + client->ipaddr = socket_hostname(hostname); + client->port = port; + client->server = socket_init(client->ipaddr, client->port, SOCKET_TCP, false_e); + if (socket_connect(client->server) == true_e) + { + // we're good to go. + /// @todo any validation needed? + SOSAL_PRINT(SOSAL_ZONE_RPC, "Client Connected to Server on port %u\n", port); + } + else + { + socket_deinit(client->server); + free(client); + client = NULL; + } + } + return client; +} + +bool_e rpc_socket_client_call(rpc_client_t *client, uint32_t function, rpc_socket_item_t *items, uint32_t numItems, rpc_socket_item_t *rets, uint32_t numRets) +{ + rpc_socket_header_t header = {sizeof(rpc_socket_header_t), // more will be added later + function, + RPC_SOCKET_CALLING, + numItems}; + uint8_t packet[RPC_SOCKET_MAX_PACKET]; + + SOSAL_PRINT(SOSAL_ZONE_RPC, "Client Calling Server Function %u with %u parameters, expecting %u returns\n", function, numItems, numRets); + + if (rpc_socket_send(client->server, packet, sizeof(packet), &header, items) == true_e) + { + header.direction = RPC_SOCKET_RETURN; + header.numItems = numRets; + // function should be the same + // length will be overwritten + return rpc_socket_recv(client->server, packet, sizeof(packet), &header, rets); + } + else + return false_e; +} + +void rpc_socket_item_length(rpc_socket_item_t *item) +{ + item->length = RPC_SOCKET_ITEM_HEADER_SIZE + (item->numElements * item->sizeElement); +} + +//****************************************************************************** +// UNIT TEST FUNCTIONS +//****************************************************************************** + +#include +#define RPC_SOCKET_TEST_PORT (5688) + +static semaphore_t sem; + +static int32_t function1(int32_t a, int32_t b) +{ + return a+b; +} + +static int32_t function2(char *string) +{ + // don't use SOSAL_PRINT + return printf("%s", string); +} + +static bool_e rpc_server_function1(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns) +{ + static int32_t a = 0, b = 0, c = 0; + static rpc_socket_item_t local_returns[1] = { + {0, + RPC_SOCKET_TYPE_INT32, + sizeof(int32_t), + 1, + &c}, + }; + semaphore_t *psem = (semaphore_t *)arg; + + if (numParams == 2 && + params[0].type == RPC_SOCKET_TYPE_INT32 && + params[1].type == RPC_SOCKET_TYPE_INT32) + { + a = *(int32_t *)params[0].item; + b = *(int32_t *)params[1].item; + semaphore_wait(psem); + c = function1(a,b); + semaphore_post(psem); + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Local Function1 Called with %u,%u returned %u\n", a,b,c); + memcpy(returns, local_returns, sizeof(local_returns)); + *numReturns = dimof(local_returns); + return true_e; + } + else + return false_e; +} + +static bool_e rpc_server_function2(void *arg, rpc_socket_item_t *params, uint32_t numParams, rpc_socket_item_t *returns, uint32_t *numReturns) +{ + static int32_t c = 0; + static rpc_socket_item_t local_returns[1] = { + {0, + RPC_SOCKET_TYPE_INT32, + sizeof(int32_t), + 1, + &c}, + }; + semaphore_t *psem = (semaphore_t *)arg; + + if (numParams == 1 && + params[0].type == RPC_SOCKET_TYPE_STRING) + { + char buffer[MAX_PATH]; + memset(buffer, 0, sizeof(buffer)); + strncpy(buffer, params[0].item, params[0].numElements * params[0].sizeElement); + semaphore_wait(psem); + c = function2(buffer); + semaphore_post(psem); + memcpy(returns, local_returns, sizeof(local_returns)); + *numReturns = dimof(local_returns); + return true_e; + } + else + return false_e; +} + +bool_e rpc_unittest(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) +{ + bool_e ret = false_e; + rpc_server_function_f functions[] = {rpc_server_function1, + rpc_server_function2}; + rpc_client_t *client = NULL; + rpc_server_t *server = NULL; + semaphore_create(&sem, 1, false_e); + server = rpc_socket_server_init("localhost",RPC_SOCKET_TEST_PORT, &sem, functions, dimof(functions)); + if (server) + { + rpc_socket_server_start(server); + thread_msleep(1000); + client = rpc_socket_client_start("localhost",RPC_SOCKET_TEST_PORT); + if (client) + { + int32_t a = 4, b = 10, c; + char buffer[MAX_PATH]; + rpc_socket_item_t items[] = {{sizeof(rpc_socket_item_t) - 4 + sizeof(int32_t), + RPC_SOCKET_TYPE_INT32, + sizeof(int32_t), + 1, + &a}, + {sizeof(rpc_socket_item_t) - 4 + sizeof(int32_t), + RPC_SOCKET_TYPE_INT32, + sizeof(int32_t), + 1, + &b}}; + rpc_socket_item_t rets[] = {{sizeof(rpc_socket_item_t) - 4 + sizeof(int32_t), + RPC_SOCKET_TYPE_INT32, + sizeof(int32_t), + 1, + &c}}; + rpc_socket_item_t stritem; + rpc_socket_client_call(client, 0, items, dimof(items), rets, dimof(rets)); + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Client is calling remote procedures!\n"); + ret = true_e; + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Received Data %u, should have been %u\n", c, a+b); + if (c != a+b) + ret = false_e; + sprintf(buffer, "%i+%i=%i\n", a,b,c); + c = 0; + stritem.length = sizeof(rpc_socket_item_t) - 4 + strlen(buffer); + stritem.type = RPC_SOCKET_TYPE_STRING; + stritem.numElements = strlen(buffer); + stritem.sizeElement = 1; + stritem.item = buffer; + rpc_socket_client_call(client, 1, &stritem, 1, rets, dimof(rets)); + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Remote Function Printed %u characters\n", c); + if (c == 0) + ret = false_e; + rpc_socket_client_stop(client); + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Client finished\n"); + } + rpc_socket_server_stop(server); + rpc_socket_server_deinit(server); + } + semaphore_delete(&sem); + return ret; +} + +#endif diff --git a/source/sosal/rtimer.c b/source/sosal/rtimer.c new file mode 100644 index 0000000..acc7c7a --- /dev/null +++ b/source/sosal/rtimer.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(DARWIN) +#include +#include +#else +#define MACH_TIMER +#define __LITTLE_ENDIAN__ 1 +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +typedef uint64_t rtime_t; +#define FMT_RTIMER_T "%llu" +#endif + +#include + +#ifdef SYSBIOS +#include +#include +#endif + +#define BILLION (1000000000) + +#ifdef POSIX_TIMER + +rtime_t rtimer_now() +{ + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + SOSAL_PRINT(SOSAL_ZONE_TIMER, "TIME sec:%lu nsec:%lu\n",t.tv_sec,t.tv_nsec); + return (rtime_t)((rtime_t)t.tv_nsec + ((rtime_t)t.tv_sec*BILLION)); +} + +rtime_t rtimer_freq() +{ + struct timespec t; + clock_getres(CLOCK_MONOTONIC, &t); + //SOSAL_PRINT(SOSAL_ZONE_TIMER, "FREQ sec:%lu nsec:%lu\n",t.tv_sec,t.tv_nsec); + return (rtime_t)(BILLION/t.tv_nsec); +} + +#elif defined(MACH_TIMER) + +rtime_t rtimer_now() +{ + static mach_timebase_info_data_t info; + uint64_t now_64 = mach_absolute_time(); + if (info.denom == 0) + mach_timebase_info(&info); + return (now_64 * info.numer)/info.denom; +} + +rtime_t rtimer_freq() +{ + static mach_timebase_info_data_t info; + if (info.denom == 0) + mach_timebase_info(&info); + //SOSAL_PRINT(SOSAL_ZONE_TIMER, "Numer:"FMT_RTIMER_T" Demon:"FMT_RTIMER_T"\n", info.numer, info.denom); + return BILLION*(info.denom/info.numer); +} + +#elif defined(SYSBIOS) + +rtime_t rtimer_now() +{ + Types_Timestamp64 tTicks; + uint64_t llTiks; + + + Timestamp_get64(&tTicks); + + llTiks = ((uint64_t)(tTicks.hi) << 32) + tTicks.lo; + return (rtime_t)(llTiks); +} + +rtime_t rtimer_freq() +{ + Types_FreqHz tFreqHz; + uint64_t llFreqHz; + + Timestamp_getFreq(&tFreqHz); + + llFreqHz = ((uint64_t)(tFreqHz.hi) << 32) + tFreqHz.lo; + return (rtime_t)(llFreqHz); +} + +#else + +rtime_t rtimer_now() +{ + LARGE_INTEGER now; + QueryPerformanceCounter(&now); + return now.QuadPart; +} + +rtime_t rtimer_freq() +{ + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + return freq.QuadPart; +} + +#endif + +rtime_t rtimer_from_rate_to_us(rtime_t t, rtime_t rate) +{ + double power = log(rate)/log(10); + //SOSAL_PRINT(SOSAL_ZONE_TIMER, "%s: log10("FMT_RTIMER_T")=%lf\n", __FUNCTION__, rate, power); + if (power > 6.0) + { + return (rtime_t)t / pow(10, power - 6.0); + } + else if (power < 6.0) + { + return (rtime_t)t * pow(10, 6.0 - power); + } + else + return (rtime_t)t; +} + +rtime_t rtimer_to_us(rtime_t t) +{ + return rtimer_from_rate_to_us(t, rtimer_freq()); +} + +double rtimer_from_rate_to_sec(rtime_t t, rtime_t rate) +{ + return (double)t/rate; +} + +double rtimer_to_sec(rtime_t t) +{ + return rtimer_from_rate_to_sec(t, rtimer_freq()); +} + diff --git a/source/sosal/semaphore.c b/source/sosal/semaphore.c new file mode 100644 index 0000000..a0c86c7 --- /dev/null +++ b/source/sosal/semaphore.c @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +bool_e semaphore_create(semaphore_t *s, uint32_t count, bool_e shared) +{ +#ifdef POSIX + if (sem_init(s, (shared == true_e ? 1 : 0), count) == 0) +#elif defined(SYSBIOS) + /* creating with default params (NULL) */ + *s = Semaphore_create(count, NULL, NULL); + if (*s != NULL) +#else + *s = CreateSemaphore(NULL, count, count, NULL); + if (*s != NULL) +#endif + return true_e; + else + return false_e; +} + +bool_e semaphore_delete(semaphore_t *s) +{ +#ifdef POSIX + if (sem_destroy(s) == 0) + return true_e; + else + return false_e; +#elif defined(SYSBIOS) + /* Delete the semaphore. */ + Semaphore_delete(s); + return true_e; +#else + if (CloseHandle(*s) == TRUE) + return true_e; + else + return false_e; +#endif +} + +bool_e semaphore_post(semaphore_t *s) +{ +#ifdef POSIX + int ret = sem_post(s); + SOSAL_PRINT(SOSAL_ZONE_SEMA, "SEM POST on %p returned %d, errno=%d\n", s, ret, errno); + if (ret == 0) + return true_e; + else + return false_e; +#elif defined(SYSBIOS) + /* Release the semaphore. */ + Semaphore_post(*s); + return true_e; +#else + if (ReleaseSemaphore(*s, 1, NULL) == TRUE) + return true_e; + else + return false_e; +#endif +} + +bool_e semaphore_wait(semaphore_t *s) +{ +#ifdef POSIX + int ret = sem_wait(s); + SOSAL_PRINT(SOSAL_ZONE_SEMA, "SEM WAIT on %p returned %d, errno=%d\n", s, ret, errno); + if (ret == 0) +#elif defined(SYSBIOS) + int ret = 1; + if(s != 0 && (*s) != 0) { + ret = Semaphore_pend(*s, BIOS_WAIT_FOREVER); //returns TRUE on success + } + if (ret != 0) +#else + DWORD status = WaitForSingleObject(*s, INFINITE); + if (status == WAIT_OBJECT_0) +#endif + return true_e; + else + return false_e; +} + +int semaphore_trywait(semaphore_t *s) +{ +#ifdef POSIX + int ret = sem_trywait(s); + SOSAL_PRINT(SOSAL_ZONE_SEMA, "SEM TRYWAIT on %p returned %d, errno=%d\n", s, ret, errno); + if (ret == 0) + return 1; + else if (ret == -1 && errno == EAGAIN) + return 0; + else + return -1; +#elif defined(SYSBIOS) + int ret = Semaphore_pend(*s, BIOS_NO_WAIT); //returns TRUE on success + if( ret != 0 ) + return 1; + else + return -1; +#else + DWORD status = WaitForSingleObject(*s, 0); + if (status == WAIT_OBJECT_0) + return 1; + else if (status == WAIT_TIMEOUT) + return -1; + else + return -1; +#endif +} + diff --git a/source/sosal/serial.c b/source/sosal/serial.c new file mode 100644 index 0000000..d660c90 --- /dev/null +++ b/source/sosal/serial.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#if defined(SOSAL_SERIAL_API) + +serial_t serial_open(uint32_t number) +{ + char device_name[256]; +#ifdef POSIX_SERIAL + FILE *ftty; + sprintf(device_name, "/dev/ttyS%02u", number); + ftty = fopen(device_name, "wb"); + return ftty; +#else + HANDLE hCom; + DCB dcb; + + sprintf(device_name, "\\\\.\\COM%u", number); + + hCom = CreateFile(device_name, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + if (hCom) + { + //SecureZeroMemory(&dcb, sizeof(DCB)); + memset(&dcb, 0, sizeof(dcb)); + dcb.DCBlength = sizeof(DCB); + + GetCommState(hCom, &dcb); + dcb.BaudRate = CBR_115200; + dcb.ByteSize = 8; + dcb.Parity = NOPARITY; + dcb.StopBits = ONESTOPBIT; + // 115200 8n1 + SetCommState(hCom, &dcb); + GetCommState(hCom, &dcb); + if (dcb.BaudRate == 0) { + CloseHandle(hCom); + hCom = NULL; + } else { + printf("%s: BaudRate = %d, ByteSize = %d, Parity = %d, StopBits = %d\n", device_name, dcb.BaudRate, dcb.ByteSize, dcb.Parity, dcb.StopBits); + } + } + return hCom; +#endif +} + +void serial_close(serial_t ser) +{ +#ifdef POSIX_SERIAL + fclose(ser); +#else + CloseHandle(ser); +#endif +} + +size_t serial_read(serial_t ser, uint8_t *buffer, size_t numBytes) +{ +#ifdef POSIX_SERIAL + return fread(buffer, 1, numBytes, ser); +#else + size_t read; + if (ReadFile(ser, buffer, numBytes, (DWORD *)&read, NULL) == FALSE) + read = 0; + return read; +#endif +} + +size_t serial_write(serial_t ser, uint8_t *buffer, size_t numBytes) +{ +#ifdef POSIX_SERIAL + return fwrite(buffer, 1, numBytes, ser); +#else + size_t wrote; + if (WriteFile(ser, buffer, numBytes, (DWORD *)&wrote, NULL) == FALSE) + wrote = 0; + return wrote; +#endif +} + +#endif + diff --git a/source/sosal/shared.c b/source/sosal/shared.c new file mode 100644 index 0000000..1c0e86d --- /dev/null +++ b/source/sosal/shared.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#if defined(ANDROID) +#error "ANDROID must use the shared.cpp file" +#endif + +void shared_free(shared_t **pshm) +{ + if (pshm) + { + shared_t *shm = *pshm; + if (shm) + { +#ifdef SHM_SYSVIPC + shmdt(shm->data); + shmctl(shm->shmid, IPC_RMID, 0); +#endif +#ifdef SHM_QNX + munmap(shm->data, shm->size); + close(shm->fd); + shm_unlink(shm->name); +#endif +#ifdef WIN32 + UnmapViewOfFile(shm->data); + CloseHandle(shm->mapfile); +#endif + free(shm); + } + *pshm = NULL; + } +} + +shared_t *shared_alloc(unique_t un, size_t size) +{ + shared_t *shm = (shared_t *)calloc(1, sizeof(shared_t)); + if (shm) + { + shm->un = un; + shm->size = size; +#ifdef SHM_SYSVIPC + shm->shmflags = IPC_CREAT | 0666; + shm->shmid = shmget(shm->un, shm->size, shm->shmflags); + if (shm->shmid > -1) + { + SOSAL_PRINT(SOSAL_ZONE_SHARED, "SHM: seg=%d flags=%x\n", shm->shmid, shm->shmflags); + shm->data = shmat(shm->shmid, NULL, 0); + if (shm->data == (void *)-1) + { + shared_free(&shm); + } + } +#endif +#ifdef SHM_QNX + sprintf(shm->name, "shared_mem_%x", shm->un); + shm->fd = shm_open(shm->name, O_RDWR | O_CREAT, 0777); + if (shm->fd > -1) + { + if (ftruncate(shm->fd, shm->size) > -1) + { + shm->data = mmap(0, shm->size, PROT_READ|PROT_WRITE, MAP_SHARED, shm->fd, 0); + if (shm->data != MAP_FAILED) + { + SOSAL_PRINT(SOSAL_ZONE_SHARED, "SHM: %s => %p for "FMT_SIZE_T" bytes\n", shm->name, shm->data, shm->size); + } + // if you clear the memory and someone else already has initialized it, you'll destroy data! + //memset(shm->data, 0, sizeof(shm->data)); + } + } +#endif +#ifdef WIN32 + wsprintf(shm->name, TEXT("shared_mem_%x\n"), shm->un); + shm->mapfile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, shm->name); + if (shm->mapfile) + { + shm->data = MapViewOfFile(shm->mapfile, FILE_MAP_ALL_ACCESS, 0, 0, shm->size); + if (shm->data == NULL) + { + shared_free(&shm); + } + } +#endif + if (shm) + { + SOSAL_PRINT(SOSAL_ZONE_SHARED, "SHM[%x]: Size="FMT_SIZE_T" Data=%p\n", shm->un, shm->size, shm->data); + } + } + return shm; +} + + +#include +bool_e shared_unittest(int argc, char *argv[]) +{ + int s = (argc > 1 ? atoi(argv[1]) : 7000); + unique_t un = (argc > 2 ? atoi(argv[2]) : 42); + char string[MAX_PATH]; + shared_t *shm = shared_alloc(un, MAX_PATH); + if (shm) + { + memset(string, 0, MAX_PATH); + if (argc > 3) { + SOSAL_PRINT(SOSAL_ZONE_SHARED, "Copying %s into %p\n", argv[3], shm->data); + strncpy((char *)shm->data, argv[3], MAX_PATH); + } + thread_msleep(s); + strncpy(string, (char *)shm->data, MAX_PATH); + SOSAL_PRINT(SOSAL_ZONE_SHARED, "String = %s\n", string); + + shared_free(&shm); + } + SOSAL_PRINT(SOSAL_ZONE_SHARED, "SHM: Exiting\n"); + return true_e; +} + diff --git a/source/sosal/shared.cpp b/source/sosal/shared.cpp new file mode 100644 index 0000000..c2d1b61 --- /dev/null +++ b/source/sosal/shared.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +using namespace android; + +void shared_free(shared_t **pshm) +{ + sp shm_service; + status_t status = getService(android::String16(SHARED_MEMORY_SERVICE_NAME), &shm_service); + if (status == NO_ERROR) { + shm_service->forget(pshm); + } else { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to obtain memory service handle! (0x%x)", status); + } +} + +shared_t *shared_alloc(unique_t un, size_t size) +{ + shared_t *shm = (shared_t *)calloc(1, sizeof(shared_t)); + if (shm) + { + shm->un = un; + shm->size = size; + { + sp shm_service; + status_t status = getService(android::String16(SHARED_MEMORY_SERVICE_NAME), &shm_service); + if (status == NO_ERROR) + { + if (shm_service->allocate(&shm) == true_e) + { + SOSAL_PRINT(SOSAL_ZONE_SHARED, "SHM[%x]: FD=%d\n", shm->un, shm->fd); + } + } + else + { + free(shm); + shm = NULL; + } + } + if (shm) + { + SOSAL_PRINT(SOSAL_ZONE_SHARED, "SHM[%x]: Size="FMT_SIZE_T" Data=%p\n", shm->un, shm->size, shm->data); + } + } + return shm; +} + + +#include +extern "C" bool_e shared_unittest(int argc, char *argv[]) +{ + bool_e ret = true_e; + int s = (argc > 1 ? atoi(argv[1]) : 7000); + unique_t un = (argc > 2 ? atoi(argv[2]) : 42); + char string[MAX_PATH]; + shared_t *shm = shared_alloc(un, MAX_PATH); + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "SHM: Testing Running!\n"); + if (shm) + { + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "SHM: %p FD=%d\n", shm, shm->fd); + + memset(string, 0, MAX_PATH); + if (argc > 3) { + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Copying %s into %p\n", argv[3], shm->data); + strncpy((char *)shm->data, argv[3], MAX_PATH); + } + thread_msleep(s); + strncpy(string, (char *)shm->data, MAX_PATH); + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "String = %s\n", string); + + shared_free(&shm); + } + else + ret = false_e; + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "SHM: Exiting\n"); + return ret; +} + diff --git a/source/sosal/shared_binder.cpp b/source/sosal/shared_binder.cpp new file mode 100644 index 0000000..b4e47dc --- /dev/null +++ b/source/sosal/shared_binder.cpp @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#ifdef SHARED_MEMORY_CLIENT +namespace android { + +BpSharedMemoryClient::BpSharedMemoryClient(const sp& impl) + : BpInterface(impl) +{ + SOSAL_PRINT(SOSAL_ZONE_API, "+BpSharedMemoryClient()\n"); +} + +BpSharedMemoryClient::~BpSharedMemoryClient() +{ + SOSAL_PRINT(SOSAL_ZONE_API, "~BpSharedMemoryClient()\n"); +} + +IMPLEMENT_META_INTERFACE(SharedMemoryClient, "com.ti.sosal.shm_client"); + +SharedMemoryClient::SharedMemoryClient() +{ + SOSAL_PRINT(SOSAL_ZONE_API, "+SharedMemoryClient()\n"); +} + +SharedMemoryClient::~SharedMemoryClient() +{ + SOSAL_PRINT(SOSAL_ZONE_API, "~SharedMemoryClient()\n"); +} + +BpSharedMemory::BpSharedMemory(const sp& impl) + : BpInterface(impl) +{ + SOSAL_PRINT(SOSAL_ZONE_API, "+BpSharedMemory()\n"); +} + +BpSharedMemory::~BpSharedMemory() +{ + SOSAL_PRINT(SOSAL_ZONE_API, "~BpSharedMemory()\n"); +} + +bool_e BpSharedMemory::allocate(shared_t **pshm) +{ + shared_t *shm = *pshm; + if (shm) + { + Parcel data, reply; + sp client = new SharedMemoryClient(); + data.writeInterfaceToken(ISharedMemory::getInterfaceDescriptor()); + data.writeInt32(shm->un); + data.writeInt64(shm->size); + data.writeStrongBinder(client->asBinder()); + remote()->transact(SHM_SRVC_ALLOCATE, data, &reply); + shm->fd = dup(reply.readFileDescriptor()); + if (shm->fd < 0) + { + free(shm); + shm = NULL; + return false_e; + } + else + { + // success + shm->data = mmap(NULL, shm->size, PROT_READ|PROT_WRITE, MAP_SHARED, shm->fd, 0); + if (shm->data == MAP_FAILED) + { + close(shm->fd); + free(shm); + shm = NULL; + return false_e; + } + client->incStrong(this); + shm->reserved = client.get(); + } + } + return true_e; +} + +void BpSharedMemory::deallocate(shared_t **pshm) +{ + if (pshm && *pshm) + { + shared_t *shm = *pshm; + munmap(shm->data, shm->size); + close(shm->fd); + sp client = (SharedMemoryClient *)shm->reserved; + client->decStrong(this); + free(shm); + *pshm = NULL; + } +} + +void BpSharedMemory::forget(shared_t **pshm) +{ + if (pshm && *pshm ) + { + shared_t *shm = *pshm; + Parcel data, reply; + data.writeInterfaceToken(ISharedMemory::getInterfaceDescriptor()); + data.writeInt32(shm->un); + sp client = (SharedMemoryClient *)shm->reserved; + data.writeStrongBinder(client); + remote()->transact(SHM_SRVC_REMOVE, data, &reply); + deallocate(pshm); + } +} + +IMPLEMENT_META_INTERFACE(SharedMemory, SHARED_MEMORY_SERVICE_NAME); + +} + +#endif // SHARED_MEMORY_CLIENT +#ifdef SHARED_MEMORY_SERVICE + +#define SHARED_MEMORY_NAME_FMT "com.ti.sosal.shm.%08x" + +namespace android { + +SharedMemoryEntry::SharedMemoryEntry(DefaultKeyedVector< unique_t, wp > *list) +{ + mUnique = 0; + mSize = 0; + mFd = 0; + mEntries = list; +} + +SharedMemoryEntry::~SharedMemoryEntry() +{ + close(mFd); + mEntries->removeItem(mUnique); + for (size_t i = 0; i < mClients.size(); i++) { + sp client = mClients.valueAt(i).promote(); + if (client != NULL) { + client->unlinkToDeath(this); + } + } + mClients.clear(); +} + +status_t SharedMemoryEntry::allocate(unique_t un, size_t size, sp& client) +{ + char name[MAX_PATH]; + sprintf(name, SHARED_MEMORY_NAME_FMT, un); + + mFd = ashmem_create_region(name, size); + if (mFd < 0) { + return NO_MEMORY; + } + + addClient(client); + mUnique = un; + mSize = size; + + return NO_ERROR; +} + +status_t SharedMemoryEntry::addClient(sp& client) +{ + mClients.add(client.get(), client); + client->linkToDeath(this); + incStrong(this); + return NO_ERROR; +} + +status_t SharedMemoryEntry::removeClient(sp& client) +{ + mClients.removeItem(client.get()); + client->unlinkToDeath(this); + decStrong(this); + return NO_ERROR; +} + +void SharedMemoryEntry::binderDied(const wp& who) +{ + mClients.removeItem(who.unsafe_get()); + decStrong(this); +} + +status_t SharedMemoryEntry::dump(int fd, const Vector&) +{ + const size_t SIZE = 4096; + char buffer[SIZE]; + String8 result; + + snprintf(buffer, SIZE, " [un:0x%x, size:%d, fd:%d]\n", mUnique, mSize, mFd); + result.append(buffer); + + for (size_t i = 0; i < mClients.size(); i++) { + const wp& client = mClients.valueAt(i); + if (client != NULL) { + snprintf(buffer, SIZE, " - client:%p\n", client.unsafe_get()); + result.append(buffer); + } + } + + write(fd, result.string(), result.size()); + return NO_ERROR; +} + + +const String16 ISharedMemoryService::descriptor(SHARED_MEMORY_SERVICE_NAME); +ISharedMemoryService::ISharedMemoryService() {}; +ISharedMemoryService::~ISharedMemoryService() {}; +const String16& ISharedMemoryService::getInterfaceDescriptor() const { + return ISharedMemoryService::descriptor; +} + +const String16 ISharedMemoryClient::descriptor(SHARED_MEMORY_SERVICE_NAME); +ISharedMemoryClient::ISharedMemoryClient() {}; +ISharedMemoryClient::~ISharedMemoryClient() {}; +const String16& ISharedMemoryClient::getInterfaceDescriptor() const { + return ISharedMemoryClient::descriptor; +} + +void SharedMemoryService::instantiate() +{ + status_t status; + status = defaultServiceManager()->addService(String16(SHARED_MEMORY_SERVICE_NAME), new SharedMemoryService()); +} + +SharedMemoryService::SharedMemoryService() { + SOSAL_PRINT(SOSAL_ZONE_API, "+SharedMemoryService()\n"); +} + +SharedMemoryService::~SharedMemoryService() { + +} + +status_t SharedMemoryService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + status_t status = NO_ERROR; + switch (code) + { + case SHM_SRVC_ALLOCATE: + { + CHECK_INTERFACE(SharedMemoryService, data, reply); + unique_t un = data.readInt32(); + size_t size = data.readInt64(); + sp client = data.readStrongBinder(); + + sp entry = mEntries.valueFor(un).promote(); + if (entry == NULL) { + SOSAL_PRINT(SOSAL_ZONE_SHARED, "SHM SRVC: Creating new Shared Region\n"); + sp entry = new SharedMemoryEntry(&mEntries); + status = entry->allocate(un, size, client); + if (status == NO_ERROR) { + mEntries.add(un, entry); + reply->writeFileDescriptor(entry->fd()); + } + } else { + SOSAL_PRINT(SOSAL_ZONE_SHARED, "SHM SRVC: Found old Shared Region\n"); + entry->addClient(client); + reply->writeFileDescriptor(entry->fd()); + } + break; + } + case SHM_SRVC_REMOVE: + { + SOSAL_PRINT(SOSAL_ZONE_SHARED, "SHM SRVC: SHM_SRVC_REMOVE\n"); + CHECK_INTERFACE(SharedMemoryService, data, reply); + unique_t un = data.readInt32(); + sp client = data.readStrongBinder(); + sp entry = mEntries.valueFor(un).promote(); + if (entry != NULL) { + entry->removeClient(client); + } else { + status = NAME_NOT_FOUND; + } + break; + } + default: + BBinder::onTransact(code, data, reply, flags); + break; + } + return status; +} + +status_t SharedMemoryService::dump(int fd, const Vector& args) +{ + const size_t SIZE = 4096; + char buffer[SIZE]; + String8 result; + + snprintf(buffer, SIZE, "SHM entries:\n"); + result.append(buffer); + write(fd, result.string(), result.size()); + + for (size_t i = 0; i < mEntries.size(); i++) { + sp entry = mEntries.valueAt(i).promote(); + if (entry != NULL) { + entry->dump(fd, args); + } + } + + return NO_ERROR; +} + +} // end of namespace + +using namespace android; + +static void signal_handler(int sig) +{ + // prevent re-entry + signal(sig, NULL); + if (sig == SIGTERM) + { + // someone gave us a kill -9 or killall + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "SIGTERM\n"); + } + else if (sig == SIGINT) + { + // someone gave us a Ctrl+C + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "SIGINT\n"); + } + else if (sig == SIGABRT) + { + // clean up before an abort kills the process + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "SIGABT\n"); + } + else if (sig == SIGBUS) + { + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "SIGBUS\n"); + } + // reinstall + signal(sig, signal_handler); +} + +int daemonize() +{ + int err = 0; + pid_t child_pid; + pid_t child_sid; + + // fork off the parent process so that we can properly be a background service + child_pid = fork(); + if (child_pid == 0) + { + SOSAL_PRINT(SOSAL_ZONE_SHARED, "Child Forked\n"); + + // change the file mode of the process to no access + umask(0); + + // change to a new session so that we're no longer tied to the previous one + child_sid = setsid(); + if (child_sid > 0) + { + SOSAL_PRINT(SOSAL_ZONE_SHARED, "New Session Established!\n"); + // move our working directory to root + err = chdir("/"); + if (err == 0) + { + SOSAL_PRINT(SOSAL_ZONE_SHARED, "Set Working Directory to root\n"); + + // install the signal handlers + if (signal(SIGTERM, signal_handler) == SIG_ERR) + err = -1; + if (signal(SIGINT, signal_handler) == SIG_ERR) + err = -1; + if (signal(SIGBUS, signal_handler) == SIG_ERR) + err = -1; + if (err == 0) { + SOSAL_PRINT(SOSAL_ZONE_SHARED, "Installed Signal Handlers!\n"); + } + } + } + else + { + err = errno; + } + } + else + err = 1; // parent returns non-zero + return err; +} + +int main(int argc, char** argv) +{ + int err = 0; + bool_e daemon = true_e; + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + + SOSAL_PRINT(SOSAL_ZONE_API, "+shm_service\n"); + + if (argc > 1 && strcmp(argv[1], "--no-fork") == 0) + daemon = false_e; + + if (daemon == true_e) + err = daemonize(); + + if (err == 0) + { + SharedMemoryService::instantiate(); + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Starting Texas Instruments Shared Memory Service\n"); + ProcessState::self()->startThreadPool(); + IPCThreadState::self()->joinThreadPool(); + } + else + { + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "SHM SERVICE: Parent Shell Dying!\n"); + } + return err; +} +#endif diff --git a/source/sosal/shared_binder.h b/source/sosal/shared_binder.h new file mode 100644 index 0000000..ccdbd4e --- /dev/null +++ b/source/sosal/shared_binder.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SHARED_MEMORY_SERVICE_ +#define _SHARED_MEMORY_SERVICE_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { + +#define SHARED_MEMORY_SERVICE_NAME "com.ti.sosal.shm_service" + +/* --- Abstract Client Interface --- */ + +class ISharedMemory: public IInterface +{ +public: + DECLARE_META_INTERFACE(SharedMemory); + virtual bool_e allocate(shared_t **pshm) = 0; + virtual void deallocate(shared_t **pshm) = 0; + virtual void forget(shared_t **pshm) = 0; +}; + +class ISharedMemoryClient: public IInterface +{ +public: + DECLARE_META_INTERFACE(SharedMemoryClient); +}; + +/* --- Client side --- */ + +class BpSharedMemory : public BpInterface +{ +public: + BpSharedMemory(const sp& impl); + ~BpSharedMemory(); + bool_e allocate(shared_t **pshm); + void deallocate(shared_t **pshm); + void forget(shared_t **pshm); +}; + +class SharedMemoryClient : public BnInterface +{ +public: + SharedMemoryClient(); + virtual ~SharedMemoryClient(); +}; + +/* --- Abstract Service Interface --- */ + +class ISharedMemoryService : public IInterface +{ +public: + DECLARE_META_INTERFACE(SharedMemoryService); +}; + +typedef enum _shared_memory_service_code_e { + SHM_SRVC_ALLOCATE, /**< Used to allocate a new shared region or open an existing shared region */ + SHM_SRVC_REMOVE, /**< Used to ask the service to close a shared region. This will only actually close once all clients close their local file descriptors */ +} SharedMemoryServiceCode_e; + +/* --- Server side --- */ + +class SharedMemoryEntry : public IBinder::DeathRecipient +{ +public: + SharedMemoryEntry(DefaultKeyedVector< unique_t, wp > *list); + ~SharedMemoryEntry(); + + status_t allocate(unique_t un, size_t size, sp& client); + status_t addClient(sp& client); + status_t removeClient(sp& client); + void binderDied(const wp& who); + + int fd() { return mFd; } + + status_t dump(int fd, const Vector& args); +private: + unique_t mUnique; + size_t mSize; + int mFd; + DefaultKeyedVector< IBinder *, wp > mClients; + DefaultKeyedVector< unique_t, wp > *mEntries; +}; + +class BpSharedMemoryClient : public BpInterface +{ +public: + BpSharedMemoryClient(const sp& impl); + ~BpSharedMemoryClient(); +}; + +class BnSharedMemoryService: public BnInterface +{ +}; + +class SharedMemoryService : public BnSharedMemoryService +{ +public: + SharedMemoryService(); + virtual ~SharedMemoryService(); + // Binder Interfaces + static void instantiate(); + virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); + String16& getInterfaceDescriptor(); + status_t dump(int fd, const Vector& args); + +private: + DefaultKeyedVector< unique_t, wp > mEntries; +}; + +}; // namespace android + +#endif /* _SHARED_MEMORY_SERVICE_ */ diff --git a/source/sosal/socket.c b/source/sosal/socket.c new file mode 100644 index 0000000..db534b9 --- /dev/null +++ b/source/sosal/socket.c @@ -0,0 +1,490 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#if defined(SOSAL_SOCKET_API) + +#if defined(WIN32_SOCKETS) + +#define SOCKET_CLOSE(sock) closesocket(sock) +#define SOCKET_GETERROR WSAGetLastError() +static bool_e winsockinit = false_e; +#define SOCKET_INIT() { \ + if (winsockinit == false_e) { \ + WSADATA data; \ + WSAStartup(2|2<<4, &data); \ + winsockinit = true_e; \ + } \ +} +#define SOCKET_DEINIT() WSACleanup() +#define SOCKET_OPTCAST char * + +#else + +#define SOCKET_CLOSE(sock) close(sock) +#define SOCKET_GETERROR errno +#define SOCKET_INIT() +#define SOCKET_DEINIT() +#define SOCKET_ERROR (-1) +#define INVALID_SOCKET (-1) +#define SOCKET_OPTCAST void * + +#endif + +socket_t *socket_init(uint32_t ipaddr, uint16_t port, socket_type_e type, bool_e isServer) +{ + SOCKET_INIT(); + if (isServer && type == SOCKET_TCP) + { + socket_t *server = calloc(1, sizeof(socket_t)); + if (server) + { + int ret = 1; + server->is_server = true_e; + server->sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (server->sock == INVALID_SOCKET) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to open a server socket\n"); + goto server_failure; + } + + if (setsockopt(server->sock, SOL_SOCKET, SO_REUSEADDR, (SOCKET_OPTCAST)&ret, sizeof(int)) == SOCKET_ERROR) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to set socket options\n"); + goto server_failure; + } + + memset(&server->server_address, 0, sizeof(struct sockaddr_in)); + server->server_address.sin_family = AF_INET; + server->server_address.sin_port = htons(port); + server->server_address.sin_addr.s_addr = ipaddr; +#if defined(ANDROID) + memset(&(server->server_address.__pad), 0, sizeof(server->server_address.__pad)); +#endif + + if (bind(server->sock, (struct sockaddr *)&server->server_address, sizeof(struct sockaddr)) == SOCKET_ERROR) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to bind to socket\n"); + goto server_failure; + } + + if (listen(server->sock, 1) == SOCKET_ERROR) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to listen on socket\n"); + goto server_failure; + } + + SOSAL_PRINT(SOSAL_ZONE_SOCKET, "Created Socket Server on Port %u\n", port); + return server; +server_failure: + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to init server\n"); + if (server->sock != SOCKET_ERROR) + SOCKET_CLOSE(server->sock); + free(server); + server = NULL; + } + } + else + { + socket_t *client = calloc(1, sizeof(socket_t)); + if (client) + { + client->is_server = false_e; + + client->sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (client->sock == INVALID_SOCKET) + goto client_failure; + + memset(&client->server_address, 0, sizeof(struct sockaddr_in)); + client->server_address.sin_family = AF_INET; + client->server_address.sin_port = htons(port); + client->server_address.sin_addr.s_addr = ipaddr; +#if defined(ANDROID) || defined(CYGWIN) + memset(&(client->server_address.__pad), 0, sizeof(client->server_address.__pad)); +#endif + + SOSAL_PRINT(SOSAL_ZONE_SOCKET, "Created Socket Client %d on Port %u\n", client->sock, port); + return client; +client_failure: + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to init client\n"); + if (client->sock != SOCKET_ERROR) + SOCKET_CLOSE(client->sock); + free(client); + client = NULL; + } + } + return NULL; +} + +bool_e socket_connect(socket_t *socket) +{ + if (socket) + { + socket->sin_size = sizeof(struct sockaddr); + if (socket->is_server == true_e) + { +#if defined(WIN32) && !defined(CYGWIN) + SOSAL_PRINT(SOSAL_ZONE_SOCKET, "Connecting to %u.%u.%u.%u\n", + socket->client_address.sin_addr.s_net, + socket->client_address.sin_addr.s_host, + socket->client_address.sin_addr.s_lh, + socket->client_address.sin_addr.s_impno); +#endif + socket->connected = accept(socket->sock, (struct sockaddr *)&socket->client_address, &socket->sin_size); + if (socket->connected == INVALID_SOCKET) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Server failed to connect. errno=%d\n", SOCKET_GETERROR); + return false_e; + } + else + { + SOSAL_PRINT(SOSAL_ZONE_SOCKET, "Server Connected Socket %d\n", socket->connected); + return true_e; + } + } + else + { +#if defined(WIN32) && !defined(CYGWIN) + SOSAL_PRINT(SOSAL_ZONE_SOCKET, "Connecting to %u.%u.%u.%u\n", + socket->server_address.sin_addr.s_net, + socket->server_address.sin_addr.s_host, + socket->server_address.sin_addr.s_lh, + socket->server_address.sin_addr.s_impno); +#endif + if (connect(socket->sock, (struct sockaddr *)&socket->server_address, socket->sin_size) == SOCKET_ERROR) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Client failed to connect.\n"); + return false_e; + } + else + return true_e; + } + } + else + return false_e; +} + +bool_e socket_send(socket_t *socket, uint8_t *data, size_t len) +{ + if (socket && data && len > 0) + { + ssize_t sent = 0; + int err = 0; + int sock = 0; + int flags = 0; + if (socket->is_server) + sock = socket->connected; + else + sock = socket->sock; + sent = send(sock, data, len, flags); + err = SOCKET_GETERROR; + if (sent == 0) + return false_e; + else if (sent == SOCKET_ERROR) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "SOSAL: Failed to send data on socket! send(%d, %p, "FMT_SIZE_T", %x) return "FMT_SSIZE_T" had (errno=%d)\n", sock, data, len, flags, sent, err); + return false_e; + } + else + { + socket->bytesSend += sent; + if (sent != (ssize_t)len) { + SOSAL_PRINT(SOSAL_ZONE_WARNING, "SOSAL: ONLY SENT "FMT_SSIZE_T" BYTES ON SOCKET %p, WANTED "FMT_SIZE_T"\n", sent, socket, len); + } else { + SOSAL_PRINT(SOSAL_ZONE_SOCKET, "SOSAL: Sent "FMT_SSIZE_T" bytes on Socket %p\n", sent, socket); + } + return true_e; + } + } + else + return false_e; +} + +bool_e socket_recv(socket_t *socket, uint8_t *data, size_t len) +{ + if (socket && data && len > 0) + { + ssize_t recvd = 0; + int flags = 0; +#if defined(POSIX_SOCKETS) + flags |= MSG_WAITALL; +#endif + SOSAL_PRINT(SOSAL_ZONE_SOCKET, "Waiting for "FMT_SIZE_T" data on socket %p to ptr %p\n", len, socket, data); + do { + ssize_t _recvd = 0; + int err = 0; + int sock = 0; + if (socket->is_server) + sock = socket->connected; + else + sock = socket->sock; + _recvd = recv(sock, &data[recvd], len-recvd, flags); + err = SOCKET_GETERROR; + if (_recvd == 0 && err != 0) { + SOSAL_PRINT(SOSAL_ZONE_WARNING, "recv() returned zero bytes with error! (errno=%d)\n", err); +#if defined(POSIX_SOCKETS) + if (err == EINVAL) { + SOSAL_PRINT(SOSAL_ZONE_WARNING, "recv(%d, %p, "FMT_SIZE_T", %08x)\n", sock, &data[recvd], len-(size_t)recvd, flags); + } +#endif + return false_e; + } + if (_recvd >= 0) + recvd += _recvd; + else // error + { + recvd = _recvd; + break; + } + } while (recvd < (ssize_t)len); + if (recvd == 0) + return false_e; + else if (recvd == SOCKET_ERROR) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "SOSAL: Failed to recv data on socket! (errno=%d)\n", SOCKET_GETERROR); + return false_e; + } + else + { + socket->bytesRecv += recvd; + if (recvd != (ssize_t)len) { + SOSAL_PRINT(SOSAL_ZONE_WARNING, "SOSAL: ONLY RECEIVED "FMT_SSIZE_T" BYTES ON SOCKET %p, WANTED "FMT_SIZE_T"\n", recvd, socket, len); + } else { + SOSAL_PRINT(SOSAL_ZONE_SOCKET, "SOSAL: Recv "FMT_SSIZE_T" bytes on Socket %p\n", recvd, socket); + } + return true_e; + } + } + else + return false_e; +} + +void socket_disconnect(socket_t * socket) +{ + if (socket) + { + if (socket->is_server) + SOCKET_CLOSE(socket->connected); + else + SOCKET_CLOSE(socket->sock); + } +} + +void socket_deinit(socket_t *socket) +{ + if (socket) + { + if (socket->is_server) + SOCKET_CLOSE(socket->sock); + memset(socket, 0, sizeof(socket_t)); + free(socket); + } + SOCKET_DEINIT(); +} + +uint32_t socket_hostname(char *string) +{ + struct hostent *host = NULL; + uint32_t ipaddr = 0; + struct in_addr *addr = NULL; + + SOCKET_INIT(); + + host = gethostbyname((const char *)string); + if (host) + { +#if defined(DARWIN) + addr = (struct in_addr *)host->h_addr_list[0]; +#else + addr = (struct in_addr *)host->h_addr; +#endif + if (addr) + { + ipaddr = addr->s_addr; +#if defined(WIN32) && !defined(CYGWIN) + SOSAL_PRINT(SOSAL_ZONE_SOCKET, "Host name %s resolves to %u.%u.%u.%u (errno=%d)\n", + string, + addr->s_net,addr->s_host,addr->s_lh,addr->s_impno, + SOCKET_GETERROR); +#endif + } + else + { + /// @todo Host address structure was NULL + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to resolve host name %s\n", string); + } + } + else + { + /// @todo Host structure was NULLs + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to resolve host name %s\n", string); + } + return ipaddr; +} + +void socket_info(socket_t *socket) +{ + socket = socket; + SOSAL_PRINT(SOSAL_ZONE_SOCKET, "Send: "FMT_SSIZE_T" bytes\n", socket->bytesSend); + SOSAL_PRINT(SOSAL_ZONE_SOCKET, "Recv: "FMT_SSIZE_T" bytes\n", socket->bytesRecv); +} + +#include + +static event_t f_wait; +#define DATA_SIZE (320*240*2) // Simulate QVGA UYVY data +#define DATA_COUNT (30*10) // Simulate 30fps for 10 seconds. + +void memfill(uint8_t *ptr, size_t len) +{ + uint32_t i; + for (i = 0; i < len; i++) + { + ptr[i] = (uint8_t)(i & 0xFF); + } +} + +static thread_ret_t thread_server(void *arg) +{ + socket_t *server = (socket_t *)arg; + uint8_t data[DATA_SIZE]; + uint32_t count; + + event_set(&f_wait); // tell the client that the server is about to start + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Server Thread Running\n"); + if (socket_connect(server) == true_e) + { + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Server Started!\n"); + socket_recv(server, (uint8_t *)&count, sizeof(count)); + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Echoing %u (0x%08x) times\n", count, count); + while (count--) + { + socket_recv(server, data, sizeof(data)); + socket_send(server, data, sizeof(data)); + } + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Echo'd\n"); + socket_disconnect(server); + } + else + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Could not start server!\n"); + thread_exit(0); +} + +static thread_ret_t thread_client(void *arg) +{ + socket_t *client = (socket_t *)arg; + uint32_t count = DATA_COUNT; + uint32_t size = DATA_SIZE * count; + uint8_t data[DATA_SIZE]; + double rate = 0.0f; + + memfill(data, DATA_SIZE); + if (event_wait(&f_wait, 1000) == true_e) // wait for the server to start + { + if (socket_connect(client) == true_e) + { + profiler_t perf; + profiler_clear(&perf); + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Connected Client\n"); + + profiler_start(&perf); + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Echoing %u (0x%08x) times\n", count, count); + socket_send(client, (uint8_t *)&count, sizeof(count)); + + while (count--) + { + socket_send(client, data, DATA_SIZE); + memset(data, 0, DATA_SIZE); + socket_recv(client, data, DATA_SIZE); + } + socket_info(client); + socket_disconnect(client); + profiler_stop(&perf); + rate = (double)size*rtimer_freq()/perf.avgTime; + rate /= 1000000; + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Perf: "FMT_RTIMER_T" (Rate: %.2lf MBps)\n", perf.avgTime,rate); + if (data[1] == 0x01) { + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Ping/Pong SUCCESS!\n"); + } else { + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Ping/Pong FAILED!\n"); + } + } + else + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Could not connect to server!\n"); + } + thread_exit(0); +} + +static bool_e no_server; +static bool_e no_client; +static option_t opts[] = { + {OPTION_TYPE_BOOL, &no_server, sizeof(bool_e), "-ns", "--no-server", "Disables the server"}, + {OPTION_TYPE_BOOL, &no_client, sizeof(bool_e), "-nc", "--no-client", "Disables the client"}, +}; + +bool_e socket_unittest(int argc, char *argv[]) +{ + thread_t server_thread = 0; + thread_t client_thread = 0; + uint32_t address = socket_hostname("127.0.0.1"); + socket_t *server = NULL; + socket_t *client = NULL; + bool_e ret = true_e; + + no_server = false_e; + no_client = false_e; + + option_process(argc, argv, opts, dimof(opts)); + + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Starting Socket Test!\n"); + + event_init(&f_wait, true_e); + + if (!no_server) + server = socket_init(SOCKET_IP_ANY, 1234, SOCKET_TCP, true_e); + else + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Server is not launched!\n"); + + if (!no_client) + client = socket_init(address, 1234, SOCKET_TCP, false_e); + else + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Client is not launched!\n"); + + if ((no_server || server) && (no_client || client)) + { + if (!no_server) + server_thread = thread_create(thread_server, server); + else if (!no_client) + event_set(&f_wait); + if (!no_client) client_thread = thread_create(thread_client, client); + + if (!no_server) thread_join(server_thread); + if (!no_client) thread_join(client_thread); + } + else + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Could not create sockets!\n"); + + if (!no_server) socket_deinit(server); + if (!no_client) socket_deinit(client); + + event_deinit(&f_wait); + + return ret; +} + +#endif diff --git a/source/sosal/status.c b/source/sosal/status.c new file mode 100644 index 0000000..3f63bf1 --- /dev/null +++ b/source/sosal/status.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#if defined(WIN32) && !defined(CYGWIN) + /*! \brief Used to co-relate the Windows codes to status_e. + * \ingroup group_status + */ + status_to_error correlations[] = { + {STATUS_NO_MAPPING, ERROR_NOT_ENOUGH_MEMORY}, + {STATUS_NOT_ENOUGH_MEMORY, ERROR_NOT_ENOUGH_MEMORY}, + {STATUS_INVALID_PARAMETER, ERROR_INVALID_PARAMETER}, + {STATUS_INVALID_STATE, ERROR_BAD_PIPE}, + {STATUS_NOT_IMPLEMENTED, ERROR_CALL_NOT_IMPLEMENTED}, + {STATUS_NO_RESOURCES, ERROR_BUSY}, + {STATUS_TIMEDOUT, ERROR_TIMEOUT}, + {STATUS_CATASTROPHIC, ERROR_GEN_FAILURE}, + {STATUS_FAILURE, ERROR_GEN_FAILURE}, + {STATUS_END_OF_FILE, ERROR_HANDLE_EOF}, + {STATUS_FILE_NOT_FOUND, ERROR_FILE_NOT_FOUND}, + {STATUS_SUCCESS, 1}, + }; +#elif defined(SYSBIOS) +/*! \brief Used to co-relate the SYSBIOS codes to status_e. + * \ingroup group_status + */ +status_to_error correlations[] = { + {STATUS_SUCCESS, 0}, +}; +#else +/*! \brief Used to co-relate the POSIX codes to status_e. + * \ingroup group_status + */ +status_to_error correlations[] = { + {STATUS_NO_MAPPING, EADDRNOTAVAIL}, + {STATUS_NOT_ENOUGH_MEMORY, ENOMEM}, + {STATUS_INVALID_PARAMETER, EINVAL}, + {STATUS_INVALID_STATE, ENOSYS}, + {STATUS_NOT_IMPLEMENTED, ENOTSUP}, + {STATUS_NO_RESOURCES, 0}, + {STATUS_TIMEDOUT, ETIMEDOUT}, + {STATUS_CATASTROPHIC, ENOSYS}, + {STATUS_FAILURE, 0}, + {STATUS_END_OF_FILE, 0}, + {STATUS_FILE_NOT_FOUND, 0}, + {STATUS_SUCCESS, 1}, + }; +#endif + +long status_convert(status_e status) +{ + uint32_t i = 0; + for (i = 0; i < dimof(correlations); i++) + { + if (status == correlations[i].status) + return correlations[i].code; + } + return -1; // generic error just about everywhere. +} + diff --git a/source/sosal/thread.c b/source/sosal/thread.c new file mode 100644 index 0000000..3c44f9e --- /dev/null +++ b/source/sosal/thread.c @@ -0,0 +1,601 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#ifdef SYSBIOS +#include +//#include //default bios malloc,... used +//#include +#include +#include +#endif +#include +#include // unit test +#include // unit test +#include // unit test +#include + +#if defined(ANDROID) +#include +#include +int sched_setaffinity(int pid, size_t len, unsigned long *cpusetp) +{ + return syscall(__NR_sched_setaffinity, pid, len, cpusetp); +} +#elif defined(LINUX) +#include +#endif + +#ifdef POSIX +static bool_e f_initialized = false_e; +#endif + +#if defined(POSIX) || defined(ANDROID) || defined(LINUX) +static mutex_t f_lock; +#endif + +void thread_nextaffinity() +{ +#if defined(ANDROID) + static unsigned long cpu_mask = ((1 << TARGET_NUM_CORES) - 1); + static unsigned long cpu_inc = 1; + unsigned long mask; + mutex_lock(&f_lock); + mask = 0; + mask = cpu_inc; + cpu_inc = (cpu_inc + 1) & cpu_mask; + if (cpu_inc == 0) + cpu_inc = 1; + sched_setaffinity(gettid(), sizeof(mask), &mask); + mutex_unlock(&f_lock); +#elif defined(LINUX) + static unsigned long cpu_mask = ((1 << TARGET_NUM_CORES) - 1); + static unsigned long cpu_inc = 1; + unsigned long s; + cpu_set_t mask; + mutex_lock(&f_lock); + CPU_ZERO(&mask); + s = CPU_SET(cpu_inc, &mask); + cpu_inc = (cpu_inc + 1) & cpu_mask; + if (cpu_inc == 0) + cpu_inc = 1; + sched_setaffinity(getpid(), sizeof(mask), &mask); + mutex_unlock(&f_lock); +#endif +} + +#ifdef SYSBIOS +#ifndef JOIN_SEMAPHORE +ack_t* sosal_add_ack(thread_t pThrdHdl) +{ + ack_t* pNew; + + pNew = malloc(sizeof(ack_t)); + if(!pNew) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Can't allocate memory for new join ACK!\n"); + return NULL; + } + + pNew->next = pThrdHdl->pAckList; + pThrdHdl->pAckList = pNew; + + pNew->exit_event_ack = malloc(sizeof(event_t)); + if(!pNew->exit_event_ack) { + free(pNew); + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Can't allocate memory for new join ACK event!\n"); + return NULL; + } + + event_init(pNew->exit_event_ack, false_e); + return (pNew); +} + +void sosal_free_ack(ack_t *pAck) +{ + event_deinit(pAck->exit_event_ack); + free(pAck->exit_event_ack); + free(pAck); +} +#endif + +void thread_main_func_translate(uint32_t argc, void* argv) +{ + thread_t sosal_thread_hdl = argv; + + /* Run client main func */ + sosal_thread_hdl->exit_code = sosal_thread_hdl->client_func(sosal_thread_hdl->client_arg); + + sosal_thread_hdl->bTaskReady = true_e; +#ifdef JOIN_SEMAPHORE + { + semaphore_t *semaphore_hdl; + + semaphore_hdl = sosal_thread_hdl->join_semaphore; + SOSAL_PRINT(SOSAL_ZONE_THREAD, "thread_main_func_translate semaphore post (%d)\n", sosal_thread_hdl->join_number); + while(sosal_thread_hdl->join_number) { + semaphore_post(semaphore_hdl); /* signal next join task in the queue to continue */ + sosal_thread_hdl->join_number--; + } + SOSAL_PRINT(SOSAL_ZONE_THREAD, "thread_main_func_translate semaphore delete (%d)\n", sosal_thread_hdl->join_number); + semaphore_delete(semaphore_hdl); + mutex_deinit(sosal_thread_hdl->join_mutex); + } + /* extra task memory releasing */ + free(sosal_thread_hdl->join_semaphore); + sosal_thread_hdl->join_semaphore = NULL; + free(sosal_thread_hdl->join_mutex); +#else + /* Event mode signaling */ + //SOSAL_PRINT(SOSAL_ZONE_THREAD, "thread_main_func_translate send ready event\n"); + event_set(sosal_thread_hdl->exit_event); + + // Wait all task to receive join event + while (sosal_thread_hdl->pAckList) { + ack_t *pAck; + pAck = sosal_thread_hdl->pAckList; + //SOSAL_PRINT(SOSAL_ZONE_THREAD, "thread_main_func_translate waits for ack\n"); + event_wait(pAck->exit_event_ack, EVENT_FOREVER); + SOSAL_PRINT(SOSAL_ZONE_THREAD, "thread_main_func_translate ack received\n"); + sosal_thread_hdl->pAckList = pAck->next; + sosal_free_ack(pAck); + } + event_deinit(sosal_thread_hdl->exit_event); + //SOSAL_PRINT(SOSAL_ZONE_THREAD, "thread_main_func_translate event deinited\n"); + + /* extra task memory releasing */ + free(sosal_thread_hdl->exit_event); +#endif + + + free(sosal_thread_hdl); + sosal_thread_hdl = NULL; + SOSAL_PRINT(SOSAL_ZONE_THREAD, "thread_main_func_translate clean up\n"); +} + +/* TODO: an alternative for task killing is to add task delete function and hook in XDC +void thread_delete(thread_t *sosal_thread_hdl) +{ + + Task_delete(&((*sosal_thread_hdl)->thread_hdl)); + (*sosal_thread_hdl)->thread_hdl = NULL; + + free((*sosal_thread_hdl)->exit_event); + free((*sosal_thread_hdl)->join_semaphore); + // free((*sosal_thread_hdl)->stack_ptr); + free((*sosal_thread_hdl)); +} + +void exitFxn(Task_Handle task) +{ + thread_t sosal_thread_hdl; + + sosal_thread_hdl = task->arg1; + + thread_delete(sosal_thread_hdl); +} +*/ +#endif + +thread_t thread_create(thread_f func, void * arg) +{ +#ifdef POSIX + thread_t handle = 0; + pthread_t p; + + if (f_initialized == false_e) + { + mutex_init(&f_lock); + f_initialized = true_e; + } + + int err = pthread_create(&p, NULL, func, arg); + if (err == EINVAL) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Invalid settings in pthread_attr\n"); + } else if (err == EAGAIN) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Insufficient resources to start thread!\n"); + } + handle = p; + return handle; +#elif defined(SYSBIOS) + thread_t sosal_thread_hdl; +#ifdef JOIN_SEMAPHORE + semaphore_t *semaphore_hdl; + mutex_t *mutex_hdl; +#else + event_t *event_hdl; +#endif + /* void *stack_ptr; */ + bool_e ret_val; + Task_Params taskParams; + long pid = 0; + + sosal_thread_hdl = malloc(sizeof(*sosal_thread_hdl)); + if(!sosal_thread_hdl) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Can't allocate memory for thread SOSAL hdl!\n"); + return NULL; + } + +#ifdef JOIN_SEMAPHORE + semaphore_hdl = malloc(sizeof(semaphore_t)); + if(!semaphore_hdl) { + free(sosal_thread_hdl); + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Can't create join semaphore!\n"); + return NULL; + } + + ret_val = semaphore_create(semaphore_hdl, 0, (bool_e)0); + if(!ret_val) { + free(semaphore_hdl); + free(sosal_thread_hdl); + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Can't create exit event!\n"); + return NULL; + } + + sosal_thread_hdl->join_semaphore = semaphore_hdl; + + mutex_hdl = malloc(sizeof(mutex_t)); + if(!mutex_hdl) { + free(semaphore_hdl); + free(sosal_thread_hdl); + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Can't create join semaphore!\n"); + return NULL; + } + + mutex_init(mutex_hdl); + + sosal_thread_hdl->join_mutex = mutex_hdl; + sosal_thread_hdl->join_number = 0; +#else + event_hdl = malloc(sizeof(event_t)); + if(!event_hdl) { + free(sosal_thread_hdl); + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Can't allocate memory for exit event!\n"); + return NULL; + } + +/* TODO: It isn't necessary to allocate stack memory + stack_ptr = malloc(SYSBIOS_DEFAULT_STASK_SIZE); + if(!stack_ptr) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Can't allocate memory for thread stack!\n"); + free(sosal_thread_hdl->exit_event); + free(sosal_thread_hdl); + return NULL; + } + sosal_thread_hdl->stack_ptr = stack_ptr; +*/ + ret_val = event_init(event_hdl, false_e); + if(!ret_val) { + /* free(sosal_thread_hdl->stack_ptr); */ + free(event_hdl); + free(sosal_thread_hdl); + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Can't create exit event!\n"); + return NULL; + } + + sosal_thread_hdl->exit_event = event_hdl; + sosal_thread_hdl->pAckList = NULL; +#endif + + sosal_thread_hdl->client_arg = arg; + sosal_thread_hdl->client_func = func; + + Task_Params_init(&taskParams); + + taskParams.arg0 = 1; + taskParams.arg1 = (UArg)(sosal_thread_hdl); + taskParams.env = NULL; + taskParams.priority = SYSBIOS_DEFAULT_PRIORITY; + /* taskParams.stack = (void *)stack_ptr;*/ + taskParams.stackSize = SYSBIOS_DEFAULT_STASK_SIZE; + taskParams.instance->name = NULL; + + pid = (long) Task_getEnv(Task_self()); + taskParams.env = (void *) pid; + + sosal_thread_hdl->thread_hdl = Task_create((Task_FuncPtr)thread_main_func_translate, &taskParams, NULL); + sosal_thread_hdl->bTaskReady = false_e; + return sosal_thread_hdl; +#else + thread_t handle = 0; + HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func, arg, CREATE_SUSPENDED, NULL); + if (hThread) + { + ResumeThread(hThread); + } + handle = hThread; + return handle; +#endif +} + +void thread_return(thread_ret_t r) +{ +#ifdef POSIX + pthread_exit(r); +#endif +} + +thread_ret_t thread_join(thread_t t) +{ + thread_ret_t r = 0; +#ifdef POSIX + int err = pthread_join(t, &r); + SOSAL_PRINT(SOSAL_ZONE_THREAD, "thread_join("THREAD_FMT") returned %d ("THREAD_RET_FMT")\n", t, err, r); + if (err == EINVAL) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Invalid Thread Handle or Thread is not joinable or another thread is joining with this thread\n"); + } else if (err == ESRCH) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! No Thread with that Handle\n"); + } else if (err == EDEADLK) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Thread Deadlock Detected!\n"); + } +#ifndef ANDROID + if (r == PTHREAD_CANCELED) { + SOSAL_PRINT(SOSAL_ZONE_WARNING, "WARNING! Thread was cancelled!\n"); + } +#endif +#elif defined(SYSBIOS) + + if (t != NULL) { + if (t->bTaskReady == false_e) { +#ifdef JOIN_SEMAPHORE + semaphore_t *semaphore_hdl; + mutex_t *mutex_hdl; + semaphore_hdl = t->join_semaphore; + mutex_hdl = t->join_mutex; + mutex_lock(mutex_hdl); + t->join_number++; + mutex_unlock(mutex_hdl); + + SOSAL_PRINT(SOSAL_ZONE_THREAD, "thread_join waits for semaphore\n"); + semaphore_wait(semaphore_hdl); + r = t->exit_code; +#else + ack_t *pAck; + SOSAL_PRINT(SOSAL_ZONE_THREAD, "thread_join add ack\n"); + pAck = sosal_add_ack(t); + SOSAL_PRINT(SOSAL_ZONE_THREAD, "thread_join start to wait for ack\n"); + event_wait(t->exit_event, EVENT_FOREVER); + r = t->exit_code; + SOSAL_PRINT(SOSAL_ZONE_THREAD, "thread_join got ack about TaskReady and raise event for ack\n"); + event_set(pAck->exit_event_ack); +#endif + } else { + r = t->exit_code; + SOSAL_PRINT(SOSAL_ZONE_THREAD, "thread_join TaskReady found\n"); + } + SOSAL_PRINT(SOSAL_ZONE_THREAD, "thread_join ready exitcode=%d\n", r); + } else { + SOSAL_PRINT(SOSAL_ZONE_THREAD, "thread_join ERROR - null task\n"); + r = false_e; + } +#else + DWORD status = WaitForSingleObject(t, INFINITE); + if (status == WAIT_OBJECT_0) { + GetExitCodeThread(t, &r); + } else if (status == ERROR_INVALID_HANDLE) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Invalid Thread Handle\n"); + } +#endif + return r; +} + +void thread_msleep(int milliseconds) +{ +#ifdef POSIX + struct timespec time_spec; + struct timespec remainder; + int err = 0; + time_spec.tv_sec = milliseconds / 1000; + time_spec.tv_nsec = (milliseconds % 1000) * 1000000; + do { + //SOSAL_PRINT(SOSAL_ZONE_THREAD, "Sleeping until %lu sec:%lu ns\n",time_spec.tv_sec, time_spec.tv_nsec); + err = nanosleep(&time_spec, &remainder); + if (err == EINTR) { + SOSAL_PRINT(SOSAL_ZONE_WARNING, "WARNING! Thread was interrupted during sleep, need to sleep for %lu more ns\n", remainder.tv_nsec); + memcpy(&time_spec, &remainder, sizeof(struct timespec)); + memset(&remainder, 0, sizeof(struct timespec)); + } + else if (err != 0) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Nanosleep returned %d\n", err); + } + } while (err == EINTR); + +#elif defined(SYSBIOS) + /* + * Don't let nonzero timeout round to 0 - semantically very + * different + */ + uint32_t bios6_timeout; + + /* convert to us and transfer to ticks (Clock_tickPeriod in us) */ + bios6_timeout = (milliseconds*1000) / Clock_tickPeriod; + /* + * Don't let nonzero timeout round to 0 - semantically very + * different + */ + if (milliseconds && (!bios6_timeout)) { + bios6_timeout = 1; + } + Task_sleep(bios6_timeout); +#else + Sleep(milliseconds); +#endif +} + +static const thread_ret_t TEST_RET_VALUE = (thread_ret_t)42; + +static thread_ret_t thread_test(void *arg) +{ + uint32_t *pCounter = (uint32_t *)arg; + do + { +// SOSAL_PRINT(SOSAL_ZONE_THREAD, "main:thread_test is running back %d pass!\n", *pCounter); + thread_msleep(100); + } while ((*pCounter)--); + return TEST_RET_VALUE; +} + +typedef struct _pingpongevent_t { + event_t ping; + event_t pong; +} pingpongevent_t; + +static thread_ret_t thread_test_events(void *arg) +{ + pingpongevent_t *p = (pingpongevent_t *)arg; + + event_set(&p->ping); + + //SOSAL_PRINT(SOSAL_ZONE_THREAD, "Thread is waiting for event!\n"); + if (event_wait(&p->pong, 500)) + { + //SOSAL_PRINT(SOSAL_ZONE_THREAD, "Thread received event!\n"); + return TEST_RET_VALUE; + } + else + { + SOSAL_PRINT(SOSAL_ZONE_THREAD, "ERROR! Thread TIMEDOUT!!\n"); + } + return 0; +} + +typedef struct _msg_t { + value_t code; +} msg_t; + +typedef struct _msg_thread_t { + queue_t *msgs; + bool_e running; + event_t signal; +} msg_thread_t; + +static thread_ret_t thread_test_msgs(void *arg) +{ + msg_thread_t *msgt = (msg_thread_t *)arg; + msg_t msg; + event_set(&msgt->signal); + while (msgt->running) + { + //SOSAL_PRINT(SOSAL_ZONE_THREAD, "Waiting for queue read!\n"); + if (queue_read(msgt->msgs, true_e, &msg)) + { + //SOSAL_PRINT(SOSAL_ZONE_THREAD, "Msg: %u\n", msg.code); + if (msg.code == (value_t)TEST_RET_VALUE) + msgt->running = false_e; + } + else + { + SOSAL_PRINT(SOSAL_ZONE_THREAD, "ERROR! Failed to read from queue!\n"); + msgt->running = false_e; + } + } + return (thread_ret_t)msg.code; +} + +bool_e thread_unittest(int argc, char *argv[]) +{ + uint32_t i, counter = 10; + pingpongevent_t events; + int numErrors = 0; + bool_e verbose = false_e; + option_t hash_opts[] = { + {OPTION_TYPE_BOOL, &verbose, sizeof(bool_e), "-v", "--verbose", "Used to print out debugging information"}, + }; + msg_t msgs[] = {{3}, {9283}, {27}, {42}}; // last value == TEST_RET_VALUE + msg_thread_t msgt; + thread_t t; + thread_ret_t r; + + option_process(argc, argv, hash_opts, dimof(hash_opts)); + + if (verbose) { + SOSAL_PRINT(SOSAL_ZONE_THREAD, "===THREAD TEST===\n"); + } + + // simple start, stop test + t = thread_create(thread_test, &counter); + r = thread_join(t); + if (r != TEST_RET_VALUE) + numErrors++; + + if (verbose) { + SOSAL_PRINT(SOSAL_ZONE_THREAD, "===PING PONG TEST===\n"); + } + + // event test across threads + event_init(&events.ping, false_e); + event_init(&events.pong, false_e); + + t = thread_create(thread_test_events, &events); + if (verbose) { + SOSAL_PRINT(SOSAL_ZONE_THREAD, "Test is waiting for thread to wakeup!\n"); + } + if (event_wait(&events.ping, 500)) + { + if (verbose) + SOSAL_PRINT(SOSAL_ZONE_THREAD, "Received Event from Thread!\n"); + } + else + { + if (verbose) + SOSAL_PRINT(SOSAL_ZONE_THREAD, "ERROR! Thread Message Timedout!\n"); + } + if (verbose) SOSAL_PRINT(SOSAL_ZONE_THREAD, "Sending Event to Thread!\n"); + + event_set(&events.pong); + + r = thread_join(t); + SOSAL_PRINT(SOSAL_ZONE_THREAD, "=== THREAD JOIN exit = "THREAD_RET_FMT" ===\n", r); + if (r != TEST_RET_VALUE) + numErrors++; + event_deinit(&events.ping); + event_deinit(&events.pong); + + if (verbose) { + SOSAL_PRINT(SOSAL_ZONE_THREAD, "===QUEUE TEST===\n"); + } + + msgt.msgs = queue_create(2, sizeof(msg_t)); + msgt.running = true_e; + event_init(&msgt.signal, false_e); + t = thread_create(thread_test_msgs, &msgt); + if (verbose) + { + SOSAL_PRINT(SOSAL_ZONE_THREAD, "Waiting for thread to start!\n"); + SOSAL_PRINT(SOSAL_ZONE_THREAD, "Thread Started?(%s!)\n", (event_wait(&msgt.signal, 1000)?"true":"false")); + } + for (i = 0; i < dimof(msgs); i++) { + if (queue_write(msgt.msgs, true_e, &msgs[i]) == false_e) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Failed to write to queue!\n"); + } else { + if (verbose) SOSAL_PRINT(SOSAL_ZONE_THREAD, "Wrote message "FMT_SIZE_T" to the Queue!\n", msgs[i].code); + } + } + r = thread_join(t); + SOSAL_PRINT(SOSAL_ZONE_THREAD, "=== THREAD JOIN exit = "THREAD_RET_FMT" ===\n", r); + queue_destroy(msgt.msgs); + event_deinit(&msgt.signal); + + if (verbose) { + SOSAL_PRINT(SOSAL_ZONE_THREAD, "===THREAD TEST EXIT Errors=%d ===\n", numErrors); + } + + if (numErrors > 0) + return false_e; + else + return true_e; +} + diff --git a/source/sosal/threadpool.c b/source/sosal/threadpool.c new file mode 100644 index 0000000..fcb19e2 --- /dev/null +++ b/source/sosal/threadpool.c @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +void threadpool_destroy(threadpool_t *pool) +{ + if (pool) + { + uint32_t i; + for (i = 0; i < pool->numWorkers; i++) + { + queue_pop(pool->workers[i].queue); + thread_join(pool->workers[i].handle); + profiler_stop(&pool->workers[i].perf); + SOSAL_PRINT(SOSAL_ZONE_THREAD, "Worker %u Thread "THREAD_FMT" took %lf sec to die\n", pool->workers[i].index, pool->workers[i].handle, rtimer_to_sec(pool->workers[i].perf.tmpTime)); + pool->workers[i].handle = 0; + queue_destroy(pool->workers[i].queue); + pool->workers[i].queue = NULL; + } + free(pool->workers); + pool->workers = NULL; + semaphore_delete(&pool->sem); + event_deinit(&pool->completed); + free(pool); + } +} + +static thread_ret_t threadpool_worker(void *arg) +{ + threadpool_worker_t *worker = (threadpool_worker_t *)arg; + + profiler_stop(&worker->perf); + + SOSAL_PRINT(SOSAL_ZONE_THREAD, "Worker %u Thread "THREAD_FMT" running! (Launch took %lf sec)\n", worker->index, worker->handle, rtimer_to_sec(worker->perf.avgTime)); + + thread_nextaffinity(); + + profiler_clear(&worker->perf); + profiler_start(&worker->perf); + + while (queue_read(worker->queue, true_e, worker->data) == true_e) + { + worker->active = true_e; + profiler_stop(&worker->perf); + SOSAL_PRINT(SOSAL_ZONE_THREAD, "Worker %u Thread "THREAD_FMT" took %lf sec to get message\n", worker->index, worker->handle, rtimer_to_sec(worker->perf.tmpTime)); + worker->function(worker); // <=== WORK IS DONE HERE + semaphore_wait(&worker->pool->sem); + worker->pool->numCurrentItems--; + if (worker->pool->numCurrentItems <= 0) + event_set(&worker->pool->completed); + semaphore_post(&worker->pool->sem); + SOSAL_PRINT(SOSAL_ZONE_THREAD, "Worker %u Thread "THREAD_FMT" completed work, %u items left\n", worker->index, worker->handle, worker->pool->numCurrentItems); + profiler_start(&worker->perf); + worker->active = false_e; + } + SOSAL_PRINT(SOSAL_ZONE_THREAD, "Worker %u Thread "THREAD_FMT" exitting!\n", worker->index, worker->handle); + thread_exit(0); +} + +threadpool_t *threadpool_create(uint32_t numThreads, uint32_t numWorkItems, size_t sizeWorkItem, threadpool_f worker, void *arg) +{ + threadpool_t *pool = (threadpool_t *)calloc(1, sizeof(threadpool_t)); + if (pool) + { + uint32_t i; + semaphore_create(&pool->sem, 1, false_e); + pool->numWorkers = numThreads; + pool->numWorkItems = numWorkItems; + pool->sizeWorkItem = sizeWorkItem; + event_init(&pool->completed, false_e); + pool->workers = (threadpool_worker_t *)calloc(pool->numWorkers, sizeof(threadpool_worker_t)); + if (pool->workers) + { + for (i = 0; i < pool->numWorkers; i++) + { + pool->workers[i].data = calloc(1, sizeWorkItem); + pool->workers[i].queue = queue_create(numWorkItems, sizeWorkItem); + pool->workers[i].index = i; + pool->workers[i].arg = arg; + pool->workers[i].function = worker; + pool->workers[i].pool = pool; // back reference to top level info + profiler_clear(&pool->workers[i].perf); + profiler_start(&pool->workers[i].perf); + pool->workers[i].handle = thread_create(threadpool_worker, &pool->workers[i]); + } + } + } + return pool; +} + +bool_e threadpool_issue(threadpool_t *pool, void *workitems[], uint32_t numWorkItems) +{ + uint32_t i; + bool_e wrote = false_e; + + SOSAL_PRINT(SOSAL_ZONE_THREAD, "About to issue %u workitems!\n", numWorkItems); + semaphore_wait(&pool->sem); + event_reset(&pool->completed); // we're going to have items to work on, so clear the event + for (i = 0; i < numWorkItems; i++) + { + uint32_t index = 0xFFFFFFFF; + uint32_t count = 0; // cycle-detector + // issue the work to the next worker, but don't wait if it's full + do { + count++; + index = pool->nextWorkerIndex; + pool->nextWorkerIndex = (pool->nextWorkerIndex + 1) % pool->numWorkers; + pool->numCurrentItems++; + wrote = queue_write(pool->workers[index].queue, false_e, workitems[i]); + if (wrote == false_e) { + pool->numCurrentItems--; + } + SOSAL_PRINT(SOSAL_ZONE_THREAD, "Issued workitem %p to worker %u (%s)\n", workitems[i], index, (wrote?"TRUE":"FALSE")); + } while (wrote == false_e && count < pool->numWorkers); + // there's too much work to do, there's an overflow condition. some of the work may have been issued, others not. + if (wrote == false_e) + break; + } + + // if none of the writes worked for whatever reason, and we didn't have any previous pending work (how?) then set the completed event + if (pool->numCurrentItems == 0) + event_set(&pool->completed); + + semaphore_post(&pool->sem); + return wrote; +} + +bool_e threadpool_complete(threadpool_t *pool, bool_e blocking) +{ + if (blocking) + { + return event_wait(&pool->completed, EVENT_FOREVER); + } + else + { + if (pool->numCurrentItems == 0) + return true_e; + else + return false_e; + } +} + +typedef struct _threadpool_data_t { + uint32_t dummy; +} threadpool_data_t; + +typedef struct _threadpool_test_t { + semaphore_t sem; + uint32_t count; +} threadpool_test_t; + +static bool_e threadpool_test(threadpool_worker_t *worker) +{ + threadpool_test_t *test = (threadpool_test_t *)worker->arg; +#if defined(SOSAL_DEBUG) + threadpool_data_t *data = (threadpool_data_t *)worker->data; +#endif + semaphore_wait(&test->sem); + test->count++; + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "\t[%u] Worker %u Thread "THREAD_FMT" Dummy Data %u\n", test->count, worker->index, worker->handle, data->dummy); + semaphore_post(&test->sem); + return true_e; +} + +#ifdef THREADPOOL_TEST +uint32_t sosal_zone_mask; // declare a local version for testing +int main(int argc, char *argv[]) +#else +bool_e threadpool_unittest(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) +#endif +{ + threadpool_t *pool = NULL; + threadpool_test_t test; + uint32_t numWorkers = 5; + threadpool_data_t dummydata[2][10] = { + { {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}}, + {{10},{11},{12},{13},{14},{15},{16},{17},{18},{19}}, + }; + void *workitems[10]; + uint32_t i,j; + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + + // initialize test data + semaphore_create(&test.sem, 1, false_e); + test.count = 0; + + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Creating %u workers, for "FMT_CONST" workitems, with "FMT_CONST" queue space each\n", numWorkers, dimof(workitems), dimof(workitems)/numWorkers); + + // create the pool + pool = threadpool_create(numWorkers, dimof(workitems)/numWorkers, sizeof(threadpool_data_t), threadpool_test, &test); + + // let the threads startup and get attached to their queues. + // thread_msleep(100); + + for (j = 0; j < 2; j++) + { + for (i = 0; i < dimof(dummydata[j]); i++) + workitems[i] = &dummydata[j][i]; + + if (threadpool_issue(pool, workitems, dimof(workitems)) == true_e) + { + if (threadpool_complete(pool, true_e) == true_e) + { + semaphore_wait(&test.sem); + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Work %u Complete!\n", j); + semaphore_post(&test.sem); + } + } + } + threadpool_destroy(pool); + semaphore_delete(&test.sem); +#ifdef THREADPOOL_TEST + return 0; +#else + return true_e; +#endif +} diff --git a/source/sosal/uinput.c b/source/sosal/uinput.c new file mode 100644 index 0000000..ec702b7 --- /dev/null +++ b/source/sosal/uinput.c @@ -0,0 +1,738 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#ifdef UINPUT_TEST +#undef SOSAL_ZONE_MASK +#define SOSAL_ZONE_MASK 0xFFFFFFFF +#endif + +#if defined(_UINPUT_T_FUNCS) +#if defined(ANDROID) || defined(LINUX) + +void set_input_event(struct input_event *ie, int type, int code, int data) +{ + memset(ie, 0, sizeof(struct input_event)); + ie->type = type; + ie->code = code; + ie->value = data; +} + +#define UINPUT_SUPPORT_TOUCHSCREEN +#undef PLATFORM_HAS_MT +static const char *uidrv_names[] = { + "/dev/uinput", + "/dev/input/uinput", + "/dev/misc/uintput", +}; +static int numDrvNames = dimof(uidrv_names); + +uinput_t *uinput_open(char *dev_name) +{ + uinput_t *p = (uinput_t *)malloc(sizeof(uinput_t)); + if (p != NULL) + { + int i; + memset(p, 0, sizeof(uinput_t)); + for (i = 0; i < numDrvNames; i++) + { + p->ufile = open(uidrv_names[i], O_WRONLY|O_NDELAY); + if (p->ufile == -1) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to open %s\n",uidrv_names[i]); + } + else + { + int retcode = 0; + + strncpy(p->uud.name, dev_name, UINPUT_MAX_NAME_SIZE); + p->uud.id.version = 1; + p->uud.id.product = 0x9000; + p->uud.id.vendor = 0x0451; // TI's Vendor Code. + p->uud.id.bustype = BUS_USB; + +#ifdef UINPUT_SUPPORT_TOUCHSCREEN +#ifndef PLATFORM_HAS_MT + p->uud.absmax[ABS_X] = UINPUT_MAX_TOUCH_X; + p->uud.absmax[ABS_Y] = UINPUT_MAX_TOUCH_Y; + p->uud.absmax[ABS_Z] = 255; + p->uud.absmax[ABS_PRESSURE] = 255; + p->uud.absmax[ABS_RZ] = 255; + p->uud.absmax[ABS_HAT0X] = 255; + p->uud.absmax[ABS_HAT0Y] = 255; + p->uud.absmax[ABS_HAT1X] = 255; + p->uud.absmax[ABS_HAT1Y] = 255; + p->uud.absmax[ABS_TOOL_WIDTH] = 15; + p->uud.absmax[ABS_VOLUME] = 255; +#endif +#endif + retcode = write(p->ufile, &p->uud, sizeof(p->uud)); + if (retcode != sizeof(p->uud)) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Error! Write only wrote %d bytes (errno=%d) \n",retcode, errno); + close(p->ufile); + p->ufile = 0; + free(p); + p = NULL; + } + else + { + // Configure the types of bits we can process + ioctl(p->ufile, UI_SET_EVBIT, EV_SYN); // Synchronize + ioctl(p->ufile, UI_SET_EVBIT, EV_KEY); // Keyboards/Mice/Touchscreen + ioctl(p->ufile, UI_SET_EVBIT, EV_REL); // Mice + ioctl(p->ufile, UI_SET_EVBIT, EV_ABS); // Touchscreen + for (i = 0; i < 256; i++) + ioctl(p->ufile, UI_SET_KEYBIT, i); // All 8 bit chars + + ioctl(p->ufile, UI_SET_RELBIT, REL_X); // Mice + ioctl(p->ufile, UI_SET_RELBIT, REL_Y); // Mice + ioctl(p->ufile, UI_SET_KEYBIT, BTN_MOUSE); // Mice +#ifdef UINPUT_SUPPORT_TOUCHSCREEN +#ifndef PLATFORM_HAS_MT + ioctl(p->ufile, UI_SET_ABSBIT, ABS_X); // Touchscreen + ioctl(p->ufile, UI_SET_ABSBIT, ABS_Y); // Touchscreen + //ioctl(p->ufile, UI_SET_ABSBIT, ABS_Z); // Touchscreen + //ioctl(p->ufile, UI_SET_ABSBIT, ABS_RZ); // Touchscreen + //ioctl(p->ufile, UI_SET_ABSBIT, ABS_HAT0X); // Touchscreen + //ioctl(p->ufile, UI_SET_ABSBIT, ABS_HAT0Y); // Touchscreen + //ioctl(p->ufile, UI_SET_ABSBIT, ABS_HAT1X); // Touchscreen + //ioctl(p->ufile, UI_SET_ABSBIT, ABS_HAT1Y); // Touchscreen + //ioctl(p->ufile, UI_SET_ABSBIT, ABS_TOOL_WIDTH); // Touchscreen + //ioctl(p->ufile, UI_SET_ABSBIT, ABS_VOLUME); // Touchscreen + //ioctl(p->ufile, UI_SET_ABSBIT, ABS_PRESSURE); // Touchscreen + ioctl(p->ufile, UI_SET_KEYBIT, BTN_TOUCH); // Touchscreen +#else + ioctl(p->ufile, UI_SET_ABSBIT, ABS_MT_SLOT); + ioctl(p->ufile, UI_SET_ABSBIT, ABS_MT_TOUCH_MAJOR); // Multitouch + ioctl(p->ufile, UI_SET_ABSBIT, ABS_MT_TOUCH_MINOR); // Multitouch + ioctl(p->ufile, UI_SET_ABSBIT, ABS_MT_WIDTH_MAJOR); // Multitouch + ioctl(p->ufile, UI_SET_ABSBIT, ABS_MT_WIDTH_MINOR); // Multitouch + ioctl(p->ufile, UI_SET_ABSBIT, ABS_MT_ORIENTATION); // Multitouch + ioctl(p->ufile, UI_SET_ABSBIT, ABS_MT_POSITION_X); // Multitouch + ioctl(p->ufile, UI_SET_ABSBIT, ABS_MT_POSITION_Y); // Multitouch + ioctl(p->ufile, UI_SET_ABSBIT, ABS_MT_TOOL_TYPE); // Multitouch + ioctl(p->ufile, UI_SET_ABSBIT, ABS_MT_BLOB_ID); // Multitouch + ioctl(p->ufile, UI_SET_ABSBIT, ABS_MT_TRACKING_ID); // Multitouch + ioctl(p->ufile, UI_SET_ABSBIT, ABS_MT_PRESSURE); // Multitouch +#endif +#endif + retcode = ioctl(p->ufile, UI_DEV_CREATE); + if (retcode != 0) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Error! ioctl() => %d\n",retcode); + close(p->ufile); + p->ufile = 0; + free(p); + p = NULL; + } + else + { + SOSAL_PRINT(SOSAL_ZONE_UINPUT, "Create %s {%04x:%04x}\n", p->uud.name,p->uud.id.vendor,p->uud.id.product); + } + } + break; + } + } + if (i == numDrvNames) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to open any uinput device\n"); + free(p); + p = NULL; + } + } + if (p == NULL) { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "Failed to open or configure the uinput device!\n"); + } + return p; +} + +bool_e uinput_close(uinput_t *p) +{ + if (p != NULL && p->ufile != 0) + { + ioctl(p->ufile, UI_DEV_DESTROY); + close(p->ufile); + p->ufile = 0; + } + if (p != NULL) + { + free(p); + p = NULL; + } + return true_e; +} + +static bool_e send_input_event(int descriptor, uint16_t type, uint16_t code, int32_t value, struct timeval *t) +{ + struct input_event event; + size_t actual; + + memset(&event, 0, sizeof(event)); + t = t; //memcpy(&event.time, t, sizeof(struct timeval)); + event.type = type; + event.code = code; + event.value = value; + SOSAL_PRINT(SOSAL_ZONE_UINPUT, "uinput => [%04x, %04x, %08x] @ %lu:%lu\n", event.type, event.code, event.value, event.time.tv_sec, event.time.tv_usec); + actual = write(descriptor, &event, sizeof(event)); + if (actual == sizeof(event)) + return true_e; + else + return false_e; +} + +bool_e uinput_send(uinput_t *p, input_t *in) +{ + if (p != NULL && p->ufile > 0) + { + struct timeval t; + bool_e ret = false_e; + + gettimeofday(&t, NULL); + + if (in->type == INPUT_TYPE_KEY) + { + ret = send_input_event(p->ufile, EV_KEY, in->data.key.code, in->data.key.state, &t); + ret = send_input_event(p->ufile, EV_SYN, SYN_REPORT, 0, &t); + } + if (in->type == INPUT_TYPE_MOUSE) + { + ret = send_input_event(p->ufile, EV_REL, REL_X, in->data.mouse.dx, &t); + ret = send_input_event(p->ufile, EV_REL, REL_Y, in->data.mouse.dx, &t); + ret = send_input_event(p->ufile, EV_SYN, SYN_REPORT, 0, &t); + } +#ifdef UINPUT_SUPPORT_TOUCHSCREEN + if (in->type == INPUT_TYPE_TOUCH) + { + int touched = (in->data.touch.pressure > 0 ? 1 : 0); +#ifndef PLATFORM_HAS_MT + ret = send_input_event(p->ufile, EV_ABS, ABS_X, in->data.touch.location_x, &t); + ret = send_input_event(p->ufile, EV_ABS, ABS_Y, in->data.touch.location_y, &t); + /* + ret = send_input_event(p->ufile, EV_ABS, ABS_Z, in->data.touch.pressure, &t); + ret = send_input_event(p->ufile, EV_ABS, ABS_RZ, 0, &t); + ret = send_input_event(p->ufile, EV_ABS, ABS_HAT0X, 0, &t); + ret = send_input_event(p->ufile, EV_ABS, ABS_HAT0Y, 0, &t); + ret = send_input_event(p->ufile, EV_ABS, ABS_HAT1X, 0, &t); + ret = send_input_event(p->ufile, EV_ABS, ABS_HAT1Y, 0, &t); + ret = send_input_event(p->ufile, EV_ABS, ABS_TOOL_WIDTH, in->data.touch.major_width * in->data.touch.minor_width, &t); + ret = send_input_event(p->ufile, EV_ABS, ABS_VOLUME, 0, &t); + */ + ret = send_input_event(p->ufile, EV_KEY, BTN_TOUCH, touched, &t); + //ret = send_input_event(p->ufile, EV_ABS, ABS_PRESSURE, in->data.touch.pressure, &t); + ret = send_input_event(p->ufile, EV_SYN, SYN_REPORT, 0, &t); +#else + if (touched) + { + ret = send_input_event(p->ufile, EV_ABS, ABS_MT_POSITION_X, in->data.touch.location_x, &t); + ret = send_input_event(p->ufile, EV_ABS, ABS_MT_POSITION_Y, in->data.touch.location_y, &t); + ret = send_input_event(p->ufile, EV_ABS, ABS_MT_PRESSURE, in->data.touch.pressure, &t); + ret = send_input_event(p->ufile, EV_ABS, ABS_MT_TOUCH_MAJOR, in->data.touch.major_width, &t); + ret = send_input_event(p->ufile, EV_ABS, ABS_MT_TOUCH_MINOR, in->data.touch.minor_width, &t); + ret = send_input_event(p->ufile, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER, &t); + } + ret = send_input_event(p->ufile, EV_SYN, SYN_MT_REPORT, 0, &t); + ret = send_input_event(p->ufile, EV_SYN, SYN_REPORT, 0, &t); +#endif + } +#endif + if (in->type == INPUT_TYPE_JOYSTICK) + { + ret = send_input_event(p->ufile, EV_ABS, ABS_X, in->data.joy.vx, &t); + ret = send_input_event(p->ufile, EV_ABS, ABS_Y, in->data.joy.vy, &t); + ret = send_input_event(p->ufile, EV_SYN, SYN_REPORT, 0, &t); + } + return ret; + } + else + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR: uinput device is not initialized!\n"); + return false_e; + } +} + +#elif defined(WIN32) || defined(UNDER_CE) || defined(CYGWIN) +#include +typedef struct _find_window_t { + char *strName; + HWND hTarget; +} FindWindow_t; + +BOOL CALLBACK FindWindowHandleCallback(HWND hWindow, LPARAM lParam) +{ + FindWindow_t *fWin = (FindWindow_t *)lParam; + char className[MAX_PATH]; + char windowName[MAX_PATH]; + + GetClassName(hWindow, className,sizeof(className)); + GetWindowText(hWindow, windowName,sizeof(windowName)); + + if (className[0] == 0) + return FALSE; + + SOSAL_PRINT(SOSAL_ZONE_UINPUT, "Window HWND %p %s:%s\n", hWindow, className, windowName); + if (strcmp(fWin->strName, className) == 0) + { + fWin->hTarget = hWindow; + return FALSE; + } + return TRUE; +} + +HWND FindWindowByName(char *pName) +{ + FindWindow_t fWin; + + fWin.strName = pName; + fWin.hTarget = NULL; + + if (EnumWindows(FindWindowHandleCallback, (LPARAM)&fWin)) + { + if (fWin.hTarget != NULL) { + SOSAL_PRINT(SOSAL_ZONE_UINPUT, "Found %s at %p\n", fWin.strName, fWin.hTarget); + } + } + return fWin.hTarget; +} + +uinput_t *uinput_open(char *dev_name) +{ + uinput_t *p = (uinput_t *)malloc(sizeof(uinput_t)); + if (p != NULL) + { + // find the requested window + p->hWindow = FindWindowByName(dev_name); + + if (p->hWindow == NULL) + { + SOSAL_PRINT(SOSAL_ZONE_ERROR, "ERROR! Window %s not found!\n",dev_name); + free(p); + p = NULL; + } + else + { + SOSAL_PRINT(SOSAL_ZONE_UINPUT, "Retrievd HWND %p!\n", p->hWindow); + } + } + return p; +} + +bool_e uinput_close(uinput_t *p) +{ + if (p != NULL) + { + free(p); + } + return true_e; +} + +bool_e uinput_send(uinput_t *p, input_t *in) +{ + INPUT input; + + memset(&input, 0, sizeof(input)); + + if (in->type == INPUT_TYPE_KEY) + { + SetForegroundWindow(p->hWindow); + input.type = INPUT_KEYBOARD; + input.ki.wVk = in->data.key.code; + input.ki.wScan = 0; + if (in->data.key.state == INPUT_KEY_STATE_UP) + input.ki.dwFlags = KEYEVENTF_KEYUP; + else + input.ki.dwFlags = 0; + input.ki.time = 0; + input.ki.dwExtraInfo = GetMessageExtraInfo(); + SOSAL_PRINT(SOSAL_ZONE_UINPUT, "Keyboard: 0x%04x flags: 0%08x\n",input.ki.wVk,input.ki.dwFlags); + } + else if (in->type == INPUT_TYPE_MOUSE) + { + SetActiveWindow(p->hWindow); + SetFocus(p->hWindow); + input.type = INPUT_MOUSE; + input.mi.dx = in->data.mouse.dx; + input.mi.dy = in->data.mouse.dy; + input.mi.mouseData = 0; + input.mi.dwFlags = MOUSEEVENTF_MOVE; + input.mi.dwExtraInfo = GetMessageExtraInfo(); + SOSAL_PRINT(SOSAL_ZONE_UINPUT, "Mouse: (%d, %d} => {%d, %d}\n", in->data.mouse.dx, in->data.mouse.dy,input.mi.dx, input.mi.dy); + } + else if (input.type == INPUT_HARDWARE) + { + //input.hi. + } + return (int)SendInput(1, &input, sizeof(input)); +} + +#elif defined(__QNX__) + +uinput_t *uinput_open(char *dev_name) +{ + int err; + uinput_t *p = (uinput_t *)calloc(1, sizeof(uinput_t)); + if (p) + { + int nDisplays = 0; + screen_display_t *displays = NULL; + err = screen_create_context(&p->context, SCREEN_INPUT_PROVIDER_CONTEXT); + err = screen_get_context_property_iv(p->context, SCREEN_PROPERTY_DISPLAY_COUNT, &nDisplays); + displays = (screen_display_t *)calloc(nDisplays, sizeof(screen_display_t *)); + err = screen_get_context_property_pv(p->context, SCREEN_PROPERTY_DISPLAYS, (void **)displays); + p->display = displays[0]; /// @todo take the first one? + } + return p; +} + +bool_e uinput_close(uinput_t * p) +{ + if (p) + { + screen_destroy_context(p->context); + free(p); + } + return true_e; +} + +bool_e uinput_send(uinput_t * p, input_t * in) +{ + if (p) + { + if (in->type == INPUT_TYPE_KEY) + { + int err, val; + bool_e ret = true_e; + screen_event_t ev; + err = screen_create_event(&ev); + if (err) ret = false_e; + val = SCREEN_EVENT_KEYBOARD; + err = screen_set_event_property_iv(ev, SCREEN_PROPERTY_TYPE, &val); + if (err) ret = false_e; + val = KEY_SYM_VALID; + if (in->data.key.state == INPUT_KEY_STATE_DOWN) + val |= KEY_DOWN; + err = screen_set_event_property_iv(ev, SCREEN_PROPERTY_KEY_FLAGS, &val); + if (err) ret = false_e; + val = in->data.key.code; + err = screen_set_event_property_iv(ev, SCREEN_PROPERTY_KEY_SYM, &val); + if (err) ret = false_e; + err = screen_inject_event(p->display, ev); + if (err) ret = false_e; + screen_destroy_event(ev); + SOSAL_PRINT(SOSAL_ZONE_UINPUT, "Key inject err=%d\n", err); + return ret; + } + else + return false_e; + } + else + return false_e; +} + +#endif + +typedef struct _ascii_to_key_t { + uint16_t key; + char ascii; +} ASCII_to_Key_t; + +ASCII_to_Key_t ktable[] = { +#if defined(LINUX) + {KEY_1, '1'},{KEY_2, '2'},{KEY_3, '3'},{KEY_4, '4'},{KEY_5, '5'},{KEY_6, '6'}, + {KEY_7, '7'},{KEY_8, '8'},{KEY_9, '9'},{KEY_Q, 'Q'},{KEY_W, 'W'},{KEY_E, 'E'}, + {KEY_R, 'R'},{KEY_T, 'T'},{KEY_Y, 'Y'},{KEY_U, 'U'},{KEY_I, 'I'},{KEY_O, 'O'}, + {KEY_P, 'P'},{KEY_A, 'A'},{KEY_S, 'S'},{KEY_D, 'D'},{KEY_F, 'F'},{KEY_G, 'G'}, + {KEY_H, 'H'},{KEY_J, 'J'},{KEY_K, 'K'},{KEY_L, 'L'},{KEY_Z, 'Z'},{KEY_X, 'X'}, + {KEY_C, 'C'},{KEY_V, 'V'},{KEY_B, 'B'},{KEY_N, 'N'},{KEY_M, 'M'},{KEY_SPACE, ' '}, + {KEY_MINUS,'-'},{KEY_TAB,'\t'},{KEY_ENTER,'\n'}, +#elif defined(WIN32) || defined(UNDER_CE) || defined(CYGWIN) + {VK_TAB, '\t'}, + {VK_RETURN, '\n'}, + {VK_CLEAR, '\r'}, + {VK_SPACE, ' '}, + {VK_OEM_4, '['}, + {VK_OEM_6, ']'}, +#elif defined(__QNX__) + {KEYCODE_ONE, '1'},{KEYCODE_TWO, '2'},{KEYCODE_THREE, '3'},{KEYCODE_FOUR, '4'},{KEYCODE_FIVE, '5'}, + {KEYCODE_SIX, '6'},{KEYCODE_SEVEN, '7'},{KEYCODE_EIGHT, '8'},{KEYCODE_NINE, '9'},{KEYCODE_ZERO, '0'}, + {KEYCODE_A, 'A'},{KEYCODE_B, 'B'},{KEYCODE_C, 'C'},{KEYCODE_D, 'D'},{KEYCODE_E, 'E'}, + {KEYCODE_F, 'F'},{KEYCODE_G, 'G'},{KEYCODE_H, 'H'},{KEYCODE_I, 'I'},{KEYCODE_J, 'J'}, + {KEYCODE_K, 'K'},{KEYCODE_L, 'L'},{KEYCODE_M, 'M'},{KEYCODE_N, 'N'},{KEYCODE_O, 'O'}, + {KEYCODE_P, 'P'},{KEYCODE_Q, 'Q'},{KEYCODE_R, 'R'},{KEYCODE_S, 'S'},{KEYCODE_T, 'T'}, + {KEYCODE_U, 'U'},{KEYCODE_V, 'V'},{KEYCODE_W, 'W'},{KEYCODE_X, 'X'},{KEYCODE_Y, 'Y'}, + {KEYCODE_Z, 'Z'}, +#endif +}; +uint32_t numKTable = dimof(ktable); + +static uint16_t GetKeyFromASCII(char k) +{ + uint32_t i; + uint16_t key; +#if defined(LINUX) + key = KEY_QUESTION; + for (i = 0; i < numKTable; i++) + { + if (k == ktable[i].ascii) + { + key = ktable[i].key; + break; + } + } +#elif defined(WIN32) || defined(UNDER_CE) || defined(CYGWIN) + key = VK_SPACE; + if (isdigit(k)) + return (uint16_t)k; + if (isalpha(k) && isupper(k)) + return (uint16_t)k; + if (isalpha(k) && islower(k)) + return (uint16_t)k - 0x20; + for (i = 0; i < numKTable; i++) + { + if (ktable[i].ascii == k) + { + key = ktable[i].key; + break; + } + } +#elif defined(__QNX__) + key = KEYCODE_QUESTION; + for (i = 0; i < numKTable; i++) + { + if (k == ktable[i].ascii) + { + key = ktable[i].key; + break; + } + } +#endif + return key; +} + +int uinput_unittest(int argc, char *argv[]) +{ + unsigned int i = 0; + if (argc > 2 && strcmp(argv[1],"mouse") == 0) + { + float r = 20; + float phi = 0; + input_t in; + uinput_t *p = uinput_open(argv[2]); + + in.type = INPUT_TYPE_MOUSE; + for (phi = 0; phi < (2*3.14); phi += 0.1f) + { + in.data.mouse.dx = (int32_t)(r * cos(phi)); + in.data.mouse.dy = (int32_t)(r * sin(phi)); + SOSAL_PRINT(SOSAL_ZONE_UINPUT, "{x,y} = {%lf,%lf} => {%d, %d}\n",r*cos(phi),r*sin(phi),in.data.mouse.dx,in.data.mouse.dy); + uinput_send(p, &in); + thread_msleep(100); + } + uinput_close(p); + } + else if (argc > 2 && strcmp(argv[1],"keyboard") == 0) + { + input_t in; + uinput_t *p = uinput_open(argv[2]); + char cstr[] = "This is a string from the uinput library\n"; + in.type = INPUT_TYPE_KEY; + + if (p == NULL) + return -1; + + SOSAL_PRINT(SOSAL_ZONE_UINPUT, "Sending string \"%s\"",cstr); + + for (i = 0; i < strlen(cstr); i++) + { + in.data.key.code = GetKeyFromASCII(cstr[i]); + in.data.key.state = INPUT_KEY_STATE_DOWN; + uinput_send(p, &in); + thread_msleep(10); + in.data.key.state = INPUT_KEY_STATE_UP; + uinput_send(p, &in); + thread_msleep(100); + } + uinput_close(p); + } + else if (argc > 2 && strcmp(argv[1],"input") == 0 ) + { + char c; + input_t in; + uinput_t *p = uinput_open(argv[2]); + printf("Enter a string (use ENTER to complete the string!):"); + in.type = INPUT_TYPE_KEY; + do { + c = getchar(); + in.data.key.code = GetKeyFromASCII(c); + in.data.key.state = INPUT_KEY_STATE_DOWN; + uinput_send(p, &in); + in.data.key.state = INPUT_KEY_STATE_UP; + uinput_send(p, &in); + } while (c != '\n'); + uinput_close(p); + } + else + { + printf("Find the Class Name of this window and pass that as the first parameter to this program.\n"); + printf("If you don't know the class name, just type any string and all the classnames will be printed in an attempt to find that one.\n"); + printf("Example: $ %s keyboard ConsoleWindowClass\n",argv[0]); + } + return 0; +} +#else +int uinput_unittest(int argc, char *argv[]) +{ + return 0; +} +#endif + +#ifdef UINPUT_TEST +#ifdef _UINPUT_T_FUNCS +int main(int argc, char *argv[]) +{ + //return uinput_unittest(argc, argv); + uint32_t lifetime = 0xFFFFFFFF; + uint32_t period = 10000; // 10 seconds + uint32_t delay = 10; // 10 ms. + char type[255]; + int i; + uinput_t *in = NULL; + + strcpy(type, "HOME"); + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "%s \n", argv[0]); + + for (i = 0; i < argc; i++) + { + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "ARGV[%u] = %s\n", i, argv[i]); + } + + if (argc > 1) lifetime = atoi(argv[1]); + if (argc > 2) period = atoi(argv[2]); + if (argc > 3) delay = atoi(argv[3]); + if (argc > 4) strcpy(type, argv[4]); + + in = uinput_open("KeepAwake"); + if (in) + { + while (lifetime-- > 0) + { + if (strcmp(type, "HOME")== 0) + { + input_t kick; + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Sending HOME key!\n"); + kick.type = INPUT_TYPE_KEY; +#if defined(LINUX) + kick.data.key.code = KEY_HOME; +#elif defined(__QNX__) + kick.data.key.code = KEYCODE_HOME; +#endif + kick.data.key.state = INPUT_KEY_STATE_DOWN; + uinput_send(in, &kick); + thread_msleep(delay); + kick.data.key.state = INPUT_KEY_STATE_UP; + uinput_send(in, &kick); + } + else if (strcmp(type, "KEY") == 0) + { + input_t key; + int i,len = strlen(argv[5]); + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Sending KEY Emulation\n"); + for (i = 0; i < len; i++) + { + key.type = INPUT_TYPE_KEY; + key.data.key.code = GetKeyFromASCII(argv[5][i]); + key.data.key.state = INPUT_KEY_STATE_DOWN; + uinput_send(in, &key); + thread_msleep(delay); + key.data.key.state = INPUT_KEY_STATE_UP; + uinput_send(in, &key); + } + } + else if (strcmp(type, "TOUCH") == 0) + { + input_t tap; + int32_t px = (argc > 5 ? atoi(argv[5]) : 50); + int32_t py = (argc > 6 ? atoi(argv[6]) : 50); + uint32_t s = (argc > 7 ? atoi(argv[7]) : 16); + uint32_t p = (argc > 8 ? atoi(argv[8]) : 10); + int32_t ex = (argc > 9 ? atoi(argv[9]) : 50); + int32_t ey = (argc > 10 ? atoi(argv[10]) : 50); + int32_t inc = (argc > 11 ? atoi(argv[11]) : 10); + int32_t i; + int32_t dx, dy, dd, ux, uy; + + // we need to make sure that ux,uy aren't < 1 + dx = abs(ex-px); + dy = abs(ey-py); + dd = (dx>dy?dx:dy); + dx = (ex-px); + dy = (ey-py); + if (inc > dd) + inc = dd; + ux = dx/inc; + uy = dy/inc; + if (ux == 0 && dx > 0) + ux = 1; + else if (ux == 0 && dx < 0) + ux = -1; + if (uy == 0 && dy > 0) + uy = 1; + else if (uy == 0 && dy < 0) + uy = -1; + for (i = 0; i < inc; i++) + { + SOSAL_PRINT(SOSAL_ZONE_ALWAYS, "Sending touchscreen tap on %u%%x%u%%\n",px,py); + tap.type = INPUT_TYPE_TOUCH; + tap.data.touch.type = INPUT_TS_FINGER; + tap.data.touch.location_x = (UINPUT_MAX_TOUCH_X * px) / 100; + tap.data.touch.location_y = (UINPUT_MAX_TOUCH_Y * py) / 100; + tap.data.touch.major_width = s; + tap.data.touch.minor_width = 1; + tap.data.touch.pressure = p; + tap.data.touch.orientation = 0; + uinput_send(in, &tap); + px += ux; + py += uy; + thread_msleep(delay); + } + tap.data.touch.pressure = 0; + uinput_send(in, &tap); + } + else + break; + + thread_msleep(period); + + } + uinput_close(in); + } + return 0; +} +#else +int main(int argc, char *argv[]) +{ + printf("This platform does not support uinput!"); +} +#endif +#endif diff --git a/source/sosal/unittest.c b/source/sosal/unittest.c new file mode 100644 index 0000000..fb57273 --- /dev/null +++ b/source/sosal/unittest.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +unittest_t tests[] = { + {"allocator", allocator_unittest, false_e}, + // bitfield? + {"cache", cache_unittest, false_e}, // needs explicit arguments + {"events", event_unittest, true_e}, + // fourcc ? + // fph ? + {"hash", hash_unittest, true_e}, + //{"heap", heap_unittest, true_e}, + {"histogram", histogram_unittest, true_e}, + {"ini", ini_unittest, true_e}, + {"list", list_unittest, true_e}, + {"module", module_unittest, false_e}, // needs explicit arguments + // mutex ? + {"options", option_unittest, true_e}, + // profiler ? + {"queue", queue_unittest, true_e}, + // ring ? + {"rpc", rpc_unittest, true_e}, + // semaphores ? + // serial ? + {"shared", shared_unittest, false_e}, // needs explicit arguments + {"socket", socket_unittest, true_e}, + {"threads", thread_unittest, true_e}, + {"pool", threadpool_unittest,true_e}, + {"uinput", uinput_unittest, false_e}, // needs explicit arguments + {"btreelist", btreelist_unittest, true_e}, + // vector ? +}; +uint32_t numTests = dimof(tests); + +int main(int argc, char *argv[]) +{ + uint32_t i,j = 0; + +#if defined(SOSAL_RUNTIME_DEBUG) + debug_get_zone_mask("SOSAL_ZONE_MASK", &sosal_zone_mask); +#endif + + printf("SOSAL Unit Test!\n"); + if (argc == 1) + { + for (i = 0; i < numTests; i++) + { + if (tests[i].noArgs == true_e && tests[i].test(argc, argv) == true_e) + { + printf("[passed] unit test %s!\n", tests[i].name); + } + else if (tests[i].noArgs == false_e) + { + printf("[xxxxxx] unit test %s needs arguments to run, use by itself!\n", tests[i].name); + } + else + { + printf("[FAILED] unit test %s!\n", tests[i].name); + } + } + } + else + { + for (i = 0; i < (uint32_t)argc; i++) + { + for (j = 0; j < numTests; j++) + { + if (strcmp(tests[j].name, argv[i]) == 0) + { + printf("Calling unit test for %s\n", tests[j].name); + if (tests[j].test(argc-i, &argv[i]) == true_e) + { + printf("[passed] unit test %s!\n", tests[j].name); + } + else + { + printf("[FAILED] unit test %s!\n", tests[j].name); + } + } + } + } + } + return 0; +} diff --git a/source/sosal/vector.c b/source/sosal/vector.c new file mode 100644 index 0000000..a6b197b --- /dev/null +++ b/source/sosal/vector.c @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +float vector_mag(vector_t *v) +{ + return (float)sqrt((v->p.x*v->p.x) + (v->p.y*v->p.y) + (v->p.z*v->p.z)); // time is not considered +} + +/** This vector math is of the form a += b */ +void vector_add(vector_t *a, vector_t *b) +{ + a->p.x += b->p.x; + a->p.y += b->p.y; + a->p.z += b->p.z; + a->p.t += b->p.t; +} + +void vector_scale(vector_t *a, float b) +{ + a->p.x *= b; + a->p.y *= b; + a->p.z *= b; + a->p.t *= b; +} + +void vector_inverse(vector_t *a) +{ + a->p.x = -a->p.x; + a->p.y = -a->p.y; + a->p.z = -a->p.z; + a->p.t = -a->p.t; +} + + diff --git a/source/tools/bitimg2img/bitimg2img.c b/source/tools/bitimg2img/bitimg2img.c new file mode 100644 index 0000000..ebb3670 --- /dev/null +++ b/source/tools/bitimg2img/bitimg2img.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief Tool to convert binary image file into byte image file (0x01 -> 0xFF) + */ + +#include +#include +#include + +int +main(int argc, char **argv) +{ + FILE *fp; + FILE *fd; + unsigned char inword[4]; + unsigned char outword[4]; + + if (argc != 3) { + printf( "bitimg2img \r\n"); + return -1; + } + + fp = fopen(argv[1], "rb"); + fd = fopen(argv[2], "wb"); + + +while (fread(inword, sizeof(inword), 1, fp) > 0) { + outword[0] = (inword[0]) ? 0xFF : 0; + outword[1] = (inword[1]) ? 0xFF : 0; + outword[2] = (inword[2]) ? 0xFF : 0; + outword[3] = (inword[3]) ? 0xFF : 0; + fwrite(outword ,sizeof(outword), 1, fd); + } + + fclose(fp); + fclose(fd); + + return 0; +} diff --git a/source/tools/bitimg2img/concerto.mak b/source/tools/bitimg2img/concerto.mak new file mode 100644 index 0000000..794bf30 --- /dev/null +++ b/source/tools/bitimg2img/concerto.mak @@ -0,0 +1,21 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_OS),LINUX) +include $(PRELUDE) +TARGET=bitimg2img +TARGETTYPE=exe +CSOURCES=bitimg2img.c +include $(FINALE) +endif diff --git a/source/tools/imgDiff/concerto.mak b/source/tools/imgDiff/concerto.mak new file mode 100644 index 0000000..3178f88 --- /dev/null +++ b/source/tools/imgDiff/concerto.mak @@ -0,0 +1,21 @@ +# Copyright (C) 2009-2011 Texas Instruments, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifeq ($(TARGET_OS),LINUX) +include $(PRELUDE) +TARGET=imgDiff +TARGETTYPE=exe +CSOURCES=imgDiff.c +include $(FINALE) +endif diff --git a/source/tools/imgDiff/imgDiff.c b/source/tools/imgDiff/imgDiff.c new file mode 100644 index 0000000..f5a46d4 --- /dev/null +++ b/source/tools/imgDiff/imgDiff.c @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2009-2011 Texas Instruments, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! \file + * \brief Tool to perform a diff compare to golden data + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +static char prefix[2]; + +static int +one (const struct dirent *unused) +{ + if(strncmp(prefix, unused->d_name, 2)==0) + return 1; + else + return 0; +} + +int +img_diff(FILE *fref, + FILE *fout, + int width, + int height, + int frames, + int hSt, + int vSt, + int hBuff, + int vBuff, + int bpp, + int planes, + int divider) +{ + int i,j,k,f, errors; + unsigned char *refBuffer; + unsigned char *outBuffer; + int shift, step, div; + size_t r = 0; + errors = 0; + + refBuffer = (unsigned char *)malloc(sizeof(char)*width*bpp); + outBuffer = (unsigned char *)malloc(sizeof(char)*width*bpp); + + step = (width-hBuff)*bpp; + + for(f=0;f0) && (refBuffer[i] != outBuffer[i])) +// if ((f>0) && (refBuffer[i] != outBuffer[i]) && errors < 1000) + { +// printf("\tFAIL: x=%d, y=%d, pl=%d, ref=%d, out=%d\n", i, j, k, refBuffer[i], outBuffer[i]); + errors++; + } + } + } + for(;j<(height/div);j++) + { + r+=fread(refBuffer, 1, width*bpp/div, fref); + r+=fread(outBuffer, 1, width*bpp/div, fout); + } + } + } + + free(refBuffer); + free(outBuffer); + return errors; +} + +void +parse_format(char *format, int *bpp, int *planes) +{ + *bpp = 1; + *planes = 1; + + if((strcmp(format, "P444") == 0) || + (strcmp(format, "IYUV") == 0) ) + *planes = 3; + else if(strcmp(format, "UYVY") == 0) + *bpp = 2; + else if(strcmp(format, "I32") == 0) + *bpp = 4; + else if(strcmp(format, "16b") == 0) + *bpp = 2; + + return; +} + +int +main(int argc, char **argv) +{ + FILE *fout; + FILE *fref; + FILE *fconfig; + + char refDir[255]; + char outDir[255]; + char refFile[255]; + char outFile[255]; + char fileName[255]; + + int frames, debug; + struct dirent **eps; + int n; + int bpp, planes, hSt, vSt, hBuff, vBuff; + int totalErrors = 0; + int totalFiles = 0; + + if (argc != 6) { + printf( "dvp_compare \r\n"); + return -1; + } + + // Parse command line arguments + strcpy(refDir, argv[1]); + strcpy(outDir, argv[2]); + fconfig = fopen(argv[3], "r"); + frames = atoi(argv[4]); + debug = atoi(argv[5]); + + // Parse each line of the config file + while(fscanf(fconfig, "%s %d %d %d %d", prefix, &hSt, &vSt, &hBuff, &vBuff) != EOF) + { + if(debug) printf("%s %d %d %d %d\n", prefix, hSt, vSt, hBuff, vBuff); + n = scandir (refDir, &eps, one, alphasort); + if (n >= 0) + { + int cnt; + for (cnt = 0; cnt < n; ++cnt) { + char *number, *name, *resolution, *fr; + char *w, *h, *format; + char *sp[20]; + int width, height, error, divider, i; + strcpy(refFile, refDir); + strcat(refFile, eps[cnt]->d_name); + strcpy(outFile, outDir); + strcat(outFile, eps[cnt]->d_name); + strcpy(fileName, eps[cnt]->d_name); + if(debug) puts (eps[cnt]->d_name); + if(debug) puts (refFile); + if(debug) puts (outFile); + fref = fopen(refFile, "rb"); + if(fref == NULL) { + printf ("Couldn't open the reference file %s\n", refFile); + break; + } + fout = fopen(outFile, "rb"); + if(fout == NULL) { + printf ("Couldn't open the output file %s.\n", outFile); + fclose(fref); + break; + } + if(debug) printf("Files are open\n"); + + // Parse file name + number = strtok(eps[cnt]->d_name, "_"); + +#if 1 + for( i=0; (sp[i] = strtok(NULL, "_")) != NULL; i++) + if(debug) printf("sp[%d]: %s\n", i, sp[i]); + format = strtok(sp[i-1], "."); + for( i=0; strchr(sp[i], (int)'x') == NULL; i++); + w = strtok(sp[i], "x"); + h = strtok(NULL, "x"); + if(debug) printf("number: %s, format: %s, w: %s, h: %s\n", + number, format, w, h); +#else + name = strtok(NULL, "_"); + resolution = strtok(NULL, "_"); + fr = strtok(NULL, "_"); + format = strtok(NULL, "."); + w = strtok(resolution, "x"); + h = strtok(NULL, "x"); + if(debug) printf("number: %s, name: %s, res: %s, fr: %s, format: %s, w: %s, h: %s\n", + number, name, resolution, fr, format, w, h); +#endif + + divider = 1; + if(strcmp(format, "IYUV") == 0) + divider = 2; + + width = atoi(w); + height = atoi(h); + if(debug) printf("%d %d\n", width, height); + + // Extract bpp and planes from file name format + parse_format(format, &bpp, &planes); + if(debug) printf("format: %s, bpp: %d, planes:%d\n", format, bpp, planes); + + // Compare files + error = img_diff(fref, fout, width, height, frames, hSt, vSt, hBuff, vBuff, bpp, planes, divider); + + if (error) + { + puts(fileName); + printf("\tFAIL: bytes mismatch = %d\n", error); + totalErrors++; + } + totalFiles++; + + fclose(fref); + fclose(fout); + } + } + else + perror ("Couldn't open the directory"); + } + + printf("\tTOTAL: %d\n\tPASSED: %d\n\tFAILED: %d\n", totalFiles, totalFiles-totalErrors, totalErrors); + + fclose(fconfig); + + return 0; +}