前言
近日,有需求想在3559上尝试移植teledyne的dalsa网络相机,想通过交叉编译的方式移植官方的aarch64版本的sdk,由于sdk里部分API是通过静态库的方式给的,所以最终没能在海思3559上跑起来,但是可以通过标准的aarch64交叉编译工具完成。移植经历记录下来,对使用aarch64-linux-gnu交叉编译工具的朋友希望能有所帮助(像瑞芯微3588这类,甚至可以直接安装sdk不需要交叉编译)
准备工作
首先登录官网https://www.teledynedalsa.com/en/support/downloads-center/,下载我们需要的sdk和开发手册,不做赘述
最开始是在x86下的ubuntu安装尝试,发现一直扫不到设备,由于同事在Windows上有过开发经验,于是通过国内代理提供的开发工具将相机的ip地址写死(默认出厂为dhcp),可以ping通后也能连接成功了
安装SDK
参考开发文档里的安装部分
实际上执行的是安装脚本corinstall,,查看下这个脚本都干了什么
在做出install还是uninstall等判断后,实际上在最后进入了另一个脚本,可以打印看下 SCRIPT_PATH下SCRIPT_NAME,发现执行了/DALSA/GigeV/bin目录下的install.gigev脚本,这个脚本也比较简单,在执行完阅读安装协议,输入y后开始分别编译动态库和配置环境
第一步执行
可见最开始是在/src/w32lib/corw32目录下编译二进制库,进入改目录后尝试修改Makefile,CC=aarch64-himix100-linux-gcc
,不出预料没有顺利通过
完整的编译log如下,发现是在静态库链接的时候出的错
aarch64-himix100-linux-gcc -I. -I…/include -g -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -Wno-unused-variable -DPOSIX_HOSTPC -DHOSTPC -DUSE_MONOTONIC_CLOCK -Darm_family -D__arm__ -D_REENTRANT -c corw32lib.c -o corw32lib.o
aarch64-himix100-linux-gcc -I. -I…/include -g -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -Wno-unused-variable -DPOSIX_HOSTPC -DHOSTPC -DUSE_MONOTONIC_CLOCK -Darm_family -D__arm__ -D_REENTRANT -c dynaqueue.c -o dynaqueue.o
aarch64-himix100-linux-gcc -I. -I…/include -g -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -Wno-unused-variable -DPOSIX_HOSTPC -DHOSTPC -DUSE_MONOTONIC_CLOCK -Darm_family -D__arm__ -D_REENTRANT -c fileutils.c -o fileutils.o
aarch64-himix100-linux-gcc -I. -I…/include -g -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -Wno-unused-variable -DPOSIX_HOSTPC -DHOSTPC -DUSE_MONOTONIC_CLOCK -Darm_family -D__arm__ -D_REENTRANT -c iniutils.c -o iniutils.o
aarch64-himix100-linux-gcc -I. -I…/include -g -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -Wno-unused-variable -DPOSIX_HOSTPC -DHOSTPC -DUSE_MONOTONIC_CLOCK -Darm_family -D__arm__ -D_REENTRANT -c objutils.c -o objutils.o
aarch64-himix100-linux-gcc -I. -I…/include -g -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -Wno-unused-variable -DPOSIX_HOSTPC -DHOSTPC -DUSE_MONOTONIC_CLOCK -Darm_family -D__arm__ -D_REENTRANT -c ioctlutils.c -o ioctlutils.o
aarch64-himix100-linux-gcc -I. -I…/include -g -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -Wno-unused-variable -DPOSIX_HOSTPC -DHOSTPC -DUSE_MONOTONIC_CLOCK -Darm_family -D__arm__ -D_REENTRANT -c csection.c -o csection.o
aarch64-himix100-linux-gcc -I. -I…/include -g -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -Wno-unused-variable -DPOSIX_HOSTPC -DHOSTPC -DUSE_MONOTONIC_CLOCK -Darm_family -D__arm__ -D_REENTRANT -c timeutils.c -o timeutils.o
aarch64-himix100-linux-gcc -I. -I…/include -g -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -Wno-unused-variable -DPOSIX_HOSTPC -DHOSTPC -DUSE_MONOTONIC_CLOCK -Darm_family -D__arm__ -D_REENTRANT -c ipcutils.c -o ipcutils.o
aarch64-himix100-linux-gcc -I. -I…/include -g -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -Wno-unused-variable -DPOSIX_HOSTPC -DHOSTPC -DUSE_MONOTONIC_CLOCK -Darm_family -D__arm__ -D_REENTRANT -c threadutils.c -o threadutils.o
aarch64-himix100-linux-gcc -I. -I…/include -g -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -Wno-unused-variable -DPOSIX_HOSTPC -DHOSTPC -DUSE_MONOTONIC_CLOCK -Darm_family -D__arm__ -D_REENTRANT -c waitutils.c -o waitutils.o
aarch64-himix100-linux-gcc -I. -I…/include -g -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -Wno-unused-variable -DPOSIX_HOSTPC -DHOSTPC -DUSE_MONOTONIC_CLOCK -Darm_family -D__arm__ -D_REENTRANT -c archutils.c -o archutils.o
ld -r corw32lib.o dynaqueue.o fileutils.o iniutils.o objutils.o ioctlutils.o csection.o timeutils.o ipcutils.o threadutils.o waitutils.o archutils.o -o libCorW32_1_0_a
ld: corw32lib.o:普通ELF重定位(M: 183)
ld: corw32lib.o:普通ELF重定位(M: 183)
ld: corw32lib.o:普通ELF重定位(M: 183)
ld: corw32lib.o:普通ELF重定位(M: 183)
ld: corw32lib.o:普通ELF重定位(M: 183)
ld: corw32lib.o:普通ELF重定位(M: 183)
ld: corw32lib.o:普通ELF重定位(M: 183)
corw32lib.o: 无法添加符号: 文件格式错误
makefile:143: recipe for target ‘libCorW32_1_0_a’ failed
make: *** [libCorW32_1_0_a] Error 1
暂时不清楚这个静态库链接出错会不会对后续有影响,先跳过执行下一步
第二步执行
修改Makefile
CC=aarch64-himix100-linux-gcc
还是很快报错了,发现是没有xxx文件,进一步检查
可以看到,因为没有定义ARCH,所以编译时会在shell中提取当前架构(x86_64)后,会链接libGevApi_2_0__a
:而不是libGevApi_2_0_armv8-a_a,
在开发板上执行uname -m
,打印3559的架构为aarch64,手动添加ARCH=aarch64
,匹配了后面的条件判断
再次编译,发现全部是动态库的报错
aarch64-himix100-linux-gcc -I. -I. -I…/…/GigeV/include -I/opt/genicam_v3_0/library/CPP/include -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -DPOSIX_HOSTPC -DHOSTPC -D_USE_GNU -D__arm__ -D_REENTRANT -march=armv8-a -c gev_linux.c -o gev_linux.o
aarch64-himix100-linux-gcc -I. -I. -I…/…/GigeV/include -I/opt/genicam_v3_0/library/CPP/include -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -DPOSIX_HOSTPC -DHOSTPC -D_USE_GNU -D__arm__ -D_REENTRANT -march=armv8-a -c cameraregdata.c -o cameraregdata.o
aarch64-himix100-linux-gcc -I. -I. -I…/…/GigeV/include -I/opt/genicam_v3_0/library/CPP/include -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -DPOSIX_HOSTPC -DHOSTPC -D_USE_GNU -D__arm__ -D_REENTRANT -march=armv8-a -c gev_message_linux.c -o gev_message_linux.o
aarch64-himix100-linux-gcc -I. -I. -I…/…/GigeV/include -I/opt/genicam_v3_0/library/CPP/include -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -DPOSIX_HOSTPC -DHOSTPC -D_USE_GNU -D__arm__ -D_REENTRANT -march=armv8-a -c gev_packet_mmap.c -o gev_packet_mmap.o
aarch64-himix100-linux-gcc -I. -I. -I…/…/GigeV/include -I/opt/genicam_v3_0/library/CPP/include -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -DPOSIX_HOSTPC -DHOSTPC -D_USE_GNU -D__arm__ -D_REENTRANT -march=armv8-a -c gev_packet_linux.c -o gev_packet_linux.o
aarch64-himix100-linux-gcc -I. -I. -I…/…/GigeV/include -I/opt/genicam_v3_0/library/CPP/include -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -Wno-attributes -DUSE_MINIZ -DPOSIX_HOSTPC -DHOSTPC -D_USE_GNU -D__arm__ -D_REENTRANT -march=armv8-a -c gev_xml_utils.c -o gev_xml_utils.o
In file included from gev_xml_utils.c:56:0:
miniz.c: In function ‘tinfl_decompress’:
miniz.c:1456:9: warning: this ‘for’ clause does not guard… [-Wmisleading-indentation]
for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8;
^~~
miniz.c:1456:47: note: …this statement, but the latter is misleadingly indented as if it is guarded by the ‘for’
for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8;
^~~
miniz.c: In function ‘tdefl_find_match’:
miniz.c:2274:5: warning: this ‘if’ clause does not guard… [-Wmisleading-indentation]
if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break;
^~
miniz.c:2274:23: note: …this statement, but the latter is misleadingly indented as if it is guarded by the ‘if’
if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break;
^
aarch64-himix100-linux-gcc -I. -I. -I…/…/GigeV/include -I/opt/genicam_v3_0/library/CPP/include -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -DPOSIX_HOSTPC -DHOSTPC -D_USE_GNU -D__arm__ -D_REENTRANT -march=armv8-a -c gevapi_utils.c -o gevapi_utils.o
aarch64-himix100-linux-gcc -I. -I. -I…/…/GigeV/include -I/opt/genicam_v3_0/library/CPP/include -fPIC -fno-for-scope -Wall -Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -DPOSIX_HOSTPC -DHOSTPC -D_USE_GNU -D__arm__ -D_REENTRANT -march=armv8-a -c gevgenapi.cpp -o gevgenapi.o
aarch64-himix100-linux-gcc -shared -Wl,-Bsymbolic -Wl,-allow-shlib-undefined
-Wl,-soname,libGevApi.so.2
-o …/…/GigeV/lib/libGevApi.so.2.0
gev_linux.o cameraregdata.o gev_message_linux.o gev_packet_mmap.o gev_packet_linux.o gev_xml_utils.o gevapi_utils.o gevgenapi.o …/…/GigeV/lib/libGevApi_2_0_armv8-a_a -L/usr/local/lib -lCorW32 -L/opt/genicam_v3_0/bin/Linux64_ARM -lGenApi_gcc54_v3_0 -lGCBase_gcc54_v3_0
/opt/hisi-linux/x86-arm/aarch64-himix100-linux/host_bin/…/lib/gcc/aarch64-linux-gnu/6.3.0/…/…/…/…/aarch64-linux-gnu/bin/ld: 当搜索用于 /usr/local/lib/libCorW32.so 时跳过不兼容的 -lCorW32
/opt/hisi-linux/x86-arm/aarch64-himix100-linux/host_bin/…/lib/gcc/aarch64-linux-gnu/6.3.0/…/…/…/…/aarch64-linux-gnu/bin/ld: 找不到 -lCorW32
/opt/hisi-linux/x86-arm/aarch64-himix100-linux/host_bin/…/lib/gcc/aarch64-linux-gnu/6.3.0/…/…/…/…/aarch64-linux-gnu/bin/ld: 找不到 -lGenApi_gcc54_v3_0
/opt/hisi-linux/x86-arm/aarch64-himix100-linux/host_bin/…/lib/gcc/aarch64-linux-gnu/6.3.0/…/…/…/…/aarch64-linux-gnu/bin/ld: 找不到 -lGCBase_gcc54_v3_0
collect2: error: ld returned 1 exit status
Makefile:122: recipe for target ‘libGevApi.so.2.0’ failed
make: *** [libGevApi.so.2.0] Error 1
-lCorW32
是我们第一步的目标文件,看来绕不过去
另外报错日志中不兼容的 -lCorW32检查到是链接到测试时x86的动态库上了,需要对原先的sdk卸载,如果之前没用过的可以跳过这一步,
卸载其他版本sdk
除了安装时的脚本入参增加了uninstall外,还需要进入卸载时提醒的目录,再次执行另一个卸载脚本(就离谱,生怕一下卸干净了)
返回第一步
仔细检查Makefile,发现动态库在编译时用到了外部库,也就是-lpthread -lm -ldl -lrt这些
所以把ARCHLIBDIR=/opt/hisi-linux/x86-arm/aarch64-himix100-linux/host_bin/…/target/lib 更改为海思库的路径
可惜make 还是一样的报错,
通过readelf -h看到了所有的-o文件都是aarch64架构,那应该还有某些标准库用了x86的
直接注掉了静态库的链接试试,反正后续也只用了动态库
因为编译动态库时是不需要链接的,直接make完成
为了方便后续步骤在寻找路径时麻烦,注掉了install.gigev后续步骤,直接执行安装脚本,让动态库的环境和官方预设的匹配
这次编译第二步的库就不再报lCorW32缺失了
最终第一步的Makefile如下
#-----------------------------------------------------------------------------
# MAKEFILE.armsf
# Copyright(C) Teledyne DALSA Inc. 2016
# All rights reserved.
#
# Description:
# CorW32 Library for Linux (Posix/Win32 compatibility layer).
# for ARMsf (soft-float) architecture.
#
# CorW32 is a shared library
#
# History:
# (Adapted from std PC makefile)
#
#-----------------------------------------------------------------------------
#
# Standard dependencies.
#
DEBUGFLAGS=-g#gdb开关
CC=aarch64-himix100-linux-gcc#交叉编译工具
RM=/bin/rm -f#
RANLIB=ranlib
LD=ld
LDCONFIG=/sbin/ldconfig
INC_PATH = -I../include
# ARCHLIBDIR=/usr/aarch64-linux-gnu/lib
ARCHLIBDIR=/opt/hisi-linux/x86-arm/aarch64-himix100-linux/host_bin/../target/lib #链接lpthread等库的路径
ARCH_OPTIONS= -Darm_family -D__arm__ -D_REENTRANT#宏开关
#
# API Version control information to be embedded.
#
TARGETNAME=CorW32
LIBVERSION=1
LIBBUILDID=0
#
# Path dependency for this library.
#
CURDIR = $(shell pwd)
VPATH = $(CURDIR)
#
# Object definitions: Specific files for this library.
#
OBJS= corw32lib.o \
dynaqueue.o \
fileutils.o \
iniutils.o \
objutils.o \
ioctlutils.o \
csection.o \
timeutils.o \
ipcutils.o \
threadutils.o \
waitutils.o \
archutils.o
#
# Libraries required.
#
EXTRALIBS=-L$(ARCHLIBDIR) -lpthread -lm -ldl -lrt
#
# Dynamic libraries need position independent code.
#
C_COMPILE_OPTIONS= $(DEBUGFLAGS) -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces \
-Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label -Wno-unused-variable
# c++ compiler options.
CXX_COMPILE_OPTIONS= $(DEBUGFLAGS) -fPIC -fno-for-scope -fno-const-strings -Wall \
-Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual \
-Wno-unused-function -Wno-unused-label -Wno-unused-variable
#BASE_OPTIONS= -DPOSIX_HOSTPC -DHOSTPC -DCOR_TRACE_LIBINIT
BASE_OPTIONS= -DPOSIX_HOSTPC -DHOSTPC
# See if this is 2.6.18 or later (named posix semaphores - process shared)
# (Hopefully kernel is name 2.6.###-### and not 2.6.###text )
CORKERNEL_MAJOR:=$(shell uname -r | cut -d '.' -f 1)
CORKERNEL_MINOR:=$(shell uname -r | cut -d '.' -f 2)
CORKERNEL_LEVEL_TMP:=$(shell uname -r | cut -d '.' -f 3)
CORKERNEL_LEVEL:=$(shell echo $(CORKERNEL_LEVEL_TMP) | cut -d '-' -f 1)
#CORKERNEL_LEVEL:=$(shell echo $(CORKERNEL_LEVEL_TMP) | cut -c '1-2')
ifeq ($(CORKERNEL_MAJOR), 2)
ifeq ($(CORKERNEL_MINOR), 6)
ifeq ($(shell if test $(CORKERNEL_LEVEL) -ge 18; then echo ok; fi), ok)
#BASE_OPTIONS += -DUSE_POSIX_SEMAPHORES
endif
endif
endif
#
# Use the monotonic clock if it is present.
#
ifeq ($(shell if test -f /usr/include/linux/time.h; then echo exists; fi), exists)
CLOCK_MONOTONIC_PRESENT = $(shell grep CLOCK_MONOTONIC /usr/include/linux/time.h)
ifneq ($(CLOCK_MONOTONIC_PRESENT),)
BASE_OPTIONS += -DUSE_MONOTONIC_CLOCK
endif
endif
.SUFFIXES: .o .c .cpp
%.o : %.c
$(CC) -I. $(INC_PATH) $(C_COMPILE_OPTIONS) $(BASE_OPTIONS) $(TARGET_OPTIONS) $(ARCH_OPTIONS) -c $< -o $@
%.o : %.cpp
$(CC) -I. $(INC_PATH) $(CXX_COMPILE_OPTIONS) $(BASE_OPTIONS) $(TARGET_OPTIONS) $(ARCH_OPTIONS) -c $< -o $@
#
# Define the installation paths
#
INSTALL_PREFIX = /usr/local
BINDIR = $(INSTALL_PREFIX)/bin
MANDIR = $(INSTALL_PREFIX)/man
LIBDIR = $(INSTALL_PREFIX)/lib
INCDIR = $(INSTALL_PREFIX)/include
CNFDIR = $(INSTALL_PREFIX)/share
LIBNAME=lib$(TARGETNAME)_$(LIBVERSION)_$(LIBBUILDID)_a
SONAME=lib$(TARGETNAME).so
SHAREDLIBLINK=$(SONAME).$(LIBVERSION)
SHAREDLIBNAME= $(SONAME).$(LIBVERSION).$(LIBBUILDID)
#
# Main target creation section.
#
all: $(LIBNAME) $(SHAREDLIBNAME)
release: $(SHAREDLIBNAME)
$(SHAREDLIBNAME): $(OBJS)
$(CC) -shared -Wl,-Bsymbolic -Wl,-allow-shlib-undefined -Wl,-soname,$(SONAME).$(LIBVERSION) -o $(SHAREDLIBNAME) $(OBJS) $(EXTRALIBS)
$(LIBNAME): $(OBJS)
# $(LD) -r $^ -o $@
# $(LD) -r $(OBJS) $(EXTRALIBS) -o $@
clean: distclean
-$(RM) $(OBJS) *~ *.bak
distclean:
-$(RM) $(SHAREDLIBNAME)
-$(RM) $(LIBNAME)
relink:
-$(RM) $(SHAREDLIBNAME)
install: all
cp $(SHAREDLIBNAME) $(LIBDIR)/$(SHAREDLIBNAME)
-$(RM) $(LIBDIR)/$(SHAREDLIBLINK)
ln -s $(LIBDIR)/$(SHAREDLIBNAME) $(LIBDIR)/$(SHAREDLIBLINK)
-$(LDCONFIG) -l $(LIBDIR)/$(SHAREDLIBNAME)
-$(RM) $(LIBDIR)/$(SONAME)
ln -s $(LIBDIR)/$(SHAREDLIBLINK) $(LIBDIR)/$(SONAME)
返回第二步
根据报错信息,安装aarch64版本的GenICam库,这个脚本有架构的检验,通过才会进一步安装
注掉判断,安装成功
再次编译第二步,这次没有报错了,编译成功
将/DALSA/GigeV/lib下的libGevApi.so.2.0拷贝至DALSA/src/gevlib
继续执行脚本
后续脚本内容也只剩下编译一些工具,可以都注掉其实,最终脚本如下
#-----------------------------------------------------------------------------
# MAKEFILE
# Copyright(C) Teledyne DALSA Inc 2009-2011
# All rights reserved.
#
# Description:
# GigE-V Framework API Library for Linux (aarch64 architectures)
#
# GigE-V Framework API is a shared library
#
#-----------------------------------------------------------------------------
#
# Standard dependencies.
#
CC=aarch64-himix100-linux-gcc
RM=/bin/rm
RANLIB=ranlib
LD=ld
LDCONFIG=/sbin/ldconfig
#
# Architecture specific environment defs for self-hosted environment
#
ifndef ARCH
ARCH := $(shell uname -m | sed -e s/aarch64/aarch64/)
endif
ARCH = aarch64
ifeq ($(ARCH), aarch64)
# Common
ARCHNAME=armv8-a
ARCH_GENICAM_BIN=Linux64_ARM
ARCH_OPTIONS= -D__arm__ -D_REENTRANT -march=armv8-a
ARCH_GCCVER=54
endif
#
# Arch dependent GenICam library specification
#
GENICAM_PATH_VERSION=v3_0
GENICAM_PATH:=$(GENICAM_ROOT_V3_0)
GENICAM_LIBS=-L$(GENICAM_PATH)/bin/$(ARCH_GENICAM_BIN)\
-lGenApi_gcc$(ARCH_GCCVER)_$(GENICAM_PATH_VERSION)\
-lGCBase_gcc$(ARCH_GCCVER)_$(GENICAM_PATH_VERSION)
INC_PATH = -I. -I../../GigeV/include -I$(GENICAM_PATH)/library/CPP/include
#
# API Version control information to be embedded.
#
TARGETNAME=GevApi
LIBVERSION=2
LIBBUILDID=0
#
# Path dependency for this library.
#
CURDIR = $(shell pwd)
VPATH = $(CURDIR)
#
# Object definitions: Specific files for this library.
#
OBJS= gev_linux.o \
cameraregdata.o \
gev_message_linux.o \
gev_packet_mmap.o \
gev_packet_linux.o \
gev_xml_utils.o \
gevapi_utils.o \
gevgenapi.o
#
# Libraries required.
#
EXTRALIBS=-L/usr/local/lib -lCorW32 $(GENICAM_LIBS)
#
# Dynamic libraries need position independent code.
#
C_COMPILE_OPTIONS= $(DEBUGFLAGS) -fPIC -fhosted -Wall -Wno-parentheses -Wno-missing-braces \
-Wno-unknown-pragmas -Wno-cast-qual -Wno-unused-function -Wno-unused-label
# c++ compiler options.
CXX_COMPILE_OPTIONS= $(DEBUGFLAGS) -fPIC -fno-for-scope -Wall \
-Wno-parentheses -Wno-missing-braces -Wno-unknown-pragmas -Wno-cast-qual \
-Wno-unused-function -Wno-unused-label
BASE_OPTIONS= -DPOSIX_HOSTPC -DHOSTPC -D_USE_GNU
.SUFFIXES: .o .c .cpp
%.o : %.c
$(CC) -I. $(INC_PATH) $(C_COMPILE_OPTIONS) $(BASE_OPTIONS) $(TARGET_OPTIONS) $(ARCH_OPTIONS) -c $< -o $@
%.o : %.cpp
$(CC) -I. $(INC_PATH) $(CXX_COMPILE_OPTIONS) $(BASE_OPTIONS) $(TARGET_OPTIONS) $(ARCH_OPTIONS) -c $< -o $@
#
# Define the installation paths
#
INSTALL_PREFIX = /usr/local
BINDIR = $(INSTALL_PREFIX)/bin
MANDIR = $(INSTALL_PREFIX)/man
LIBDIR = $(INSTALL_PREFIX)/lib
INCDIR = $(INSTALL_PREFIX)/include
CNFDIR = $(INSTALL_PREFIX)/share
GENIE_DIR = ../../GigeV
GENIE_LIB_DIR = $(GENIE_DIR)/lib
LIBNAME=lib$(TARGETNAME)_$(LIBVERSION)_$(LIBBUILDID)_$(ARCHNAME)_a
SONAME=lib$(TARGETNAME).so
SHAREDLIBLINK=$(SONAME).$(LIBVERSION)
SHAREDLIBNAME= $(SONAME).$(LIBVERSION).$(LIBBUILDID)
#
# Main target creation section.
#
all: $(SHAREDLIBNAME)
$(SHAREDLIBNAME): $(OBJS)
$(CC) -shared -Wl,-Bsymbolic -Wl,-allow-shlib-undefined \
-Wl,-soname,$(SONAME).$(LIBVERSION) \
-o $(GENIE_LIB_DIR)/$(SHAREDLIBNAME) \
$(OBJS) $(GENIE_LIB_DIR)/$(LIBNAME) $(EXTRALIBS)
clean:
-$(RM) $(GENIE_LIB_DIR)/$(SHAREDLIBNAME) $(OBJS) *~ *.bak
install: all
cp $(GENIE_LIB_DIR)/$(SHAREDLIBNAME) $(LIBDIR)/$(SHAREDLIBNAME)
-$(RM) $(LIBDIR)/$(SHAREDLIBLINK)
ln -s $(LIBDIR)/$(SHAREDLIBNAME) $(LIBDIR)/$(SHAREDLIBLINK)
-$(LDCONFIG) -l $(LIBDIR)/$(SHAREDLIBNAME)
-$(RM) $(LIBDIR)/$(SONAME)
ln -s $(LIBDIR)/$(SHAREDLIBLINK) $(LIBDIR)/$(SONAME)
# Specific file handling..... (to quiet warnings etc....)
gev_xml_utils.o: gev_xml_utils.c
$(CC) -I. $(INC_PATH) $(C_COMPILE_OPTIONS) -Wno-attributes -DUSE_MINIZ $(BASE_OPTIONS) $(TARGET_OPTIONS) $(ARCH_OPTIONS) -c $< -o $@
安装脚本如下
#!/bin/bash
#!/bin/ksh
#-----------------------------------------------------------------------------
# install.gigev
# Copyright(C) 2009-2011 Teledyne DALSA Inc
# All rights reserved.
#
# Description:
# Manual install script for GigE-V Framework under Linux.
#-----------------------------------------------------------------------------
#
export PATH=/sbin:/usr/sbin:/bin:/usr/bin
CUR=$(pwd)
cd ..
GIGEPKGDIR=$(pwd)/..
GIGEVDIR=GigeV
cd $CUR
GEV_VERSION=2.20
GEV_BUILD=0.0182
MODE="Interactive"
if [ ! -z "$TDY_INSTALL_MODE" ] ; then
if [ $TDY_INSTALL_MODE = "Silent" ] ; then
MODE="Silent"
fi
fi
if [ $# -eq 0 ] ; then
OPTION="Install"
elif [ $1 = "install" ] ; then
OPTION="Install"
elif [ $1 = "Install" ] ; then
OPTION="Install"
elif [ $1 = "uninstall" ] ; then
OPTION="Uninstall"
elif [ $1 = "Uninstall" ] ; then
OPTION="Uninstall"
elif [ $1 = "Info" ] ; then
OPTION="Info"
elif [ $1 = "info" ] ; then
OPTION="Info"
else
echo "You must specify 'install' or 'uninstall'"
exit 1
fi
if [ $OPTION = "Info" ] ; then
case $2 in
product_string_list)
echo "genie Genie GENIE gigev gige-v GigE-V"
;;
product_string)
echo "gigev"
;;
*)
echo "GigE-V Framework $GEV_VERSION build $GEV_BUILD"
;;
esac
exit 0
fi
if [ $UID != 0 ]; then
SUDOCMD=sudo
fi
GENICAM_PATH_VERSION="v3_0"
GENICAM_PKG_STRING="GenICam_v3_0_0_linux_pkg"
GENICAM_VERSION_ENV_STRING="GENICAM_ROOT_V"
GENICAM_OUR_VERSION_ENV_STRING="GENICAM_ROOT_V3_0"
if [ $OPTION = "Install" ] ; then
GENICAM_INSTALLED="No"
# Check for GenICam library installation (Needed for this package).
GENICAM_ENV=`env | grep $GENICAM_OUR_VERSION_ENV_STRING`
#GENICAM_ENV=`env | grep GENICAM_ROOT`
if [[ $GENICAM_ENV == "" ]] ; then
CUR=$(pwd)
cd $GIGEPKGDIR/$GIGEVDIR
# Expected GenICam library is not found - install it here (should be present in package)
# Check if it is unzipped
if [ -d $GENICAM_PKG_STRING ] ; then
# GenICam package is unzipped - run the installer
cd $GENICAM_PKG_STRING
. installer.sh
GENICAM_INSTALLED="Yes"
else
# Check for package to unzip
if [ -f $GENICAM_PKG_STRING.tgz ] ; then
# Unzip it and install
tar -zpxf $GENICAM_PKG_STRING.tgz
cd $GENICAM_PKG_STRING
. installer.sh
GENICAM_INSTALLED="Yes"
else
# The GenICam package we want is missing. Cannot continue.
echo "******************************************************************************************"
echo ""
echo " GenICam library installation not found : GENICAM_ROOT environment variable missing !!!"
echo " Make sure $GENICAM_PKG_STRING is installed and then restart this installation"
echo ""
echo "******************************************************************************************"
exit -1
fi
fi
cd $CUR
else
# Check if existing one is our installation (if so - unzip it here so we can uninstall it later).
# Look for the scripts we add to the profile directory.
CUR=$(pwd)
cd $GIGEPKGDIR/$GIGEVDIR
if [ -f /etc/profile.d/td_genapi_"$GENICAM_PATH_VERSION".sh ] ; then
# Most probably our GenICam installation -
if [ ! -d $GENICAM_PKG_STRING ] ; then
# GenICam is not unzipped - we should unzip it so it can be uninstalled (if possible)
if [ -f $GENICAM_PKG_STRING.tgz ] ; then
# Unzip it (so it is ready for uninstall).
tar -zpxf $GENICAM_PKG_STRING.tgz
fi
fi
else
if [ -f /etc/profile.d/td_genapi_"$GENICAM_PATH_VERSION".csh ] ; then
# Most probably our GenICam installation -
if [ ! -d $GENICAM_PKG_STRING ] ; then
# GenICam is not unzipped - we should unzip it so it can be uninstalled (if possible)
if [ -f $GENICAM_PKG_STRING.tgz ] ; then
# Unzip it (so it is ready for uninstall).
tar -zpxf $GENICAM_PKG_STRING.tgz
fi
fi
fi
fi
cd $CUR
fi
if [ $MODE = "Interactive" ] ; then
# Display the license information and get acceptance/rejection.
#
# echo "Please read the terms of use for GigE_V Framework $GEV_VERSION build $GEV_BUILD"
# # Detect if X11 (GUI environment) is running.
# #
# if [[ $DISPLAY ]] ; then
# if [ -x /usr/bin/gnome-terminal ] ; then
# OUTPUT_LICENSE="/usr/bin/gnome-terminal -t GIGE_V_LICENSE.TXT -x ../../utils/display_license ../GIGE_V_LICENSE.TXT "
# elif [ -x /usr/bin/xterm ] ; then
# OUTPUT_LICENSE="/usr/bin/xterm -T GIGE_V_LICENSE.TXT -e ../../utils/display_license ../GIGE_V_LICENSE.TXT"
# else
# OUTPUT_LICENSE="../../utils/display_license ../GIGE_V_LICENSE.TXT"
# fi
# else
# OUTPUT_LICENSE="../../utils/display_license ../GIGE_V_LICENSE.TXT"
# fi
# read -p "Press any key to display the license (you must scroll to the end)" INSTALL_PROMPT
# $OUTPUT_LICENSE
INSTALL_PROMPT=""
while [ "$INSTALL_PROMPT" == "" ]
do
read -p "Do you agree to the terms of use ? [y/n] : " INSTALL_PROMPT
INSTALL_PROMPT=$(echo $INSTALL_PROMPT | tr '[:upper:]' '[:lower:]')
case "$INSTALL_PROMPT" in
"yes" | "y" )
echo "Installing..."
;;
"no" | "n" )
echo "Cancelling installation"
exit -1
;;
* )
INSTALL_PROMPT=""
;;
esac
done
fi
# Here we will need the sudo password set up to copy to installation dir.
#
INSTALLER_NAME="GigE-V Installer"
if [[ $SUDOCMD != "" ]] ; then
if [[ $DISPLAY ]] ; then
if [ -x /usr/bin/gksudo ] ; then
if ! gksudo -m "$INSTALLER_NAME needs administrative privileges" echo " " ; then
exit 1
fi
elif [ -x /usr/bin/kdesudo ] ; then
if ! kdesudo --comment "$INSTALLER_NAME needs administrative privileges" echo " " ; then
exit 1
fi
else
echo "**************************************************************"
echo "****** $INSTALLER_NAME needs administrative privileges ******"
sudo echo " "
RETVAL=$?
if [[ "$RETVAL" -ne 0 ]] ; then
exit 1
fi
fi
else
echo "**************************************************************"
echo "****** $INSTALLER_NAME needs administrative privileges ******"
sudo echo " "
RETVAL=$?
if [[ "$RETVAL" -ne 0 ]] ; then
exit 1
fi
fi
fi
if [ -f ../../utils/genie_instools.sh ]; then
. ../../utils/genie_instools.sh
else
echo "Missing Component genie_instools"
exit 0
fi
# Build shared Win32 library from source
#
CUR=$(pwd)
cd $GIGEPKGDIR/src/w32lib/corw32
make
# Copy shared libraries to installation location
#
W32LIBS=$(ls *.so.*)
for i in $W32LIBS ; do install_library "$i" $GIGEPKGDIR/src/w32lib/corw32 ; done
# Build the shared gevapi library from source (and lib).
# (Makefile outputs lib in $GIGEPKGDIR/GigE-V/lib)
#
cd $CUR
cd $GIGEPKGDIR/src/gevlib
make
cd $GIGEPKGDIR/$GIGEVDIR/lib
GEVLIBS=$(ls *.so.*)
for i in $GEVLIBS ; do install_library "$i" $GIGEPKGDIR/$GIGEVDIR/lib ; done
# Make sure the .so cache is updated.
$SUDOCMD /sbin/ldconfig $LIBINSTALLDIR
# Create Coreco (now DALSA) include link
add_coreco_link $GIGEVDIR $GIGEPKGDIR/$GIGEVDIR
# Add the GIGEV_DIR and GIGEV_XML_DOWNLOAD environment variable(s).
# Generate the environment variable files to their proper place.
# Usually this is /etc/profile.d where they get sourced by /etc/profile
# for interactive shells.
if [ -d /etc/profile.d ] ; then
# For bash shells
$SUDOCMD echo "export GIGEV_DIR=/usr/dalsa/$GIGEVDIR" > td_gigevapi.sh
$SUDOCMD echo "export GIGEV_XML_DOWNLOAD=/usr/dalsa/$GIGEVDIR" >> td_gigevapi.sh
$SUDOCMD cp td_gigevapi.sh /etc/profile.d
# Assume this is a bash shell and set the variables.
source td_gigevapi.sh
rm td_gigevapi.sh
# For csh shells
$SUDOCMD echo "setenv GIGEV_DIR /usr/dalsa/$GIGEVDIR" > td_gigevapi.csh
$SUDOCMD echo "setenv GIGEV_XML_DOWNLOAD /usr/dalsa/$GIGEVDIR" >> td_gigevapi.csh
$SUDOCMD cp td_gigevapi.csh /etc/profile.d
rm td_gigevapi.csh
# Update the current environment (in case it needs to be used before another script starts up)
source /etc/profile
fi
# # Make tools
# cd $GIGEPKGDIR/$GIGEVDIR/tools/lsgev
# make
# $SUDOCMD make install
# cd $GIGEPKGDIR/$GIGEVDIR/tools/gevipconfig
# make
# $SUDOCMD make install
# #
# # Make sure libGlade is installed
# #
# GLADEINC=`$SUDOCMD find /usr/include -iname glade.h -print`
# if [[ $GLADEINC == "" ]] ; then
# echo "***********************************************************"
# echo " Note: libGlade is not installed (glade.h is missing). "
# echo " The GigeDeviceStatus tool will not be available....."
# echo " Use the lsgev utility in its place"
# echo "***********************************************************"
# else
# cd $GIGEPKGDIR/$GIGEVDIR/tools/GigeDeviceStatus
# make
# $SUDOCMD make install
# fi
echo "...................................................... maketools is done............................"
cd $CUR
if [[ $SUDOCMD == "" ]] ; then
chown -R $SUDO_USER *
chgrp -R $SUDO_GID *
cd $GIGEPKGDIR/src
chown -R $SUDO_USER *
chgrp -R $SUDO_GID *
cd $CUR
fi
if [[ $GENICAM_INSTALLED == "Yes" ]] ; then
echo "******************************************************************************************"
echo " GenICam library installation was performed - you will need to log out and back in to "
echo " properly set up the environment variables. "
echo "******************************************************************************************"
fi
exit 0
fi
if [ $OPTION = "Uninstall" ] ; then
# Here we will need the sudo password set up to remove links and libraries.
#
INSTALLER_NAME="GigE-V Uninstaller"
if [[ $SUDOCMD != "" ]] ; then
if [[ $DISPLAY ]] ; then
if [ -x /usr/bin/gksudo ] ; then
if ! gksudo -m "$INSTALLER_NAME needs administrative privileges" echo " " ; then
exit 1
fi
elif [ -x /usr/bin/kdesudo ] ; then
if ! kdesudo --comment "$INSTALLER_NAME needs administrative privileges" echo " " ; then
exit 1
fi
else
echo "**************************************************************"
echo "****** $INSTALLER_NAME needs administrative privileges ******"
sudo echo " "
RETVAL=$?
if [[ "$RETVAL" -ne 0 ]] ; then
exit 1
fi
fi
else
echo "**************************************************************"
echo "****** $INSTALLER_NAME needs administrative privileges ******"
sudo echo " "
RETVAL=$?
if [[ "$RETVAL" -ne 0 ]] ; then
exit 1
fi
fi
fi
if [ -f ../../utils/genie_instools.sh ]; then
. ../../utils/genie_instools.sh
else
echo "Missing Component genie_instools"
exit 0
fi
del_coreco_link $GIGEVDIR
# Remove the environment variable files.
# Usually this is /etc/profile.d where they get sourced by /etc/profile
# for interactive shells.
if [ -f /etc/profile.d/td_gigevapi.sh ] ; then
$SUDOCMD rm /etc/profile.d/td_gigevapi.sh
fi
if [ -f /etc/profile.d/td_gigevapi.csh ] ; then
$SUDOCMD rm /etc/profile.d/td_gigevapi.csh
fi
source /etc/profile
# Gige-V Framework libraries
CUR=$(pwd)
cd $GIGEPKGDIR/$GIGEVDIR/lib
GENIELIBS=$(ls *.so.*)
for i in $GENIELIBS ; do remove_library "$i" ; done
cd $GIGEPKGDIR/src/gevlib
$SUDOCMD make clean
# Check if other packages (namely SaperaLT package) are using libCorW32
#
if [ ! -d /usr/dalsa/Sapera ] ; then
cd $GIGEPKGDIR/src/w32lib/corw32
W32LIBS=$(ls *.so.*)
for i in $W32LIBS ; do remove_library "$i" ; done
$SUDOCMD make clean
fi
cd $GIGEPKGDIR/$GIGEVDIR/tools/lsgev
$SUDOCMD make clean
$SUDOCMD make uninstall
cd $GIGEPKGDIR/$GIGEVDIR/tools/gevipconfig
$SUDOCMD make clean
$SUDOCMD make uninstall
cd $GIGEPKGDIR/$GIGEVDIR/tools/GigeDeviceStatus
$SUDOCMD make clean
$SUDOCMD make uninstall
cd $GIGEPKGDIR/$GIGEVDIR
CUR2=$(pwd)
# Check for GenICam library installation - reminder for uninstalling.
GENICAM_ENV=`env | grep $GENICAM_OUR_VERSION_ENV_STRING`
#GENICAM_ENV=`env | grep GENICAM_ROOT`
if [[ $GENICAM_ENV != "" ]] ; then
# GenICam library is installed - remind them how to uninstall is needed
# Check if we installed it
if [ -d ./$GENICAM_PKG_STRING ] ; then
# GenICam package is unzipped - assume we installed it.
#
echo ""
echo "******************************************************************************************"
echo " Found the GenICam library installation directory at $CUR2/$GENICAM_PKG_STRING "
echo " It is not necessary to uninstall it if it will be re-used later "
echo ""
echo " To uninstall the GenICam library use the following command :"
echo ""
echo " . $CUR2/$GENICAM_PKG_STRING/uninstall.sh "
echo ""
echo " (Then you will need to log out and log in to remove the environment variables)"
echo ""
echo "******************************************************************************************"
else
# The GenICam package might not have been installed by us
echo ""
echo "******************************************************************************************"
echo " The GenICam library package directory was NOT found at $CUR2/$GENICAM_PKG_STRING "
echo " The uninstall script is not present! "
echo " It is not necessary to uninstall the GenICam library it if it will be re-used later"
echo ""
echo " Note : You will need to uninstall it manually if you want it uninstalled"
echo "******************************************************************************************"
fi
fi
cd $CUR
exit 0
fi
编译应用
因为海思没有QT的库,所以需要删掉包含X11 Xext等库函数的部分,不看实时窗口的播放内容直接保存下来看
删除X_Display_utils.c:
X_Display_utils.h
SapX11Util.h
GevUtils.c GevUtils.c注掉#include “SapX11Util.h”
genicam_c_demo.c最终的内容如下:
#include "stdio.h"
#include "cordef.h"
#include "gevapi.h" //!< GEV lib definitions.
// #include "SapX11Util.h"
// #include "X_Display_utils.h"
#include "FileUtil.h"
#include <sched.h>
#define MAX_NETIF 8
#define MAX_CAMERAS_PER_NETIF 32
#define MAX_CAMERAS (MAX_NETIF * MAX_CAMERAS_PER_NETIF)
// Enable/disable Bayer to RGB conversion
// (If disabled - Bayer format will be treated as Monochrome).
#define ENABLE_BAYER_CONVERSION 1
// Enable/disable buffer FULL/EMPTY handling (cycling)
#define USE_SYNCHRONOUS_BUFFER_CYCLING 0
// Enable/disable transfer tuning (buffering, timeouts, thread affinity).
#define TUNE_STREAMING_THREADS 0
#define NUM_BUF 8
void *m_latestBuffer = NULL;
// typedef struct tagMY_CONTEXT
// {
// X_VIEW_HANDLE View;
// GEV_CAMERA_HANDLE camHandle;
// int depth;
// int format;
// void *convertBuffer;
// BOOL convertFormat;
// BOOL exit;
// }MY_CONTEXT, *PMY_CONTEXT;
static unsigned long us_timer_init( void )
{
struct timeval tm;
unsigned long msec;
// Get the time and turn it into a millisecond counter.
gettimeofday( &tm, NULL);
msec = (tm.tv_sec * 1000000) + (tm.tv_usec);
return msec;
}
static unsigned long ms_timer_init( void )
{
struct timeval tm;
unsigned long msec;
// Get the time and turn it into a millisecond counter.
gettimeofday( &tm, NULL);
msec = (tm.tv_sec * 1000) + (tm.tv_usec / 1000);
return msec;
}
static int ms_timer_interval_elapsed( unsigned long origin, unsigned long timeout)
{
struct timeval tm;
unsigned long msec;
// Get the time and turn it into a millisecond counter.
gettimeofday( &tm, NULL);
msec = (tm.tv_sec * 1000) + (tm.tv_usec / 1000);
// Check if the timeout has expired.
if ( msec > origin )
{
return ((msec - origin) >= timeout) ? TRUE : FALSE;
}
else
{
return ((origin - msec) >= timeout) ? TRUE : FALSE;
}
}
static void _GetUniqueFilename( char *filename, size_t size, char *basename)
{
// Create a filename based on the current time (to 0.01 seconds)
struct timeval tm;
uint32_t years, days, hours, seconds;
if ((filename != NULL) && (basename != NULL) )
{
if (size > (16 + sizeof(basename)) )
{
// Get the time and turn it into a 10 msec resolution counter to use as an index.
gettimeofday( &tm, NULL);
years = ((tm.tv_sec / 86400) / 365);
tm.tv_sec = tm.tv_sec - (years*86400*365);
days = (tm.tv_sec / 86400);
tm.tv_sec = tm.tv_sec - (days * 86400);
hours = (tm.tv_sec / 3600);
seconds = tm.tv_sec - (hours * 3600);
snprintf(filename, size, "%s_%03d%02d%04d%02d", basename, days,hours, (int)seconds, (int)(tm.tv_usec/10000));
}
}
}
char GetKey()
{
char key = getchar();
while ((key == '\r') || (key == '\n'))
{
key = getchar();
}
return key;
}
void PrintMenu()
{
printf("GRAB CTL : [S]=stop, [1-9]=snap N, [G]=continuous, [A]=Abort\n");
printf("MISC : [Q]or[ESC]=end, [T]=Toggle TurboMode (if available), [@]=SaveToFile\n");
}
// void * ImageDisplayThread( void *context)
// {
// MY_CONTEXT *displayContext = (MY_CONTEXT *)context;
// if (displayContext != NULL)
// {
// unsigned long prev_time = 0;
// //unsigned long cur_time = 0;
// //unsigned long deltatime = 0;
// prev_time = us_timer_init();
// // While we are still running.
// while(!displayContext->exit)
// {
// GEV_BUFFER_OBJECT *img = NULL;
// GEV_STATUS status = 0;
// // Wait for images to be received
// status = GevWaitForNextImage(displayContext->camHandle, &img, 1000);
// if ((img != NULL) && (status == GEVLIB_OK))
// {
// if (img->status == 0)
// {
// m_latestBuffer = img->address;
// // Can the acquired buffer be displayed?
// if ( IsGevPixelTypeX11Displayable(img->format) || displayContext->convertFormat )
// {
// // Convert the image format if required.
// if (displayContext->convertFormat)
// {
// int gev_depth = GevGetPixelDepthInBits(img->format);
// // Convert the image to a displayable format.
// //(Note : Not all formats can be displayed properly at this time (planar, YUV*, 10/12 bit packed).
// ConvertGevImageToX11Format( img->w, img->h, gev_depth, img->format, img->address, \
// displayContext->depth, displayContext->format, displayContext->convertBuffer);
// // Display the image in the (supported) converted format.
// Display_Image( displayContext->View, displayContext->depth, img->w, img->h, displayContext->convertBuffer );
// }
// else
// {
// // Display the image in the (supported) received format.
// Display_Image( displayContext->View, img->d, img->w, img->h, img->address );
// }
// }
// else
// {
// //printf("Not displayable\n");
// }
// }
// else
// {
// // Image had an error (incomplete (timeout/overflow/lost)).
// // Do any handling of this condition necessary.
// }
// }
// #if USE_SYNCHRONOUS_BUFFER_CYCLING
// if (img != NULL)
// {
// // Release the buffer back to the image transfer process.
// GevReleaseImage( displayContext->camHandle, img);
// }
// #endif
// }
// }
// pthread_exit(0);
// }
int IsTurboDriveAvailable(GEV_CAMERA_HANDLE handle)
{
int type;
UINT32 val = 0;
if ( 0 == GevGetFeatureValue( handle, "transferTurboCurrentlyAbailable", &type, sizeof(UINT32), &val) )
{
// Current / Standard method present - this feature indicates if TurboMode is available.
// (Yes - it is spelled that odd way on purpose).
return (val != 0);
}
else
{
// Legacy mode check - standard feature is not there try it manually.
char pxlfmt_str[64] = {
0};
// Mandatory feature (always present).
GevGetFeatureValueAsString( handle, "PixelFormat", &type, sizeof(pxlfmt_str), pxlfmt_str);
// Set the "turbo" capability selector for this format.
if ( 0 != GevSetFeatureValueAsString( handle, "transferTurboCapabilitySelector", pxlfmt_str) )
{
// Either the capability selector is not present or the pixel format is not part of the
// capability set.
// Either way - TurboMode is NOT AVAILABLE.....
return 0;
}
else
{
// The capabilty set exists so TurboMode is AVAILABLE.
// It is up to the camera to send TurboMode data if it can - so we let it.
return 1;
}
}
return 0;
}
int main(int argc, char* argv[])
{
GEV_DEVICE_INTERFACE pCamera[MAX_CAMERAS] = {
0};
GEV_STATUS status;
int numCamera = 0;
int camIndex = 0;
// X_VIEW_HANDLE View = NULL;
// MY_CONTEXT context = {0};
pthread_t tid;
char c;
int done = FALSE;
int turboDriveAvailable = 0;
char uniqueName[128];
uint32_t macLow = 0; // Low 32-bits of the mac address (for file naming).
// Boost application RT response (not too high since GEV library boosts data receive thread to max allowed)
// SCHED_FIFO can cause many unintentional side effects.
// SCHED_RR has fewer side effects.
// SCHED_OTHER (normal default scheduler) is not too bad afer all.
if (0)
{
//int policy = SCHED_FIFO;
int policy = SCHED_RR;
pthread_attr_t attrib;
int inherit_sched = 0;
struct sched_param param = {
0};
// Set an average RT priority (increase/decrease to tuner performance).
param.sched_priority = (sched_get_priority_max(policy) - sched_get_priority_min(policy)) / 2;
// Set scheduler policy
pthread_setschedparam( pthread_self(), policy, ¶m); // Don't care if it fails since we can't do anyting about it.
// Make sure all subsequent threads use the same policy.
pthread_attr_init(&attrib);
pthread_attr_getinheritsched( &attrib, &inherit_sched);
if (inherit_sched != PTHREAD_INHERIT_SCHED)
{
inherit_sched = PTHREAD_INHERIT_SCHED;
pthread_attr_setinheritsched(&attrib, inherit_sched);
}
}
//============================================================================
// Greetings
printf ("\nGigE Vision Library GenICam C Example Program (%s)\n", __DATE__);
printf ("Copyright (c) 2015, Teledyne DALSA.\nAll rights reserved.\n\n");
//===================================================================================
// Set default options for the library.
{
GEVLIB_CONFIG_OPTIONS options = {
0};
GevGetLibraryConfigOptions( &options);
//options.logLevel = GEV_LOG_LEVEL_OFF;
//options.logLevel = GEV_LOG_LEVEL_TRACE;
options.logLevel = GEV_LOG_LEVEL_NORMAL;
GevSetLibraryConfigOptions( &options);
}
//====================================================================================
// DISCOVER Cameras
//
// Get all the IP addresses of attached network cards.
status = GevGetCameraList( pCamera, MAX_CAMERAS, &numCamera);
printf ("%d camera(s) on the network\n", numCamera);
// Select the first camera found (unless the command line has a parameter = the camera index)
if (numCamera != 0)
{
if (argc > 1)
{
sscanf(argv[1], "%d", &camIndex);
if (camIndex >= (int)numCamera)
{
printf("Camera index out of range - only %d camera(s) are present\n", numCamera);
camIndex = -1;
}
}
if (camIndex != -1)
{
//====================================================================
// Connect to Camera
//
// Direct instantiation of GenICam XML-based feature node map.
int i;
int type;
UINT32 height = 0;
UINT32 width = 0;
UINT32 format = 0;
UINT32 maxHeight = 1600;
UINT32 maxWidth = 2048;
UINT32 maxDepth = 2;
UINT64 size;
UINT64 payload_size;
int numBuffers = NUM_BUF;
PUINT8 bufAddress[NUM_BUF];
GEV_CAMERA_HANDLE handle = NULL;
UINT32 pixFormat = 0;
UINT32 pixDepth = 0;
UINT32 convertedGevFormat = 0;
//====================================================================
// Open the camera.
status = GevOpenCamera( &pCamera[camIndex], GevControlMode, &handle);
if (status == 0)
{
//=================================================================
// GenICam feature access via Camera XML File enabled by "open"
//
// Get the name of XML file name back (example only - in case you need it somewhere).
//
char xmlFileName[MAX_PATH] = {
0};
status = GevGetGenICamXML_FileName( handle, (int)sizeof(xmlFileName), xmlFileName);
if (status == GEVLIB_OK)
{
printf("XML stored as %s\n", xmlFileName);
}
status = GEVLIB_OK;
// Get the camera width, height, and pixel format
GevGetFeatureValue(handle, "Width", &type, sizeof(width), &width);
GevGetFeatureValue(handle, "Height", &type, sizeof(height), &height);
GevGetFeatureValue(handle, "PixelFormat", &type, sizeof(format), &format);
}
// Get the low part of the MAC address (use it as part of a unique file name for saving images).
// Generate a unique base name to be used for saving image files
// based on the last 3 octets of the MAC address.
macLow = pCamera[camIndex].macLow;
macLow &= 0x00FFFFFF;
snprintf(uniqueName, sizeof(uniqueName), "img_%06x", macLow);
// Go on to adjust some API related settings (for tuning / diagnostics / etc....).
if ( status == 0 )
{
GEV_CAMERA_OPTIONS camOptions = {
0};
// Adjust the camera interface options if desired (see the manual)
GevGetCameraInterfaceOptions( handle, &camOptions);
//camOptions.heartbeat_timeout_ms = 60000; // For debugging (delay camera timeout while in debugger)
camOptions.heartbeat_timeout_ms = 5000; // Disconnect detection (5 seconds)
#if TUNE_STREAMING_THREADS
// Some tuning can be done here. (see the manual)
camOptions.streamFrame_timeout_ms = 1001; // Internal timeout for frame reception.
camOptions.streamNumFramesBuffered = 4; // Buffer frames internally.
camOptions.streamMemoryLimitMax = 64*1024*1024; // Adjust packet memory buffering limit.
camOptions.streamPktSize = 9180; // Adjust the GVSP packet size.
camOptions.streamPktDelay = 10; // Add usecs between packets to pace arrival at NIC.
// Assign specific CPUs to threads (affinity) - if required for better performance.
{
int numCpus = _GetNumCpus();
if (numCpus > 1)
{
camOptions.streamThreadAffinity = numCpus-1;
camOptions.serverThreadAffinity = numCpus-2;
}
}
#endif
// Write the adjusted interface options back.
GevSetCameraInterfaceOptions( handle, &camOptions);
// Access some features using the C-compatible functions.
{
UINT32 val = 0;
char value_str[MAX_PATH] = {
0};
printf("Camera ROI set for \n\t");
GevGetFeatureValueAsString( handle, "Height", &type, MAX_PATH, value_str);
printf("Height = %s\n\t", value_str);
GevGetFeatureValueAsString( handle, "Width", &type, MAX_PATH, value_str);
printf("Width = %s\n\t", value_str);
GevGetFeatureValueAsString( handle, "PixelFormat", &type, MAX_PATH, value_str);
printf("PixelFormat (str) = %s\n\t", value_str);
GevGetFeatureValue(handle, "PixelFormat", &type, sizeof(UINT32), &val);
printf("PixelFormat (val) = 0x%x\n", val);
}
if (status == 0)
{
//=================================================================
// Set up a grab/transfer from this camera
//
// Get the image / payload size (adjusting for any unpacking of packed pixels)
GevGetPayloadParameters( handle, &payload_size, (UINT32 *)&type);
maxHeight = height;
maxWidth = width;
maxDepth = GetPixelSizeInBytes(GevGetUnpackedPixelType(format));
// Allocate image buffers - (image size or payload_size, whichever is larger)
size = maxDepth * maxWidth * maxHeight;
size = (payload_size > size) ? payload_size : size;
for (i = 0; i < numBuffers; i++)
{
bufAddress[i] = (PUINT8)malloc(size);
memset(bufAddress[i], 0, size);
}
#if USE_SYNCHRONOUS_BUFFER_CYCLING
// Initialize a transfer with synchronous buffer handling.
status = GevInitializeTransfer( handle, SynchronousNextEmpty, size, numBuffers, bufAddress);
#else
// Initialize a transfer with asynchronous buffer handling.
status = GevInitializeTransfer( handle, Asynchronous, size, numBuffers, bufAddress);
#endif
// Create an image display window.
// This works best for monochrome and RGB. The packed color formats (with Y, U, V, etc..) require
// conversion as do, if desired, Bayer formats.
// (Packed pixels are unpacked internally unless passthru mode is enabled).
// Translate the raw pixel format to one suitable for the (limited) Linux display routines.
// status = GetX11DisplayablePixelFormat( ENABLE_BAYER_CONVERSION, format, &convertedGevFormat, &pixFormat);
// if (format != convertedGevFormat)
// {
// // We MAY need to convert the data on the fly to display it.
// if (GevIsPixelTypeRGB(convertedGevFormat))
// {
// // Conversion to RGB888 required.
// pixDepth = 32; // Assume 4 8bit components for color display (RGBA)
// context.format = Convert_SaperaFormat_To_X11( pixFormat);
// context.depth = pixDepth;
// context.convertBuffer = malloc((maxWidth * maxHeight * ((pixDepth + 7)/8)));
// context.convertFormat = TRUE;
// }
// else
// {
// // Converted format is MONO - generally this is handled
// // internally (unpacking etc...) unless in passthru mode.
// // (
// pixDepth = GevGetPixelDepthInBits(convertedGevFormat);
// context.format = Convert_SaperaFormat_To_X11( pixFormat);
// context.depth = pixDepth;
// context.convertBuffer = NULL;
// context.convertFormat = FALSE;
// }
// }
// else
// {
// pixDepth = GevGetPixelDepthInBits(convertedGevFormat);
// context.format = Convert_SaperaFormat_To_X11( pixFormat);
// context.depth = pixDepth;
// context.convertBuffer = NULL;
// context.convertFormat = FALSE;
// }
// View = CreateDisplayWindow("GigE-V GenApi Console Demo", TRUE, height, width, pixDepth, pixFormat, FALSE );
// // Create a thread to receive images from the API and display them.
// context.View = View;
// context.camHandle = handle;
// context.exit = FALSE;
// pthread_create(&tid, NULL, ImageDisplayThread, &context);
// // Call the main command loop or the example.
PrintMenu();
while(!done)
{
c = GetKey();
// Toggle turboMode
if ((c == 'T') || (c=='t'))
{
// See if TurboDrive is available.
turboDriveAvailable = IsTurboDriveAvailable(handle);
if (turboDriveAvailable)
{
UINT32 val = 1;
GevGetFeatureValue(handle, "transferTurboMode", &type, sizeof(UINT32), &val);
val = (val == 0) ? 1 : 0;
GevSetFeatureValue(handle, "transferTurboMode", sizeof(UINT32), &val);
GevGetFeatureValue(handle, "transferTurboMode", &type, sizeof(UINT32), &val);
if (val == 1)
{
printf("TurboMode Enabled\n");
}
else
{
printf("TurboMode Disabled\n");
}
}
else
{
printf("*** TurboDrive is NOT Available for this device/pixel format combination ***\n");
}
}
// Stop
if ((c == 'S') || (c=='s') || (c == '0'))
{
GevStopTransfer(handle);
}
//Abort
if ((c == 'A') || (c=='a'))
{
GevAbortTransfer(handle);
}
// Snap N (1 to 9 frames)
if ((c >= '1')&&(c<='9'))
{
for (i = 0; i < numBuffers; i++)
{
memset(bufAddress[i], 0, size);
}
status = GevStartTransfer( handle, (UINT32)(c-'0'));
if (status != 0) printf("Error starting grab - 0x%x or %d\n", status, status);
}
// Continuous grab.
if ((c == 'G') || (c=='g'))
{
for (i = 0; i < numBuffers; i++)
{
memset(bufAddress[i], 0, size);
}
status = GevStartTransfer( handle, -1);
if (status != 0) printf("Error starting grab - 0x%x or %d\n", status, status);
}
// Save image
if ((c == '@'))
{
char filename[128] = {
0};
int ret = -1;
uint32_t saveFormat = format;
void *bufToSave = m_latestBuffer;
int allocate_conversion_buffer = 0;
// Make sure we have data to save.
if ( m_latestBuffer != NULL )
{
uint32_t component_count = 1;
UINT32 convertedFmt = 0;
// Bayer conversion enabled for save image to file option.
//
// Get the converted pixel type received from the API that is
// based on the pixel type output from the camera.
// (Packed formats are automatically unpacked - unless in "passthru" mode.)
//
convertedFmt = GevGetConvertedPixelType( 0, format);
if ( GevIsPixelTypeBayer( convertedFmt ) && ENABLE_BAYER_CONVERSION )
{
int img_size = 0;
int img_depth = 0;
uint8_t fill = 0;
// Bayer will be converted to RGB.
saveFormat = GevGetBayerAsRGBPixelType(convertedFmt);
// Convert the image to RGB.
img_depth = GevGetPixelDepthInBits(saveFormat);
component_count = GevGetPixelComponentCount(saveFormat);
img_size = width * height * component_count* ((img_depth + 7)/8);
bufToSave = malloc(img_size);
fill = (component_count == 4) ? 0xFF : 0; // Alpha if needed.
memset( bufToSave, fill, img_size);
allocate_conversion_buffer = 1;
// Convert the Bayer to RGB
ConvertBayerToRGB( 0, height, width, convertedFmt, m_latestBuffer, saveFormat, bufToSave);
}
else
{
saveFormat = convertedFmt;
allocate_conversion_buffer = 0;
}
// Generate a file name from the unique base name.
_GetUniqueFilename(filename, (sizeof(filename)-5), uniqueName);
#if defined(LIBTIFF_AVAILABLE)
// Add the file extension we want.
strncat( filename, ".tif", sizeof(filename));
// Write the file (from the latest buffer acquired).
ret = Write_GevImage_ToTIFF( filename, width, height, saveFormat, bufToSave);
if (ret > 0)
{
printf("Image saved as : %s : %d bytes written\n", filename, ret);
}
else
{
printf("Error %d saving image\n", ret);
}
#else
printf("*** Library libtiff not installed ***\n");
#endif
}
else
{
printf("No image buffer has been acquired yet !\n");
}
// Quick test that the image can be read back.
#if 1
if (ret == 0)
{
uint32_t w, h;
int d;
int num_components = 0;
int pxlsize = 0;
void *rtif = NULL;
uint32_t size;
#if defined(LIBTIFF_AVAILABLE)
File_GetTIFFInfo( filename, &w, &h, &d, &num_components);
//printf("TIFF Info : 1=%d, h=%d, d=%d, spp=%d\n", w,h,d,num_components);
// Calculate the pixel size
pxlsize = (num_components > 1) ? num_components : ((d+7)/8);
size = w*h*pxlsize;
rtif = malloc(size);
if (rtif != NULL)
{
// Set up a suitable pixel format to read.
uint32_t pxlFmt;
if ( num_components == 1 )
{
pxlFmt = (d > 8) ? fmtMono16 : fmtMono8;
}
else if (num_components == 3 )
{
pxlFmt = (d > 8) ? fmtRGB16Packed : fmtRGB8Packed;
}
else if (num_components == 4 )
{
pxlFmt = (d > 8) ? fmtRGBA16Packed : fmtRGBA8Packed;
}
else
{
printf("Error : Unexpected number of pixel components (%d)\n", num_components);
}
Read_TIFF_ToGevImage( filename, &w, &h, pxlFmt, size, rtif);
{
uint32_t i;
unsigned char *orig, *rimg;
orig = (unsigned char *)bufToSave;
rimg = (unsigned char *)rtif;
for (i = 0; i < size; i++)
{
if (orig[i] != rimg[i])
{
printf(" Mismatch : i = %d:\n", i);
break;
}
}
}
free(rtif);
}
#endif
}
#endif
if (allocate_conversion_buffer)
{
free(bufToSave);
}
}
if (c == '?')
{
PrintMenu();
}
if ((c == 0x1b) || (c == 'q') || (c == 'Q'))
{
GevStopTransfer(handle);
done = TRUE;
// context.exit = TRUE;
pthread_join( tid, NULL);
}
}
GevAbortTransfer(handle);
status = GevFreeTransfer(handle);
// DestroyDisplayWindow(View);
for (i = 0; i < numBuffers; i++)
{
free(bufAddress[i]);
}
// if (context.convertBuffer != NULL)
// {
// free(context.convertBuffer);
// context.convertBuffer = NULL;
// }
}
GevCloseCamera(&handle);
}
else
{
printf("Error : 0x%0x : opening camera\n", status);
}
}
}
// Close down the API.
GevApiUninitialize();
// Close socket API
_CloseSocketAPI (); // must close API even on error
//printf("Hit any key to exit\n");
//kbhit();
return 0;
}
结果
编译应用demo的结果如下:
在链接库的顺序确认肯定没出错后,怀疑这些定义都在sdk包里给的静态库中
于是决定用标准的aarch64重新走一遍流程
sudo apt install g++-aarch64-linux-gnu
成功