30.Android Studio下FFmpeg的编译和使用(四.Android Studio ndk开发环境和CMakeLists脚本编写)
项目源码
1.环境配置
ffmpeg库已经编译好了,接下来准备将so引入Android studio进行开发
我们创立一个新的项目,注意在创立过程中这几个选项的勾选
6C~L[SE8UA3Z]JEAFB~CU24.png
勾选增加C++支持,Android studio会自动帮我们做少量配置,后边进行简单的解释
Y%~`T`0D1PM`(`}}$ENC9G2.png
C++ Standard:使用哪种 C++ 标准。选择 Toolchain Default 会使用默认的 CMake 设置。有C11和C14两种,我们选择C11
Exceptions Support:假如希望启用对 C++ 异常解决的支持,请选中此复选框。假如启用此复选框,Android Studio 会将 -fexceptions 标志增加到板块级 build.gradle 文件的 cppFlags 中,Gradle 会将其传递到 CMake。
Runtime Type Information Support:(Run-Time Type Identification),通过运行时类型信息程序能够使用基类的指针或者引用来检查这些指针或者引用所指的对象的实际派生类型。假如希望支持 RTTI,请选中此复选框。假如启用此复选框,Android Studio 会将 -frtti 标志增加到板块级 build.gradle 文件的 cppFlags 中,Gradle 会将其传递到 CMake。
项目创立出来之后,可以看到,项目默认创立了一个调用C++代码的小demo输出一行字符串。在app根目录可以看到一个CMakeLists.txt的文件,这是增加c++支持后默认创立的cmake脚本,我们将使用这个脚本对ffmpeg进行编译
打开app目录下的build.gradle,可以看到下边两项配置
apply plugin: 'com.android.application'android { ... defaultConfig { ... externalNativeBuild { cmake { //C++标准选择C11之后做的配置 cppFlags "-std=c++11" } } } externalNativeBuild { cmake { //指定的CMakeLists脚本文件的路径 path "CMakeLists.txt" } }}
这是工具自动做好的配置,接下来还需要我们手动做少量解决,来完善ffmpeg编译的环境。
第一. ffmpeg播放视频会涉及到操作内存卡,所以需要配置存储权限,6.0及以上Android版本还要记得动态权限获取的配置,这里不多说
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
第二. 在app main目录下创立jniLibs目录,将我们创立好的so放在这个目录下,或者者直接把so放在libs目录下,但是这种方式需要我们在build.gradle中配置路径,这里选用第二种方式
dir.png.png
而后打开app下build.gradle文件,在android/defaultConfig节点下增加如下配置,指定so文件的存放目录,默认是jniLibs
sourceSets{ //将so放在libs文件夹下,需要指定这个路径,由于默认路径是jniLibs main{ jniLibs.srcDirs=['libs'] } }
还有一点,由于我们只编译了armeabi-v7a版本的ffmpeg,所以需要指定过滤版本,在android/defaultConfig/externalNativeBuild节点中增加
ndk{ abiFilters "armeabi-v7a" }
此时,整个build.gradle文件应该是这样的(只留下了ndk相关的配置)
apply plugin: 'com.android.application'android { ... defaultConfig { ... externalNativeBuild { cmake { cppFlags "-std=c++11" } //默认情况下,Gradle 会针对 [NDK 支持的 ABI](https://developer.android.google.cn/ndk/guides/abis.html?hl=zh-cn#sa) //将原生库构建到单独的 .so文件中,并将其一律打包到 APK 中。假如希望 Gradle 仅构建和打包原生 //库的特定 ABI 配置,可以在板块级build.gradle文件中使用 ndk.abiFilters标志指定这些配置 ndk{ //abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a' abiFilters "armeabi-v7a" } } sourceSets{ //将so放在libs文件夹下,需要指定这个路径,由于默认路径是jniLibs main{ jniLibs.srcDirs=['libs'] } } } ... //将 Gradle 关联到原生库,需要提供一个指向 CMake 或者 ndk-build 脚本文件的路径。在构建应用时,Gradle //会以依赖项的形式运行 CMake 或者 ndk-build,并将共享的库打包到 APK 中 externalNativeBuild { cmake { path "CMakeLists.txt" } }}dependencies { ...}
2.CMakeLists.txt脚本文件的编写
CMake 构建脚本是一个纯文本文件,必需将其命名为 CMakeLists.txt,一般放在项目根目录(app的根目录),后边会附上我测试成功的CMakeLists.txt,
CMakeLists Android官方教程
add_library():
该命令用于向CMake构建脚本增加源文件和库,它有三个参数,每个参数的解释如下
add_library( //这个参数指定你的源文件被编译或者者库被引入后的名字,可以指 //定任意你觉得合适的名字 native-lib //第二个参数有STATIC 和SHARED两种选择,SHARED表示会编 //译成动态库,STATIC 表示静态库 SHARED //这个位置用于指定源文件的相对路径(相对于CMakeLists.txt的 //路径),或者者假如你是在引入其余库,那么这里指定IMPORTED //属性 src/main/cpp/native-lib.cpp )
set_target_properties:
假如你add_library引入的是已经编译好的库文件,那么你需要通过set_target_properties指定被引入的库文件的路径
//这两个逐个对应,这两个命令结合可以引入一个so库,一个so库对应这两个命令add_library( avcodec SHARED IMPORTED)set_target_properties( //指定是给谁设置属性,这里是上边add的avcodec avcodec //指定是设置什么样的属性,这里是引入的路径,是一个相对路径 PROPERTIES IMPORTED_LOCATION //这里具体指定相对于脚本文件的路径 ${FFMPEG_DIR}/libavcodec.so)
include_directories():
通过上边两个命令,库文件会被增加进来,这些库一般会依赖少量头文件,这时我们可以通过include_directories来指定头文件的位置,确保 CMake 在编译时可以定位到头文件
include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/include)
以ffmpeg的编译为例,我们会add很多的so库,add_library了好屡次,将所有需要的so增加,我们还add了自己的源文件,最终我们指定了这些源文件被编译成ffmpeg的so
add_library( ffmpeg SHARED ${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/native-lib.cpp )
这些源文件依赖于增加的ffmpeg中的库,所以最终我们要把我们自己编译的库和其余这些so链接到一块,这时就需要命令
target_link_libraries( ffmpeg avcodec avfilter avformat avutil swresample swscale ${log-lib} )
看到这里有个这样的引入${log-lib},这个库是ndk中提供的,通过find_library命令引入
find_library
Android NDK 提供了一套实用的原生 API 和库。通过将NDK 库包含到项目的 CMakeLists.txt脚本文件中,预构建的 NDK 库已经存在于 Android 平台上,因而,无需再构建或者将其打包到 APK 中。因为 NDK 库已经是 CMake 搜索路径的一部分,甚至不需要在本地 NDK 安装中指定库的位置 – 只要要向 CMake 提供希望使用的库的名称,并将其关联到自己的原生库上就可。
将 find_library()命令增加到您的 CMake 构建脚本中以定位 NDK 库,并将其路径存储为一个变量。可以使用此变量在构建脚本的其余部分引用 NDK 库。以下示例可以定位Android 特定的日志支持库并将其路径存储在 log-lib 中
find_library( log-lib log )
3.编译ffmpeg的CMakeLists.txt完整脚本
#指定Cmake构建工具的最低版本cmake_minimum_required(VERSION 3.4.1)#设置头文件路径include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/include)#设置FFmpeg库路径变量#CMAKE_CURRENT_SOURCE_DIR,指的是当前解决的 CMakeLists.txt 所在的路径,CMAKE_SOURCE_DIR,不管采用何种编译方式,都是工程顶层目录set(FFMPEG_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libs/${ANDROID_ABI})#增加avcodecadd_library(avcodec SHARED IMPORTED)set_target_properties(avcodec PROPERTIES IMPORTED_LOCATION ${FFMPEG_DIR}/libavcodec.so)#增加avfilteradd_library(avfilter SHARED IMPORTED)set_target_properties(avfilter PROPERTIES IMPORTED_LOCATION ${FFMPEG_DIR}/libavfilter.so)#增加avformatadd_library(avformat SHARED IMPORTED)set_target_properties(avformat PROPERTIES IMPORTED_LOCATION ${FFMPEG_DIR}/libavformat.so)#增加avutiladd_library(avutil SHARED IMPORTED)set_target_properties(avutil PROPERTIES IMPORTED_LOCATION ${FFMPEG_DIR}/libavutil.so)#增加swresampleadd_library(swresample SHARED IMPORTED)set_target_properties(swresample PROPERTIES IMPORTED_LOCATION ${FFMPEG_DIR}/libswresample.so)#增加swscaleadd_library(swscale SHARED IMPORTED)set_target_properties(swscale PROPERTIES IMPORTED_LOCATION ${FFMPEG_DIR}/libswscale.so)add_library( ffmpeg SHARED ${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/native-lib.cpp )find_library( log-lib log )target_link_libraries( ffmpeg avcodec avfilter avformat avutil swresample swscale ${log-lib} )
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 30.Android Studio下FFmpeg的编译和使用(四.Android Studio ndk开发环境和CMakeLists脚本编写)