最详细版Mac下编译FFmpeg,并移植到AndroidStud
2020-10-26 本文已影响0人
醉挽清风_666
最近项目空闲,开始调研学习Android音视频技术,又开始小白踩坑之路。。。搜了一圈,如果从零开始的话,ffmpeg应该是基础,必须要掌握的,网上的编译集成资料挺多的,然而,对着操作了一波,发现能用的挺少。。。磕磕碰碰的最后还是成功编译了,下面分享下集成经验~
集成准备
- Android NDK : [android-ndk-r17c](版本太高的编译报错)(https://developer.android.google.cn/ndk/downloads/older_releases)
- FFmpeg: FFmpge4.0.6
集成步骤
image.png- 修改FFmpeg目录下的configure文件(我用的Sublime Text)找到下面代码
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)'
- 在解压后的FFmpeg包的根目录下新建一个.sh文件,这里我创建一个称为build_android.sh的文件,文件编辑内容如下:
ADDI_CFLAGS="-marm"
API=19
PLATFORM=arm-linux-androideabi
CPU=armv7-a
NDK=/Users/admin/android-ndk-r17c # 修改成自己本地的ndk路径。
SYSROOT=$NDK/platforms/android-$API/arch-arm/
ISYSROOT=$NDK/sysroot
ASM=$ISYSROOT/usr/include/$PLATFORM
TOOLCHAIN=$NDK/toolchains/$PLATFORM-4.9/prebuilt/darwin-x86_64
OUTPUT=/Users/admin/FFmpeg/android #自己指定一个输出目录,用来放生成的文件的。
function build
{
./configure \
--prefix=$OUTPUT \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-avdevice \
--disable-doc \
--disable-symver \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=android \
--arch=arm \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-I$ASM -isysroot $ISYSROOT -Os -fpic -marm" \
--extra-ldflags="-marm" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
build
这里主要修改的两个点我注释所在了,大家改成自己的目录就行了,第一个地方是你的NDK包下载后解压的路径,第二个地方是生成编译后的文件目录路径。
-
编译build_android : 用终端cd 到当前目录 然后运行 sh build_android.sh(需要一段时间,会弹出多个授权框需要点同意),无报错即编译成功,如下图:
image.png -
编译后的文件如下图:
image.png -
新建Android项目,需要勾选支持C++:
image.png
新建后的项目结构目录如下:
image.png -
注意:把CMakeLists.txt文件移动到跟src同级
image.png -
把我们的so文件和包括文件放到lib目录下,还有build.gradle文件和CMakeLists.txt文件的代码一并放出,如下:
image.png -
修改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)
# 定义变量
set(distribution_DIR ../../../../libs)
# 添加库——自己编写的库
# 库名称:native-lib
# 库类型:SHARED,表示动态库,后缀为.so(如果是STATIC,则表示静态库,后缀为.a)
# 库源码文件:src/main/cpp/native-lib.cpp
add_library( native-lib
SHARED
src/main/cpp/native-lib.cpp )
# 添加库——外部引入的库
# 库名称:avcodec(不需要包含前缀lib)
# 库类型:SHARED,表示动态库,后缀为.so(如果是STATIC,则表示静态库,后缀为.a)
# IMPORTED表明是外部引入的库
add_library( avcodec
SHARED
IMPORTED)
# 设置目标属性
# 设置avcodec目标库的IMPORTED_LOCATION属性,用于说明引入库的位置
# 还可以设置其他属性,格式:PROPERTIES key value
set_target_properties( avcodec
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libavcodec.so)
find_library(
log-lib
log)
add_library( avfilter
SHARED
IMPORTED)
set_target_properties( avfilter
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libavfilter.so)
add_library( avformat
SHARED
IMPORTED)
set_target_properties( avformat
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libavformat.so)
add_library( avutil
SHARED
IMPORTED)
set_target_properties( avutil
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libavutil.so)
add_library( swresample
SHARED
IMPORTED)
set_target_properties( swresample
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libswresample.so)
add_library( swscale
SHARED
IMPORTED)
set_target_properties( swscale
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libswscale.so)
# 引入头文件
include_directories(libs/include)
# 告诉编译器生成native-lib库需要链接的库
# native-lib库需要依赖avcodec、avfilter等库
target_link_libraries( native-lib
avcodec
avfilter
avformat
avutil
swresample
swscale
-landroid
${log-lib} )
- 之后,修改build.gradle(:app)
apply plugin: 'com.android.application'
android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
applicationId "com.sweet.sugarbeetest"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cmake {
cppFlags "-frtti -fexceptions -Wno-deprecated-declarations"
}
ndk {
abiFilters "armeabi-v7a"
}
}
}
// sourceSets {
// main {
// jniLibs.srcDirs = ['libs']
// }
// }
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
version "3.10.2"
}
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
- 最后,可以验证下是否成功,修改native-lib.cpp文件,打印FFmpeg版本号:
#include <jni.h>
#include <string>
extern "C"{
#include <libavcodec/avcodec.h>>
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_sweet_sugarbeetest_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(av_version_info());
}
image.png