前面用了大概6篇和大家分享了关于JNI的一系列内容,相信大家看过后肯定对JNI有了大致的了解。其实JNI的主要内容基本都是API的一些使用操作。
最近在研究Android音视频的一些内容,今天就和大家分享一下如何编译ffmpeg并集成到Android Studio环境下使用。
提示:
1. 编译ffmpeg基于window10环境
2. Android Studio版本为2.2+
3. ffmpeg版本为3.x
一、编译ffmpeg
ffmpeg在linux操作系统下编译要方便的多,在window下需要我们做一些额外的工作,我们使用MinGw工具来编译。
1.安装MinGw
MinGw的exe文件和源码开源在SourceForge,点击即可下载
2. 安装完成后,下载msys-base和mingw-32-gcc-ada两个库文件即可。这里我们主要是使用gcc来完成编译工作。
3. 将bin目录配置到系统Path环境变量:
4. 因为ffmpeg编译出来的so文件后缀不能直接在Android环境下使用,所以需要我们找到ffmpeg文件夹下的configure文件并打开,搜索SLIBNAME_WITH_MAJOR定位到该行,将原来的:
SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'
替换为:
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
也就是修改编译出来的so文件后缀为.so形式。
5. 在ffmpeg目录下创建一个build_android.sh文件,拷贝如下代码:
#!/bin/bash
export TMPDIR=C:/Users/Song/Desktop/ffmpeg-3.2.4/tmpdir
NDK=D:/Android/android_studio/sdk/ndk-bundle
SYSROOT=$NDK/platforms/android-23/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64
CPU=arm
PREFIX=C:/Users/Song/Desktop/ffmpeg-3.2.4/install
ADDI_CFLAGS="-marm"
function build_one
{
./configure \
--prefix=$PREFIX \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-doc \
--disable-symver \
--enable-small \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=linux \
--arch=arm \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $ADDI_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
build_one
read -p "Press any key to continue." var
上面需要我们注意的地方有以下几点:
(1)TMPDIR :该字段指向一个文件夹目录,该文件夹路径可任意指定。作用是在编译ffmpeg期间,会生成一些临时文件用于存放在该目录,编译完成后,临时文件会自动清除。
(2)NDK:即你本地电脑NDK目录
(3)SYSROOT:根据你目前的NDK中platforms文件夹下的版本来设置。
(4)PREFIX:ffmpeg编译完成的so文件存放路径,可随意指定。
其它保持不变即可。
6. 执行gcc命令编译
打开MinGW目录下的msys文件夹,找到msys.bat,打开:
cd切换到ffmpeg根目录,执行./build_android.sh开始编译,这时,你可以先去泡杯咖啡喝上一口等待它编译完成。经锅一段时间后,当ffmpeg编译完成,打开第5步中我们配置的PREFIX所指向的目录。可以发现多了两个文件夹:
其中,include就是编译出来的头文件,lib中就是so文件了:
此时,对于ffmpeg的编译工作就搞定啦~,接下来我们就要将编译出来的文件集成到Android Studio中进行校验是否正确,如何集成呢?继续来看~
二、ffmpeg集成到Android Studio
Android Studio 2.2以上版本采用了cmake来代替老版本的ndk-build方式。在NDK的开发上也越来越方便。我们也使用cmake的方式来编译ffmpeg。
1. 将编译好的头文件和so库添加到cpp目录下
2. 在main目录下创建jniLibs目录存放so文件:
2. 配置CMakeLists文件
#添加ffmpeg对应的头文件目录在CmakeList文件中:
include_directories(src/main/cpp/ffmpeg3/include)
#添加库文件,实际上就是引入so文件,IMPORT代表从第三方引入
add_library(avcodec-lib SHARED IMPORTED)
#这句话是ffmpeg对应的so文件,so文件是放到JNILibs这个文件夹中
set_target_properties(avcodec-lib PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/armeabi/libavcodec-57.so)
add_library(avdevic-lib SHARED IMPORTED)
set_target_properties(avdevic-lib PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/armeabi/libavdevice-57.so)
add_library(avfilter-lib SHARED IMPORTED)
set_target_properties(avfilter-lib PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/armeabi/libavfilter-6.so)
add_library(avformat-lib SHARED IMPORTED)
set_target_properties(avformat-lib PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/armeabi/libavformat-57.so)
add_library(avutil-lib SHARED IMPORTED)
set_target_properties(avutil-lib PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/armeabi/libavutil-55.so)
add_library(swresample-lib SHARED IMPORTED)
set_target_properties(swresample-lib PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/armeabi/libswresample-2.so)
add_library(swscale-lib SHARED IMPORTED)
set_target_properties(swscale-lib PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/armeabi/libswscale-4.so)
# 指定库CMake链接到您的目标库。 您可以链接多个库,例如你在中定义的库构建脚本,预构建的第三方库或系统库.
target_link_libraries( # 指定目标库.
native-l
# 为native-lib加载ffmpeg库
avcodec-lib
avdevic-lib
avfilter-lib
avformat-lib
avutil-lib
swresample-lib
swscale-lib
# 将目标库链接到日志库包括在NDK中.
${log-lib} )
(1)首先使用include_directories配置了ffmpeg的头文件路径。将ffmpeg的头文件包含进来。
(2)将JniLibs目录下的so文件引入。
(3)将目标库和引入的so文件链接。
经过以上几步,ffmpeg就集成到了我们的工程下。接下来就是测试啦~
1. 打开app.gradle,在defaultConfig下配置:
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
arguments '-DANDROID_TOOLCHAIN=clang','-DANDROID_STL=gnustl_static'
}
}
ndk {
abiFilters 'armeabi' //arm64-v8a','x86', 'x86_64', 'armeabi-v7a'
}
2. 在cpp目录下创建cpp文件,首先包含头文件
extern "C"{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
}
3. 调用ffmpeg的API函数,例如:
如果程序没有提示错误,证明ffmpeg已经成功的集成啦~
ok,以上就是关于ffmpeg的编译和使用内容,有问题的朋友可以给我留言哈~