FFmpeg: mac下手动编译android上使用的FFmpeg(支持x86、armeabi-v7a、arm64-v8a)
之前一直在linux下编译FFmpeg,最近换电脑了,尝试了下在mac下编译ffmpeg,特记录之。
一. 准备工作
1. 下载FFmpeg。(http://ffmpeg.org/download.html#releases),看了下最新的是4.1.4,我用的是3.4.6。
2. 下载mac上使用的NDK。(https://developer.android.google.cn/ndk/downloads/index.html), 我用的是android-ndk-r14b-darwin-x86_64.zip,不推荐使用ndk-bundle,有些头文件在ndk-bundle里没有,遇到过一次。
3. 修改FFmpeg3.4.6目录下的configure文件。如果不修改的话之后编译生成的版本号会加在so的后面,会导致android不能识别,切记。

修改的内容如下,将:
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)'
4. 编写编译用的脚本文件。这个网上有很多,我找到了两个可以用的:
用于编译 armeabi-v7a、arm64-v8a、x86_64版本的:
#!/bin/bash echo "进入FFmpeg编译脚本" # NDK环境
export NDK=/Users/haiyuegao/Library/Android/android-ndk-r14b
export SYSROOT=$NDK/platforms/android-/arch-arm
export TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
PREFIX=android-build COMMON_OPTIONS="\
--prefix=android/ \
--target-os=android \
--enable-shared \
--enable-runtime-cpudetect \
--enable-small \
--disable-static \
--disable-debug \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-doc \
--disable-symver \
--disable-asm \
--disable-stripping \
--disable-armv5te \
" function build_android { echo "开始编译FFmpeg..." # armeabi
echo "开始编译FFmpeg(armeabi)"
./configure \
--libdir=${PREFIX}/libs/armeabi \
--incdir=${PREFIX}/include/armeabi \
--pkgconfigdir=${PREFIX}/pkgconfig/armeabi \
--arch=arm \
--cpu=armv6 \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--sysroot=$SYSROOT \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
echo "结束编译FFmpeg(armeabi)" # armeabi-v7a
echo "开始编译FFmpeg(armeabi-v7a)"
./configure \
--libdir=${PREFIX}/libs/armeabi-v7a \
--incdir=${PREFIX}/include/armeabi-v7a \
--pkgconfigdir=${PREFIX}/pkgconfig/armeabi-v7a \
--arch=arm \
--cpu=armv7-a \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--sysroot=$SYSROOT \
--extra-cflags="-march=armv7-a -mfloat-abi=softfp -mfpu=neon" \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
echo "结束编译FFmpeg(armeabi-v7a)" # arm64-v8a
echo "开始编译FFmpeg(arm64-v8a)"
./configure \
--libdir=${PREFIX}/libs/arm64-v8a \
--incdir=${PREFIX}/include/arm64-v8a \
--pkgconfigdir=${PREFIX}/pkgconfig/arm64-v8a \
--arch=aarch64 \
--cpu=armv8-a \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--sysroot=$SYSROOT \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
echo "结束编译FFmpeg(arm64-v8a)" # x86_64
echo "开始编译FFmpeg(x86_64)"
./configure \
--libdir=${PREFIX}/libs/x86_64 \
--incdir=${PREFIX}/include/x86_64 \
--pkgconfigdir=${PREFIX}/pkgconfig/x86_64 \
--arch=x86_64 \
--cpu=x86_64 \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--sysroot=$SYSROOT \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
echo "结束编译FFmpeg(x86_64)" echo "编译结束" };
build_android
macos_build_android.sh
用于编译x86版本的
#!/bin/bash echo "进入FFmpeg编译脚本" # NDK环境
export NDK=/Users/haiyuegao/Library/Android/android-ndk-r14b
export SYSROOT=$NDK/platforms/android-/arch-x86
export TOOLCHAIN=$NDK/toolchains/x86-4.9/prebuilt/darwin-x86_64
PREFIX=android-build COMMON_OPTIONS="\
--prefix=android/ \
--target-os=android \
--enable-shared \
--enable-runtime-cpudetect \
--enable-small \
--disable-static \
--disable-debug \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-doc \
--disable-symver \
--disable-asm \
--disable-stripping \
--disable-armv5te \
" function build_android { echo "开始编译FFmpeg..." # x86
echo "开始编译FFmpeg(x86)"
./configure \
--libdir=${PREFIX}/libs/x86 \
--incdir=${PREFIX}/include/x86 \
--pkgconfigdir=${PREFIX}/pkgconfig/x86 \
--arch=x86 \
--cpu=i686 \
--cross-prefix=$TOOLCHAIN/bin/i686-linux-android- \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic -march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32" \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
echo "结束编译FFmpeg(x86)" echo "编译结束" };
build_android
macos_build_android_x86.sh
需要注意的是:要根据自己电脑的实际环境修改下上面的NDK目录地址,我的NDK地址是:

5. 修改脚本的执行权限。将脚本放置到ffmpeg的根目录下,为其添加执行权限:

然后打开终端,cd到ffmpeg那级目录,分别执行以下两条命令(如果要编译x86版本,就把shell脚本的名字换成x86版本的那个):
chmod macos_build_android.sh
./macos_build_android.sh
6. 开始编译。视电脑的配置不同编译的时间也不同,我电脑用了大约5分钟左右完成了编译。

等待编译完成,稍后ffmpeg那级目录会出现一个android-build文件夹,里面包含了我们会用到的库文件和头文件。

二. 集成FFmpeg到项目中
1. 新建一个支持C++的Android Studio 项目。
2. 拷贝ffmpeg库文件和头文件。将编译生成的libs文件夹和include文件夹分别拷贝到项目的app目录下:

3. 更新配置文件。
修改app目录下的build.gradle文件:
添加下列代码到gradle文件:
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
}
ndk {
abiFilters "armeabi-v7a","x86"
}
}
sourceSets {
main {
jniLibs.srcDirs=['libs']
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
最终文件如下:
apply plugin: 'com.android.application'
android {
compileSdkVersion
defaultConfig {
applicationId "com.yongdaimi.android.ffapitest"
minSdkVersion
targetSdkVersion
versionCode
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
}
ndk {
abiFilters "armeabi-v7a","x86"
}
}
sourceSets {
main {
jniLibs.srcDirs=['libs']
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
build.gradle
修改app目录下的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.) # 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. # 添加头文件路径
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/${ANDROID_ABI}) # 设置FFmpeg库所在路径
set(FF ${CMAKE_CURRENT_SOURCE_DIR}/libs/${ANDROID_ABI}) # 打印当前位置信息
message("Current souce file positon: " ${CMAKE_CURRENT_SOURCE_DIR}) # avcodec
add_library(avcodec SHARED IMPORTED)
set_target_properties(avcodec PROPERTIES IMPORTED_LOCATION ${FF}/libavcodec.so) 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) # 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
avcodec # Links the target library to the log library
# included in the NDK.
${log-lib})
CMakeLists.txt
最终目录结构如下:

这里一定要注意CMakeLists.txt这个文件的位置,我在Windows下创建AS项目时这个文件在app目录下,在Mac上创建AS项目时这个文件却在app/src/main/cpp目录下,个人为了保持习惯,便将这个文件仍然移动到了app目录下,若使用Mac上默认的位置,则上述CMakeLists.txt和build.gradle中声明文件的位置部分也需要修改,切记。
4. 添加测试代码。打开native-lib.cpp,修改已有的JNI方法:
#include <jni.h>
#include <string> extern "C" {
#include <libavcodec/avcodec.h>
} extern "C" JNIEXPORT jstring JNICALL
Java_com_yongdaimi_android_ffapitest_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++"; hello += avcodec_configuration(); return env->NewStringUTF(hello.c_str());
}
由于FFmpeg是使用纯C编写的,因此在导入其头文件的时候要注意使用extern "C" 大括号包裹。
之后运行项目,如果能出现相关的配置信息就说明FFmpeg已经加载成功了。

三. 常见错误说明
1. Error computing CMake server result.
若编译出现
Error computing CMake server result.
Check for working C compiler: D:/sdk/sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe
Check for working C compiler: D:/sdk/sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe -- works
Detecting C compiler ABI info
Detecting C compiler ABI info - done
Detecting C compile features
Detecting C compile features - done
Check for working CXX compiler: D:/sdk/sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/bin/clang++.exe
Check for working CXX compiler: D:/sdk/sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/bin/clang++.exe -- works
Detecting CXX compiler ABI info
Detecting CXX compiler ABI info - done
Detecting CXX compile features
Detecting CXX compile features - done
Boost version: 1.70.
Configuring for JNI
Configuring done
则打开Build的Toggle View按钮,根据Log分析出错的详细原因,看看是native-lib.cpp的文件找不到或者是其它问题。

2. ninja error needed by missing and no known rule to make it
Error:error: '../../../../src/main/jniLibs/x86/libstblur_preview_api.so',
needed by '../../../../build/intermediates/cmake/debug/obj/x86/libjnistblur_preview_api.so', missing and no known rule to make it
这种错误一般是缺失了某个平台的库导致的,首先查看具体缺失的是哪个平台的so库,如果该平台的库不需要,可以在app下的build.gradle中声明不加载:
ndk {
// 声明只使用这两个版本的库,否则默认的可是4个平台
abiFilters 'armeabi-v7a','arm64-v8a'
}
或者是检查下CMakeLists.txt中FFmpeg库的路径声明是否正确:

比如我这里声明的库路径就是app/libs/具体的平台。
参考链接:
2. 在Mac中编译Android平台的FFmpeg( arm和x86 )
FFmpeg: mac下手动编译android上使用的FFmpeg(支持x86、armeabi-v7a、arm64-v8a)的更多相关文章
- Mac 下反编译Android APK
准备工作:安装ApkTool.dex2jar.JD-GUI 安装ApkTool 1.下载ApkTool.大家可以从 https://ibotpeaches.github.io/Apktool/inst ...
- mac下反编译android apk
所需要的工具 http://pan.baidu.com/disk/home#path=%252Fandroid%252Fdecompile%252Fapktool-all apktool用于将资源文件 ...
- Mac下重新编译Linux内核
Mac下重新编译Linux内核 操作系统实验,要求添加系统调用并重新编译内核,这里记录一下编译内核的过程 0.下载VirtualBox 博主一直用parallel desk,但因为驱动等问题,在PD上 ...
- Ubuntu+NDK编译openssl(为了Android上使用libcurl且支持HTTPS协议)
为了Android上使用libcurl且支持HTTPS协议,需要依赖openssl,因此先来了解一下如何编译OpenSSL1.编译ARM下的共享库(默认的)我使用的是guardianproject的o ...
- mac下识别国产android手机
mac下识别国产android手机困扰了我很久,这几天总算在google帮助下找到了解决方法. 在~/.android/下找到adb_usb.ini,如果不存在则创建.通过“系统信息”查看到插入的an ...
- 【FAQ】Ubuntu环境下ant编译android代码问题
在Ubuntu14.04环境下,编译android程序时候,运行ant debug的时候出现如下异常:
- mac下phpize编译提示Cannot find autoconf解决办法
mac下phpize编译如下报错: /usr/bin/phpizeConfiguring for:PHP Api Version: 20121113Zend Module Api No: 201212 ...
- Charles在Mac、iPhone、Android上抓http/https协议的包
1.我使用的版本是4.0.2,下载和破解网上方法很多,不做说明 2.Charles在Mac上抓http/https协议的包 2.1先把这三个都给装上,装完后会自动跳转到钥匙串中 2.2如果装完后提示证 ...
- Linux下手动编译shogun
手动编译shogun,如果按照直接按照官网上的步骤进行,会踩非常多的坑,下面分享一下在下的编译过程,希望能为阁下提供些许借鉴. 1. git clone https://github.com/shog ...
随机推荐
- 交互式计算引擎MOLAP篇
交互式计算引擎MOLAP篇 摘自:<大数据技术体系详解:原理.架构与实践> MOLAP是一种通过预计算cube方式加速查询的OLAP引擎,它的核心思想是“空间换时间”,典型代表包括Drui ...
- Apache的虚拟主机
一.虚拟主机的分类 基于IP的虚拟主机:一台服务器,多个ip,搭建多个网站 基于端口的虚拟主机:一台服务器,一个ip,利用不同端口,搭建多个网站 基于域名的虚拟主机:一台服务器,一个ip,多个域名,搭 ...
- spring常用的事务传播属性说明
事务Transaction,就是一组操作数据库的动作集合.事务是现代数据库理论中的核心概念之一.如果一组处理步骤或者全部发生或者一步也不执行,我们称该组处理步骤为一个事务.当所有的步骤像一个操作一样被 ...
- jquery复杂节点获取
jquery.find方法 1 $("div").find(".1").css({"color":"red"," ...
- 利用webhook实现发送通知到Slack
概要 最近办公交流应用 Slack在各团队里大行其道,非常火热. 今天我们就来说说怎么用他的incoming-webhook来做一些同步通知. 从kintone发送通知给Slack 我们先来看看这种i ...
- 手写Java的字符串简单匹配方法IndexOf()
简单的字符串模式匹配算法,可使用KMP进行优化 /** * @param s1 母串 * @param s2 子串 * @return */ public static int myIndexOf(S ...
- 神经网络MNIST数据集分类tensorboard
今天分享同样数据集的CNN处理方式,同时加上tensorboard,可以看到清晰的结构图,迭代1000次acc收敛到0.992 先放代码,注释比较详细,变量名字看单词就能知道啥意思 import te ...
- test20190827 NOIP2019 模拟赛
100+100+50=250.最后那道期望题需要用另外的方式统计. 精灵加护 ljss 被 M 个敌人打倒在地上啦!每个敌人有一个威力值 bi.但是他手中还拥有 N 把武器!每把武器有一个威力值 ai ...
- bugzilla权限说明
admin:Administrators权限 bz_canusewhineatothers:可定期向其它用户发送有关bug的邮件 bz_canusewhines: 用户在这个组,才能向其发送上 ...
- (java)Jsoup爬虫学习--获取网页所有的图片,链接和其他信息,并检查url和文本信息
Jsoup爬虫学习--获取网页所有的图片,链接和其他信息,并检查url和文本信息 此例将页面图片和url全部输出,重点不太明确,可根据自己的需要输出和截取: import org.jsoup.Jsou ...