Dalsa相机的aarch64移植:aarch64-linux-gnu交叉编译

前言

  近日,有需求想在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外,还需要进入卸载时提醒的目录,再次执行另一个卸载脚本(就离谱,生怕一下卸干净了)

扫描二维码关注公众号,回复: 14607814 查看本文章

返回第一步

  仔细检查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, &param); // 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

  成功
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42330920/article/details/127485258