这里记录一下ffmpeg的编译过程而且在Andorid中使用的过程。java
这里拿的当前日期最新的release版本ffmpeg4.0.2,编译环境mac,下载mac版本的ffmepg后进行编译,编译脚本build.sh以下:linux
#!/bin/bash export NDK=/Users/linchen/Library/Android/sdk/ndk-bundle export SYSROOT=$NDK/platforms/android-19/arch-arm/ export TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64 export CPU=arm export PREFIX=/Users/linchen/Desktop/arm #最终编译后的头文件以及so包的位置 export ADDI_CFLAGS="-marm" function build_one { ./configure \ --prefix=$PREFIX \ --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \ --arch=arm \ --sysroot=$SYSROOT \ --extra-cflags="-Os -fpic $ADDI_CFLAGS" \ --extra-ldflags="$ADDI_LDFLAGS" \ --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \ --nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm \ --enable-shared \ --enable-runtime-cpudetect \ --enable-gpl \ --enable-small \ --target-os=android \ --enable-cross-compile \ --disable-debug \ --disable-static \ --disable-doc \ --disable-asm \ --disable-ffmpeg \ --disable-ffplay \ --disable-ffprobe \ --enable-postproc \ --enable-avdevice \ --disable-symver \ --disable-stripping \ $ADDITIONAL_CONFIGURE_FLAG sed -i '' 's/HAVE_LRINT 0/HAVE_LRINT 1/g' config.h sed -i '' 's/HAVE_LRINTF 0/HAVE_LRINTF 1/g' config.h sed -i '' 's/HAVE_ROUND 0/HAVE_ROUND 1/g' config.h sed -i '' 's/HAVE_ROUNDF 0/HAVE_ROUNDF 1/g' config.h sed -i '' 's/HAVE_TRUNC 0/HAVE_TRUNC 1/g' config.h sed -i '' 's/HAVE_TRUNCF 0/HAVE_TRUNCF 1/g' config.h sed -i '' 's/HAVE_CBRT 0/HAVE_CBRT 1/g' config.h sed -i '' 's/HAVE_RINT 0/HAVE_RINT 1/g' config.h make clean # 这里是定义用几个CPU编译 make -j4 make install } build_one
build.sh在ffmpeg4.0.2的根目录下,首先须要安装一些须要的编译环境如gcc等,因为个人机子中之前已经安装了,因此直接运行bash build.sh
命令就能够了,编译后在个人桌面上会出现arm文件夹:android
其中include文件夹是导出的头文件文件夹,lib中的so包是须要使用的,接下来新建一个支持c++的Android项目,在新建的时候选择support c++
,Android Studio会自动帮咱们配置好,接下添加编译好的文件到Android Studio中: c++
因为个人手机是arm64-v8a的cpu架构,又因为编译ffmpeg选择的架构,因此这里使用armeabi通用架构支持,所以文件夹就建立了armeabi,若是手机cpu架构不一样,能够再编译ffmpeg的时候指定对应的架构,具体参考这篇文章。git
接下来编写一下Cmake代码:github
cmake_minimum_required(VERSION 3.4.1) 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) 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) set(distribution_DIR ${CMAKE_SOURCE_DIR}/src/main/jni/armeabi) add_library( avutil SHARED IMPORTED ) set_target_properties( avutil PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/libavutil.so) add_library( swresample SHARED IMPORTED ) set_target_properties( swresample PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/libswresample.so) add_library( avcodec SHARED IMPORTED ) set_target_properties( avcodec PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/libavcodec.so) add_library( avfilter SHARED IMPORTED ) set_target_properties( avfilter PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/libavfilter.so) add_library( swscale SHARED IMPORTED ) set_target_properties( swscale PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/libswscale.so) add_library( avdevice SHARED IMPORTED ) set_target_properties( avdevice PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/libavdevice.so) add_library( avformat SHARED IMPORTED ) set_target_properties( avformat PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/libavformat.so) add_library( postproc SHARED IMPORTED ) set_target_properties( postproc PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/libpostproc.so) set(CMAKE_VERBOSE_MAKEFILE on) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") include_directories(src/main/cpp) include_directories(src/main/jni/include) target_link_libraries( # Specifies the target library. native-lib avutil #工具库(大部分须要) swresample #音频采样数据格式转换 avcodec #编解码(重要) avfilter #滤镜特效处理 swscale #视频像素数据格式转换 avdevice #各类设备的输入输出 avformat #封装格式处理 postproc #后加工 # Links the target library to the log library # included in the NDK. ${log-lib})
而后再MainActivity中使用so库:bash
public class MainActivity extends AppCompatActivity { // Used to load the 'native-lib' library on application startup. static { //加载so包是有序的必定要那么写,不过这里我是复制过来的,因此没出现问题 System.loadLibrary("avutil"); System.loadLibrary("swresample"); System.loadLibrary("avcodec"); System.loadLibrary("avfilter"); System.loadLibrary("swscale"); System.loadLibrary("avdevice"); System.loadLibrary("avformat"); System.loadLibrary("postproc"); System.loadLibrary("native-lib"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Example of a call to a native method TextView tv = (TextView) findViewById(R.id.sample_text); tv.setText(stringFromJNI()); } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ public native String stringFromJNI(); }
这里编译过程当中遇到一个问题:架构
Build command failed. Error while executing process /Users/linchen/Library/Android/sdk/cmake/3.6.4111459/bin/cmake with arguments {--app
...ide
../../../../src/main/jni/armeabi/libavutil.so: error adding symbols: File in wrong format clang++: error: linker command failed with exit code 1 (use -v to see invocation) ninja: build stopped: subcommand failed.
问题是jni文件夹下的架构包缺失,使用ndk abi过滤器过滤便可:
ndk { abiFilters 'armeabi' }
编译完成后运行项目发现直接奔溃了,说ffmpeg的so包找不到,解压apk一看还真是,最终发现设置sourceSets的路径不对,修改以下:
sourceSets{ main{ jniLibs.srcDirs = ['src/main/jni'] } }
最终编译成功,项目正常启动,不过还没写代码验证,这里主要先记录一下配置的过程。
项目地址以下: