如果做高通平台的VR开发,QVRService是绕不过的坎
可以这么说,QVRService是高通VR平台的软件层最核心的组件,其中不仅集成了高通的SLAM算法,负责向SDK输出Pose、内容端和硬件层互传Event,还涉及到对cdsp的调度,VST partial frame模式实现、SLAM和VST Camera的图像传输、SLAM Camera软件同步等重要功能,另外还包括对6DOF标定的QVRDatalogger,Qvrservicetest等都集成在QVRService
因此,对QVRService的开发,是基于高通VR平台开发十分重要的一环,否则数据流从kernel往上过了qvrservice,output就只有pose和event,想要在openxr、runtime层拓展功能、api或获取一些数据源(例如:camera图像数据、IMU数据)就无法实现。
目前,高通在其createpoint网站上或者通过case找高通能够获取到的高通SDK,应该还是2021年下半年高通公开出来的SnapdragonXR-SDK 4.0.6。
相比于上一版SnapdragonXR-SDK 4.0.5、SnapdragonXR-SDK 4.0.6有诸多改变,先对比一下这两版SDK最主要的不同之处:
1.在SnapdragonXR-SDK 4.0.5中,qvrservice的api可以直接在NDK环境中进行脚本编码和编译,生成可执行文件或动态库,然后直接执行或调用来操作qvrservice,熟悉NDK脚本开发的对此应该不陌生
2.在SnapdragonXR-SDK 4.0.6中, 4.0.5里qvrservice的绝大部分api基本上没有变化,但是最关键的两个结构体 qvrcamera_client_helper_t 和 qvrservice_client_helper_t 的创建接口却不一样了。
qvrservice_client_helper_t:
SnapdragonXR-SDK 4.0.5 SnapdragonXR-SDK 4.0.6
QVRServiceClient_Create() QXRCoreClient_Create(JavaVM* javaVM, jobject context)
qvrcamera_client_helper_t:
SnapdragonXR-SDK 4.0.5 SnapdragonXR-SDK 4.0.6
QVRCameraClient_Create() QXRCamClient_Create(JavaVM* javaVM, jobject context)
这两个结构体句柄分别对应了qvrservice两大功能模块:QVR Service 和 QVR Camera Service
SnapdragonXR-SDK 4.0.6的改动是为了适配Android12的安全策略,也就是说无法再对qvrservice直接脚本编程,NDK编译,push到system或vendor去直接操作了。
必须得老老实实的按照android应用调用C/C++的调用标准,通过application层传入 javaVM虚拟机内存地址 和 application的运行上下文。
这也就是高通在后续将要发布的基于OpenXR+Runtime架构的SnapdragonXR OpenXR SDK V1.x,其相关交付件大多都以apk形式集成了,甚至包括Runtime都做成了apk集成在vendor里面,要不然平台运行的插件就没法通过Runtime调用到qvrservice.
(1).SnapdragonXR-SDK 4.0.5 SnapdragonXR-SDK 4.0.6
(2).qvrservice_client_helper_t 创建方式对比:
(3).qvrcamera_client_helper_t 创建方式对比:
基于SnapdragonXR-SDK 4.0.6的特性,如果要对qvrservice进行编程开发,就需要进行JNI方式的Native开发,才能成功调用到qvrservice的API:
先回顾下JNI 编程所需要用到的几个基本参数:
1.JavaVm
JavaVM 是虚拟机在 JNI 层的代表,一个进程只有一个 JavaVM,所有的线程共用一个 JavaVM。
其指针指向了java虚拟机的内存首地址
2.JNIEnv
JNIEnv 表示 Java 调用 native 语言的环境,是一个封装了几乎全部 JNI 方法的指针。
JNIEnv 只在创建它的线程生效,不能跨线程传递,不同线程的 JNIEnv 彼此独立。
作为一个结构体,它里面定义了JNI系统操作函数,在jni.h中能够找到其详细定义
3.jobject 类型
jobject可以看做是java中的类实例的引用。当然,情况不同,意义也不一样。
如果native方法不是static, obj 就代表native方法的类实例。
如果native方法是static, obj就代表native方法的类的class 对象实例(static 方法不需要类实例的,所以就代表这个类的class对象)。
在针对qvrservice的开发中,需要传入的jobject是java 层的application context实例
1.需要include的头文件
include SnapdragonXR-SDK-source.rel.4.0.6/3rdparty/ 下面qvr和qxr两个目录里的所有头文件
代码如下:
2.jniLibs下面需要加载的so库
加载 SnapdragonXR-SDK-source.rel.4.0.6\3rdparty\qxr\libs\arm64-v8a 下的三个so
代码图示如下:
3.加载aar包
SnapdragonXR-SDK-source.rel.4.0.6\3rdparty\qxr\libs 目录下有 1个jar包 和 3个aar包:
这四个包主要是用于创建 qvrservice 相关结构体句柄时,需要链接的一些service的.class文件
不用全部都 implementation 到工程代码中,要不然会有很多重复的类文件会导致编译不过,
classes.jar中的class文件最少,不考虑加载
本次调试使用了qxrclientlibs-cppstatic-release.aar
4.service权限声明
AndroidMainfest.xml里对上述aar里包含的需要链接的service权限进行申请
5.CMakeLists.txt的编写
主要包含如下几个部分:
(1).声明jni so和编译成jni so的源文件
(2).IMPORTED jniLibs下要加载的外部so
(3).需要被include的头文件
(4).jni so需要link的外部so
代码如下:
6.代码实现
(1).JNI 函数声明:
(2).java activity的onCreate()中调用JNI,传入applicationContext
(3).通过JNIEnv获取到JavaVM,保存JavaVM和上一步传下来的context:
(4).关键结构体的创建:
第(2)步中由java层调用的nativeQxrTest()在jni执行之后
对qvrcamera_client_helper_t 、qvrservice_client_helper_t 两个关键结构体进行创建,
获取到句柄:
在拿到qvrcamera_client_helper_t 、qvrservice_client_helper_t 的句柄后,
就可以调用QVRService 的相关Api 进行QVRService 的开发了。
从Log中可以看到,
qvrcamera_client_helper_t * qvrcamera_client
qvrservice_client_helper_t * qvrservice_client
都创建成功了,
并且通过 qvrservice_client 也能调用qvrservice_client的相关api获取到当前tracking_mode等。
但是在创建qvrcamera_device_helper_t的句柄时却出现了Failed,
原因是在创建qvrcamera_client后,还需要调用
QVRCameraClient_AttachCamera(qxrcamclient_t* helper, const char* pCameraName)
创建出qvrcamera_device_helper_t * device_helper。
QVRService中所有针对Camera的操作
实际是通过 qvrcamera_device_helper_t 的句柄调用Api实现的
1.QVRService Api的详细注解,可以在高通createpoint网站上下载文档:
《80-PV306-1-SXR2130 XR Platform API Reference.pdf》
如果权限不够搜索不到,可向高通提Case获取。
2.高通发布的 SnapdragonXR-SDK 4.0.6 并不是基于OpenXR 标准的SDK,
这是2021.09.21高通发布的SDK。
高通即将发布的新版SDK,
是基于OpenXR开源标准命名为SnapdragonXR OpenXR SDK v1.x系列的SDK。
因此,SnapdragonXR-SDK 4.0.6 后续高通不会再维护,也不会再有衍生版本。
本次调试时,是基于Android12的VR设备,Android12是2021.10.05发布的
在Android 12设备上调试QVRService Camera相关功能时,需要使用高通为了适配Android12
同时也是基于OpenXR的将要发布的新SDK:SnapdragonXR OpenXR SDK v1.x中的API
在SnapdragonXR OpenXR SDK v1.x中,
高通将创建qvrcamera_device的 AttachCamera API从
QVRCameraClient_AttachCamera(qvrcamclient_t* helper, const char* pCameraName)
换成了:
QXRCamClient_AttachCamera(qxrcamera_client, const char* pCameraName)
所以调用QVRCameraClient_AttachCamera(...)就会Failed
要想qvrcamera_device在Android 12的VR设备上创建成功,就需要使用
SnapdragonXR OpenXR SDK v1.x 中的so和QXRCamClient_AttachCamera(...)才行、
3.在此次调试过程中,曾经遇到过 QXRCamClient_Create(TxrAndroidContextGetVM(), (jobject) Context);直接引用java层传下来的ApplicationContext后的引用报错
在代码中引入了github上开源的jnipp.cpp和jnipp.h后运行正常
GitHub - mitchdowd/jnipp: C++ wrapper for the Java Native Interface
这是一个C++ wrapper,对jni进行了再次封装。
基于SnapdragonXR-SDK 4.0.6 进行QVRService的开发就总结到这,
这是高通不会再进行维护的SDK版本,
但是根据目前能了解到的信息,相对于SnapdragonXR-SDK 4.0.6 ,高通即将发布的SnapdragonXR OpenXR SDK v1.x尽管在软件层级和架构上变化很大,使用了OpenXR+Runtime的方式,但是QVRService的Api高通几乎没有做什么改动。
所以基于SnapdragonXR-SDK 4.0.6进行的QVRService的开发,在高通新版SDK上依然可用,至于AttachCamera无法成功的问题,待拿高通发布新的SDK后自然就不存在了
后续的博文会持续跟进高通新版SDK的发布进展,以及基于新版SDK如何进行QVRService开发
敬请关注