写点什么

啃论文俱乐部——移植 speexdsp 到 OpenHarmony 标准系统④

作者:离北况归
  • 2022-10-12
    江苏
  • 本文字数:7381 字

    阅读完需:约 24 分钟

  • 大家好!我来自南京,在 OpenHarmony 成长计划啃论文俱乐部,与华为、软通动力、润和软件、拓维信息、深开鸿等公司一起,学习和研究操作系统技术从今年 1 月 11 日加入 OpenHarmony 俱乐部已经有接近 8 个月时间了。笔者一直在思考啃论文给我带来了些什么,通过啃论文能为 OpenHarmony 做些什么。笔者利用大二升大三暑假两个月时间移植了 Speexdsp 这个三方库到 OpenHarmony 标准系统,而关于前面的问题我似乎找到了答案,现将啃论文和三方库移植分享经验如下:

由于想要分享的内容较多,为避免读者姥爷们失去看下去的耐心,分享将以连载的方式进行。下期预告:speexdsp 功能分析和功能测试


本期为移植speexdsp到OpenHarmony标准系统的第④期,主要内容如下:





speexdsp 移植后已提交至 openhamrony sig 仓库https://gitee.com/openharmony-sig/contest/tree/master/2022_OpenHarmony_thirdparty/speexdsp



五、在 OpenHarmony 编译体系下增量编译 Speexdsp

建议先增量编译生成三方库的动态链接库和可执行文件,验证是否成功把三方库加入 OpenHarmonybian 编译体系。


  • 成功编译出 so 和可执行文件,即成功把三方库加入到 ohos 编译体系。之后还要验证三方库在 ohos 运行,功能是否正常。功能正常才能视为移植成功。


推荐增量编译出三方库的动态链接库和测试用例,不推荐的做法是把三方库加入 openharmony 编译体系后全量编译出烧录 ohos 用的固件。


  • 第一是因为全量编译 ohos 对电脑的性能,特别是内存要求比较高(笔者的笔记本上的虚拟机内存给到了 32G,对学生开发者来讲,编译 ohos 的硬件门槛还是有点高的。)增量编译对内存要求不是特别高。(笔者的 8G 内存二合一笔记本都可以编译出来,并且虚拟机内存只给到了 4GB 左右

  • 第二是因为全量编译花费时间较多(笔者完整编译出一个固件需要 3 个小时左右。)增量编译需要的时间相对较少(笔者大概只需要花费 9 分钟左右


全量编译和增量编译概念

  • 全量编译是将所有文件重新编译,重新生成解决方案就是全量编译

  • 增量编译只对改动的文件进行编译,执行生成解决方案就是增量编译


在源码目录执行如下命令,进行增量编译:


./build.sh --product-name rk3568 --ccache --build-target=speexdsp --target-cpu arm64
复制代码


  • ohos3.2beta1版本开始新增特性,支持 64 位系统的编译,默认情况下编译的都是 32 位系统,在编译命令中添加--target-cpu arm64即可构建 64 位系统,编译 so 和可执行文件的执行语句更改为:


加快本地编译的一些参数

编译时,适当选择添加以下的编译参数可以加快编译的过程。

  • 添加--ccache 参数:

  • 原理:ccache 会缓存 c/c++编译的编译输出,下一次在编译输入不变的情况下,直接复用缓存的产物。

  • 安装:

  • 快速安装:执行 sudo apt-get install ccache 命令。

  • 使用:执行./build.sh --product-name 产品名 --ccache 命令。

  • 添加--fast-rebuild 参数

  • 原理:编译流程主要分为:preloader->loader->gn->ninja 这四个过程,在本地没有修改 gn 和产品配置相关文件的前提下,添加--fast-rebuild 会让你直接从 ninja 编译开始。

  • 使用:执行./build.sh --product-name 产品名 --fast-rebuild 命令。

  • 添加 enable_notice_collection=false 参数

  • 原理:省略掉收集开源软件模块的 license 的过程。

  • 使用:执行./build.sh --product-name 产品名 --gn-args --enable_notice_collection=false --ccache 命令。

  • 添加--build-target 参数

  • 该参数用于指定编译模块,如何找模块的名字:

  • 相关仓下 BUILD.gn 中关注 group、ohos_shared_library、ohos_executable 等关键字。

  • ./build.sh --product-name 产品名 --build-target 模块名 --build-only-gn 生成 build.ninja,然后去该文件中查找相关模块名。

  • 使用:执行./build.sh --product-name 产品名 --build-target ark_js_host_linux_tools_packages 命令。

解决编译报错

(笔者理解移植过程肯定不会是一帆风顺的)


执行编译命令后,有部分报错 1.部分头文件缺失报错‘speexdsp_config_types.h’ file not found


编译找不到 third_party/speexdsp/include/speex 目录下的 speexdsp_config_types.h 文件。


../../third_party/speexdsp/include/speex/speexdsp_types.h:122:10: fatal error: 'speexdsp_config_types.h' file not found
复制代码



解决办法:


  • speexdsp_types.h 是由 linux 下编译生成的,因此需要在 Linux 下编译整个 Speexdsp 源码,然后把在 speexdsp 原生库目录下 build/include/speex 目录生成的 speexdsp_types.h 文件拷贝到要 ohos 源码下的 third_party/speexdsp/include/speex 目录下,


2.json 文件语法发生错误。



解决方法:查看 out/rk3568 目录下 build.log 文件,检查源码/build/subsystem_config.json 文件语法笔者出现这个问题的原因是 json 文件语法发生错误,在 subsystem_config.json 文件第一行的{没有匹配},添加上去就没问题。


编译成功

解决完编译报错后,再次执行编译命令。


./build.sh --product-name rk3568 --ccache --build-target=speexdsp --target-cpu arm64
复制代码



编译成功,终端打印信息如下:(下面只选取关键的一小部分,实际打印出来的信息有两千行左右。)


jiajiahao@ubuntu:~/Desktop/OpenHarmony/sources$ ./build.sh --product-name rk3568 --ccache --build-target=speexdsp --target-cpu arm64++++++++++++++++++++++++++++++++++++++++2022-09-07 22:03:47--product-name rk3568 --ccache --build-target=speexdsp --target-cpu arm64......······[OHOS INFO] [1595/1633] STAMP obj/third_party/speexdsp/speexdsp_share.inputdeps.stamp[OHOS INFO] [1596/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src/ttyname_r.o[OHOS INFO] [1597/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src/ualarm.o[OHOS INFO] [1598/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src/unlink.o[OHOS INFO] [1599/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src/unlinkat.o[OHOS INFO] [1600/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src/usleep.o[OHOS INFO] [1601/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src/write.o[OHOS INFO] [1602/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/unistd/soft_musl_src/writev.o[OHOS INFO] [1603/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/string/soft_musl_src_nossp/mempcpy.o[OHOS INFO] [1604/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/string/soft_musl_src_nossp/memset.o[OHOS INFO] [1605/1633] STAMP obj/third_party/musl/soft_musl_src.stamp[OHOS INFO] [1606/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/buffer.o[OHOS INFO] [1607/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/fftwrap.o[OHOS INFO] [1608/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/filterbank.o[OHOS INFO] [1609/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/env/soft_musl_src_nossp/__libc_start_main.o[OHOS INFO] [1610/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/scal.o[OHOS INFO] [1611/1633] ASM obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/thread/aarch64/soft_musl_src_nossp/__set_thread_area.o[OHOS INFO] [1612/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/env/soft_musl_src_nossp/__init_tls.o[OHOS INFO] [1613/1633] CC obj/out/rk3568/obj/third_party/musl/intermidiates/linux/musl_src_ported/src/env/soft_musl_src_nossp/__stack_chk_fail.o[OHOS INFO] [1614/1633] STAMP obj/third_party/musl/soft_musl_src_nossp.stamp[OHOS INFO] [1615/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/jitter.o[OHOS INFO] [1616/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/preprocess.o[OHOS INFO] [1617/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/resample.o[OHOS INFO] [1618/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/mdf.o[OHOS INFO] [1619/1633] SOLINK obj/third_party/musl/usr/lib/aarch64-linux-ohos/libc.so[OHOS INFO] [1620/1633] STAMP obj/third_party/musl/soft_shared_libs.stamp[OHOS INFO] [1621/1633] STAMP obj/build/config/common_deps.stamp[OHOS INFO] [1622/1633] STAMP obj/build/config/executable_deps.stamp[OHOS INFO] [1623/1633] STAMP obj/build/config/shared_library_deps.stamp[OHOS INFO] [1624/1633] CC obj/third_party/speexdsp/libspeexdsp/speexdsp_share/smallft.o[OHOS INFO] [1625/1633] SOLINK speexdsp/speexdsp/libspeexdsp_share.z.so[OHOS INFO] [1626/1633] LINK speexdsp/speexdsp/testdenoise[OHOS INFO] [1627/1633] LINK speexdsp/speexdsp/testecho[OHOS INFO] [1628/1633] LINK speexdsp/speexdsp/testjitter[OHOS INFO] [1629/1633] LINK speexdsp/speexdsp/testresample[OHOS INFO] [1630/1633] LINK speexdsp/speexdsp/testresample2[OHOS INFO] [1631/1633] STAMP obj/out/rk3568/build_configs/speexdsp/speexdsp/speexdsp_info.stamp[OHOS INFO] [1632/1633] ACTION //out/rk3568/build_configs/speexdsp/speexdsp:speexdsp(//build/toolchain/ohos:ohos_clang_arm64)[OHOS INFO] [1633/1633] STAMP obj/out/rk3568/build_configs/speexdsp/speexdsp/speexdsp.stamp[OHOS INFO] ---------------------------------------------[OHOS INFO] ccache summary:[OHOS INFO] cache hit (direct)  : 0[OHOS INFO] cache hit (preprocessed)  : 0[OHOS INFO] cache miss  : 1340[OHOS INFO] hit rate:  0.00% [OHOS INFO] mis rate: 100.00% [OHOS INFO] ---------------------------------------------[OHOS INFO] c targets overlap rate statistics[OHOS INFO] subsystem         files NO.  percentage  builds NO.  percentage  overlap rate[OHOS INFO] aafwk                   25  0.9%        25  0.9%  1.00[OHOS INFO] arkui                   11  0.4%        11  0.4%  1.00[OHOS INFO] bundlemanager           45  1.5%        45  1.5%  1.00[OHOS INFO] communication          197  6.7%       197  6.7%  1.00[OHOS INFO] hiviewdfx               32  1.1%        32  1.1%  1.00[OHOS INFO] securec                 78  2.7%        78  2.7%  1.00[OHOS INFO] speexdsp                14  0.5%        14  0.5%  1.00[OHOS INFO] startup                 46  1.6%        46  1.6%  1.00[OHOS INFO] third_party           1065  36.3%      1065  36.3%  1.00[OHOS INFO] thirdparty            1065  36.3%      1065  36.3%  1.00[OHOS INFO] utils                   58  2.0%        58  2.0%  1.00[OHOS INFO] zxing-cpp-1.2.0        117  4.0%       117  4.0%  1.00[OHOS INFO] [OHOS INFO] c overall build overlap rate: 1.00[OHOS INFO] [OHOS INFO] [OHOS INFO] rk3568 build success[OHOS INFO] cost time: 0:02:24=====build  successful=====
复制代码

验证编译结果

编译 speexdsp 生成的动态链接库和测试用的可执行程序,在 openharmony 源码目录的 out/rk3568 下。



out/rk3568/speexdsp 目录结构如下:



├── libspeexdsp_share.z.so # 动态链接库├── testdenoise            # 测试用例 ├── testecho               # 测试用例 ├── testjitter             # 测试用例 ├── testresample           # 测试用例 └── testresample2          # 测试用例 
复制代码

六、API 接口导出

在源码 third_party/speexdsp 目录下新建 export_api 文件夹。


1.在 export_api 目录下新建 allHeads.h 文件

该头文件中包含所有库对外导出的头文件。speexdsp 有 5 个测试程序 testdenoise、testecho、testjitter、testresample、testresample2。



查看这五个测试程序的源文件 testdenoise.c、testecho.c、testjitter.c、testresample.c、testresample2.c。



其用到的 libspeexdsp_share.z.so 的头文件如下:


#include "speex_preprocess.h"#include "speex_echo.h"#include "speex_jitter.h"#include "speex_resampler.h"
复制代码

2.新增 allDySos 目录,该目录下放置生成的动态库:

3、新增 allTests 目录,该目录下放置所有生成的测试文件:

4、新建自动化测试脚本 export_interface.sh,如下所示:

其中 cxx="0"表示根据.c 文件进行导出,cxx="1"则表示根据.cpp 文件进行导出(如果导出 c++的三方库的 api 接口,使用该脚本就让 cxx=1):


#!/bin/sh#C库cxx="0"
mixed_api() { while read line do if [ $cxx != "1" -o "$4" == "1" ];then tmp=$line else tmp=`echo $line | sed "s/(.*$//g" | sed "s/^.*:://g"` fi res=`cat $2 |grep "$tmp" -F` if [ "$res" != "" ];then echo "$line" >> $3 fi done < $1}
remove_standard_api() { flag="0" while read line do tmp1=`echo $line |grep ".*#.*\/usr\/"` tmp2=`echo $line |grep ".*#.*[0-9].*\".*\""` if [ "$tmp1" != "" ];then flag="0" elif [ "$tmp2" != "" ];then flag="1" elif [ $flag == "1" ];then echo "$line" >> $2 fi done < $1}
src1="allHeads.h"src2="allDySos"src3="allTests"
if [ $cxx == "1" ];then flags_D="-DC" flags_DU="-DCu" CC=g++else flags_D="-D" flags_DU="-Du" CC=gccfi
if [ ! -e $src1 ];then echo "$src1 is not exist!" exit 1fi
if [ ! -e $src2 ];then echo "$src2 is not exist!" exit 1fi
if [ ! -e $src3 ];then echo "$src3 is not exist!" exit 1fi
rm -rf $src1.i* $src2.txt $src3.txt export_api.txt tested_api.txt
$CC -E $* $src1 -o $src1.i
if [ "$?" != "0" ];then exit 1fi
remove_standard_api $src1.i $src1.i.tmp
nm $src2/* $flags_D | sort -u | grep " T " | sed "s/^.* T //g" >> $src2.txtnm $src3/* $flags_DU | sort -u | sed "s/^.* U //g" >> $src3.txt
mixed_api $src2.txt $src1.i.tmp export_api.txt 0mixed_api export_api.txt $src3.txt tested_api.txt 1
rm -rf $src1.i* $src2.txt $src3.txt
复制代码

执行脚本导出 api 接口

执行该脚本导出 api 接口时,需要给脚本传入编译头文件的参数。(运行此 api 接口导出脚本在 PC 端)


  • 例如./export_interface.sh -I 头文件所在路径 -D宏定义(编译所有动态库时,cflags/cflags_cc中的参数)

  • 头文件所在路径为绝对路径

  • D 宏定义指的是(编译所有动态库时,cflags/cflags_cc 中的参数)


笔者导出 speexdsp API 接口,在 export_api 文件夹下打开终端输入了如下命令:


chmod 777 export_interface.sh./export_interface.sh -I/home/jiajiahao/Desktop/OpenHarmony/sources/third_party/speexdsp/include/speex 
复制代码


结果是生成 export_api.txt(导出 so 对外 api 接口)与 testd_api.txt(导出测试程序所用到 so 对外导出 api 接口 )。



export_api.txt 文件内容如下:


speex_preprocess_state_initspeex_preprocess_state_destroyspeex_preprocessspeex_preprocess_runspeex_preprocess_estimate_updatespeex_preprocess_ctljitter_buffer_initjitter_buffer_ctljitter_buffer_resetjitter_buffer_destroyjitter_buffer_putjitter_buffer_getjitter_buffer_get_anotherjitter_buffer_update_delayjitter_buffer_get_pointer_timestampjitter_buffer_tickjitter_buffer_remaining_spanspeex_echo_state_initspeex_echo_state_init_mcspeex_echo_state_resetspeex_echo_state_destroyspeex_echo_capturespeex_echo_cancellationspeex_echo_playbackspeex_echo_cancelspeex_echo_ctlspeex_resampler_initspeex_resampler_init_fracspeex_resampler_set_qualityspeex_resampler_set_rate_fracspeex_resampler_destroyspeex_resampler_process_floatspeex_resampler_process_intspeex_resampler_process_interleaved_floatspeex_resampler_process_interleaved_intspeex_resampler_set_ratespeex_resampler_get_ratespeex_resampler_get_ratiospeex_resampler_get_qualityspeex_resampler_set_input_stridespeex_resampler_get_input_stridespeex_resampler_set_output_stridespeex_resampler_get_output_stridespeex_resampler_get_input_latencyspeex_resampler_get_output_latencyspeex_resampler_skip_zerosspeex_resampler_reset_memspeex_resampler_strerrorspeex_decorrelate_newspeex_decorrelatespeex_decorrelate_destroy
复制代码


tested_api.txt 文件内容如下:


speex_preprocess_state_initspeex_preprocess_state_destroyspeex_preprocessspeex_preprocess_runspeex_preprocess_ctljitter_buffer_initjitter_buffer_resetjitter_buffer_putjitter_buffer_getjitter_buffer_tickspeex_echo_state_initspeex_echo_state_destroyspeex_echo_cancellationspeex_echo_cancelspeex_echo_ctlspeex_resampler_initspeex_resampler_destroyspeex_resampler_process_floatspeex_resampler_set_ratespeex_resampler_skip_zeros
复制代码

下期预告:speexdsp 功能分析和功能测试

发布于: 刚刚阅读数: 3
用户头像

离北况归

关注

还未添加个人签名 2022-03-26 加入

OpenHarmony啃论文俱乐部PIMF团队。 位于南京一学生,可私信。

评论

发布
暂无评论
啃论文俱乐部——移植speexdsp到OpenHarmony标准系统④_OpenHarmony_离北况归_InfoQ写作社区