当前位置:   article > 正文

Android Studio 单独编译WebRTC的 vad 模块_execinfo.h' file not found

execinfo.h' file not found
Android Studio 3.0.1

Mac OS X 10.12.6

先配置 jni 环境,按照一年前写的文章 android Studio jni 编程 进行配置在build 工程的时候出现错误

Error:Execution failed for task ':app:compileDebugNdk'.
> Error: Your project contains C++ files but it is not using a supported native build system.
  Consider using CMake or ndk-build integration. For more information, go to:
   https://d.android.com/r/studio-ui/add-native-code.html
  Alternatively, you can use the experimental plugin:
   https://developer.android.com/r/tools/experimental-plugin.html

然后搜索到 Android Studio 的文档 向您的项目添加 C 和 C++ 代码

原生库构建的默认工具是 CMake, 所以决定改用 CMake.

首先是配置环境, 向您的项目添加 C 和 C++ 代码 中有就不详细介绍了,首先下载 NDK、CMake、LLDB.
然后创建一个只是 C++的项目看看与以前ndk-build的时候有啥不一样.

build.gradle 文件中,多了 两个 externalNativeBuild 参数 ,defaultConfig 下的 externalNativeBuild 里面的参数 是在创建工程的时候选择的,
-fexceptions 对应创建工程时的选项 Exceptions Support,是启用对 C++异常处理的支持
-frtti 对应创建工程时的选项 Runtime Type Information Support 选项,支持 RTTI 的




多了一个 CMakeyLists.txt 文件 里面的内容就4个函数
cmake_minimum_required,add_library,find_library,target_link_libraries




不同就这些,在现有工程上照着弄一遍就好了.下面下载 webrtc 源码.

在终端 执行命令

git clone https://android.googlesource.com/platform/external/webrtc
下载成功后 

cd webrtc/common_audio/vad 
然后将里面的文件(带 test 的不要)拷贝到统一个目录下(vad_src),然后打开 vad_core.c 文件,根据 #include 的文件路径去找到相应的文件并且把他们都拷贝到现在的目录(递归查找拷贝),并将 #include 的路径去掉.
都弄好后在现有工程上根据上面的分析配置环境, 现在 c++文件都存放在 app/src/main/cpp 路径下了.

将 vad_src 文件夹拷贝到 cpp 目录下 ,执行 Build -> Refresh Linked C++ Projects 刷新,然后修改 CMakeLists.txt文件.


add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp
             src/main/cpp/vad_src/vad_core.c
             			.
             			.	
             			.			)


需要包含的源文件添加到 add_library 函数中,但是文件有好多,一个一个加得累死,幸好 CMake 有一个命令 aux_source_directory ,查找在某个路径下的所有源文件,将搜索到的源文件列表存储到指定的变量中.就像这样

aux_source_directory(src/main/cpp/vad_src/ DIR_LIB_SRCS)

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp
             ${DIR_LIB_SRCS})

用aux_source_directory命令的一个缺点就是你添加新的源文件的时候,它不会触发 CMake 编译,你得手动重新运行CMake.


现在编译会报错 
Error:error: C++ requires a type specifier for all declarations
Error:(20, 2) error: "Must define either WEBRTC_WIN or WEBRTC_POSIX."


第二个错误 是没有宏定义的原因
在 CMakeLists.txt 文件中添加 add_definitions(-DWEBRTC_POSIX) 


第一个错误 点击后会跳到c++0x_warning.h 文件有这一句


This file requires compiler and library support for the \
ISO C++ 2011 standard. This support is currently experimental, and must be \
enabled with the -std=c++11 or -std=gnu++11 compiler options.


需要启用 C++11,需要修改 build.gradle 文件 cppFlags 选项 
cppFlags "-std=c++11 -frtti -fexceptions"


继续编译 错误
Error:(21, 10) fatal error: 'execinfo.h' file not found
execinfo.h 是属于glibc的,Android 用的是bionic 

通过 CMake 和 C++ 库支持 知道ANDROID_STL  CMake 默认用 gnustl_static,那就换一个试试 

在 cppFlags 上一行添加 

arguments = ['-DANDROID_STL=c++_static']
然后编译报错
Error:(44, 9) error: reinterpret_cast from 'pthread_t' (aka 'long') to 'pid_t' (aka 'int') is not allowed
出错文件为 platform_thread.cc 文件,看了源码后发现还是确实宏定义,因为现在是在给 android 编译,
所以在 CMakeLists.txt 文件中添加 add_definitions(-DWEBRTC_ANDROID)

没有报错,然后在测试 cpp 文件中引用 #include "webrtc_vad.h"

编译报错
Error:(10, 10) fatal error: 'webrtc_vad.h' file not found

解决方式是 在 CMakeLists.txt 中添加 引用头文件
include_directories(src/main/cpp/vad_src/)

编译成功.

CMakeLists.txt

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)



# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

aux_source_directory(src/main/cpp/vad_src/ DIR_LIB_SRCS)


add_definitions(-DWEBRTC_POSIX)
add_definitions(-DWEBRTC_ANDROID)

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp
             ${DIR_LIB_SRCS})

include_directories(src/main/cpp/vad_src/)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.example.wolf.webrtc_vad"
        minSdkVersion 15
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                arguments = ['-DANDROID_STL=c++_static']
                cppFlags "-std=c++11 -frtti -fexceptions"
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}

测试文件 native-lib.cpp

  1. #include <jni.h>
  2. #include <string>
  3. #include <stdio.h>
  4. #include <assert.h>
  5. #include <android/log.h>
  6. #include "webrtc_vad.h"
  7. #define LOG_TAG "jnitest"
  8. #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
  9. static jstring jni_sayHello(JNIEnv *env, jobject)
  10. {
  11. int ret = 0;
  12. int i = 0;
  13. int kRates[] = { 8000, 12000, 16000, 24000, 32000, 48000 };
  14. int kMaxFrameLength = 16;
  15. int kFrameLengths[] = { 80, 120, 160, 240, 320, 480, 640, 960 };
  16. short zeros[160] = {0};
  17. short speech[160] = {0};
  18. for (i = 0; i < 160; i++) {
  19. speech[i] = (i * i);
  20. }
  21. VadInst* handle = WebRtcVad_Create();
  22. WebRtcVad_Init(handle);
  23. WebRtcVad_set_mode(handle,0);
  24. ret = WebRtcVad_Process(handle, kRates[2], speech, kFrameLengths[2]);
  25. LOGD("ret1 = %d\n",ret);
  26. ret = WebRtcVad_Process(handle, kRates[2], zeros, kFrameLengths[2]);
  27. LOGD("ret2 = %d\n",ret);
  28. WebRtcVad_Free(handle);
  29. std::string hello = "Hello from C++";
  30. return env->NewStringUTF(hello.c_str());
  31. }
  32. static jboolean jni_calcDecibelLevel(JNIEnv *env, jobject,jshortArray buffer,jint offseetInshort,jint readSize)
  33. {
  34. VadInst* handle = WebRtcVad_Create();
  35. WebRtcVad_Init(handle);
  36. WebRtcVad_set_mode(handle,0);
  37. short speech[160] = {0};
  38. int index = readSize/160;
  39. jshort *pcm_data = env->GetShortArrayElements(buffer, JNI_FALSE);
  40. bool b;
  41. for (int i = 0; i < index; ++i) {
  42. int vad = WebRtcVad_Process(handle, 16000, pcm_data+offseetInshort+i*160, 160);
  43. if(vad==1)
  44. b = JNI_TRUE;
  45. }
  46. env->ReleaseShortArrayElements(buffer,pcm_data,JNI_ABORT);
  47. WebRtcVad_Free(handle);
  48. return b;
  49. }
  50. /**
  51. * JNINativeMethod由三部分组成:(1)Java中的函数名;
  52. (2)函数签名,格式为(输入参数类型)返回值类型;
  53. (3)native函数名
  54. */
  55. static JNINativeMethod gMethods[] = {
  56. {"stringFromJNI", "()Ljava/lang/String;", (void *)jni_sayHello},
  57. {"calcDecibelLevelJNI", "([SII)Z", (void *)jni_calcDecibelLevel},
  58. };
  59. jint JNI_OnLoad(JavaVM *vm, void *reserved)
  60. {
  61. JNIEnv *env = NULL;
  62. jint result = JNI_FALSE;
  63. if (vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK) { 从JavaVM获取JNIEnv
  64. LOGD("Error GetEnv\n");
  65. return result;
  66. }
  67. assert(env != NULL);
  68. //获取类引用,这里可以找到要注册的类,前提是这个类已经加载到java虚拟机中
  69. jclass clazz = env->FindClass("com/example/wolf/webrtc_vad/RecordAudioPcm");
  70. if (clazz == NULL) {
  71. return result;
  72. }
  73. //注册方法,把本地函数和一个java类方法关联起来
  74. if (env->RegisterNatives(clazz, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) < 0) {
  75. return result;
  76. }
  77. return JNI_VERSION_1_4;
  78. }

java文件

  1. public class RecordAudioPcm {
  2. private static final String TAG = "RecordAudioPcm";
  3. static {
  4. System.loadLibrary("native-lib");
  5. }
  6. public native String stringFromJNI();
  7. public native boolean calcDecibelLevelJNI(short[] buffer,int offseetInshort, int readSize) ;}




声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/261399?site
推荐阅读
相关标签
  

闽ICP备14008679号