NDK编译ffmpeg

由于android中的音视频的解码有限,就学习了android NDK基础,决定使用ffmpeg来完成一些简单的来解码,但是ffmpeg没有android版本的 .so文件,就必须自行来编译ffmpeg了,网上有些博客,写得还是很不错的,为了自己以后方便查找,特此记录

ffmpeg在Linux操作系统下编译要方便的多(对linux不是很熟悉,就选择了windows来编译),在window下需要我们做一些额外的工作,我们使用MinGw工具来编译
我是基于以下环境编译ffmpeg的

    1. 编译ffmpeg基于window7环境
    2. ffmpeg版本为3.3
    3. 编译使用MinGW来编译 

1.ffmpeg最新下载链接
2.安装MinGw的exe文件和源码开源在SourceForge,MinGW下载链接
3.安装完成后,下载msys-base和mingw-32-gcc-ada两个库文件即可。这里我们主要是使用gcc来完成编译工作
4.将MinGW的安装目录下的bin目录配置到系统Path环境变量
5.因为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形式
6.在ffmpeg目录下创建一个build_android.sh文件,拷贝如下代码

#!/bin/bash
export TMPDIR=D:/tmpdir
NDK=D:/Android/android-sdk-windows/ndk-bundle
SYSROOT=$NDK/platforms/android-24/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64
CPU=arm
PREFIX=D:/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

上面需要我们注意的地方有以下几点:(上面所有的路径都用反斜杠,以免报错)
(1)TMPDIR :该字段指向一个文件夹目录,该文件夹路径可任意指定。作用是在编译ffmpeg期间,会生成一些临时文件用于存放在该目录,编译完成后,临时文件会自动清除。
(2)NDK:即你本地电脑NDK目录
(3)SYSROOT:根据你目前的NDK中platforms文件夹下的版本来设置。
(4)PREFIX:ffmpeg编译完成的so文件存放路径,可随意指定。
其它保持不变即可。
7.执行gcc命令编译
打开MinGW目录下的msys文件夹,找到msys.bat,打开:
这里写图片描述
cd切换到ffmpeg根目录,执行./build_android.sh开始编译,这时等待它编译完成。经过一段时间后,当ffmpeg编译完成,打开第6步中我们配置的PREFIX所指向的目录。可以发现多了两个文件夹:
这里写图片描述

其中,include就是编译出来的头文件,lib中就是so文件了:

这里写图片描述
这里写图片描述
看到有这些文件,说明ffmpeg编译成功了

<think>好的,用户之前询问了如何使用NDK编译Hello World,现在他们问的是如何用NDK编译FFmpeg。我需要先理解用户的需求。他们可能是在开发一个需要处理音视频的Android应用,想集成FFmpeg库。用户可能已经掌握了基础的NDK使用,现在想进阶到更复杂的库编译。 首先,用户可能对交叉编译不太熟悉,尤其是针对Android不同ABI的配置。FFmpeg本身是用C编写的,依赖较多,配置选项复杂,所以用户可能需要详细的步骤指导,包括环境准备、配置脚本的编写、编译命令以及集成到Android项目中的方法。 我需要检查之前的回答结构,之前关于Hello World的指南分步骤详细,用户可能希望类似的清晰结构。所以这次回答也应该分步骤,涵盖环境准备、下载源码、配置编译脚本、编译命令、常见问题解决等部分。 用户可能遇到的问题包括:如何正确配置FFmpeg的configure选项,如何处理不同的ABI架构,如何解决依赖库的问题,以及编译后的库如何集成到Android项目中。此外,可能还需要提到版本兼容性,比如NDK版本与FFmpeg版本的匹配问题。 需要提醒用户注意NDK的路径设置,以及选择正确的目标API版本。还可能要提到禁用某些不必要的模块来减少库的大小,比如禁用文档生成、不需要的编解码器等。此外,静态库和动态库的选择也可能影响最终应用的大小和性能。 另外,用户可能想知道如何验证编译后的库是否可用,比如在JNI中调用FFmpeg的函数,或者处理常见的错误如符号找不到、ABI不兼容等。可能还需要提供一些优化建议,比如剥离调试符号以减小库的体积。 最后,用户可能有进阶需求,比如启用特定的编解码器或硬件加速,这时候需要指导他们如何修改configure选项。同时,如果用户使用CMake而不是ndk-build,可能需要不同的集成方式,但考虑到复杂性,可能先重点介绍ndk-build的方法,再提及CMake的可能性。</think>以下是使用 Android NDK 编译 FFmpeg 的完整指南,涵盖从环境配置到 Android 项目集成的全流程: --- ### **1. 环境准备** #### **1.1 安装必要组件** 1. **NDK 版本选择** - 推荐 NDK r21+ (旧版本需自行适配) - 验证安装: ```bash echo $ANDROID_NDK_HOME # 确认环境变量已配置 ``` 2. **FFmpeg 源码下载** ```bash git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg cd ffmpeg && git checkout release/6.0 # 选择稳定分支 ``` --- ### **2. 配置交叉编译工具链** #### **2.1 确定目标ABI架构** | ABI类型 | 工具链目录 | 三元组 (Triplet) | |----------------|-----------------------------|-------------------------| | arm64-v8a | toolchains/llvm/prebuilt/...| aarch64-linux-android | | armeabi-v7a | toolchains/llvm/prebuilt/...| armv7a-linux-androideabi| | x86_64 | toolchains/llvm/prebuilt/...| x86_64-linux-android | #### **2.2 编写编译脚本** 创建 `build_ffmpeg.sh`: ```bash #!/bin/bash API=24 ARCH=arm64 TARGET=$ARCH-linux-android TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64 SYSROOT=$TOOLCHAIN/sysroot OUTPUT=android/$ARCH ./configure \ --prefix=$OUTPUT \ --enable-shared \ # 生成动态库 --disable-static \ # 禁用静态库 --disable-doc \ # 禁用文档生成 --disable-programs \ # 不生成可执行文件 --target-os=android \ # 指定目标系统 --arch=$ARCH \ # 指定CPU架构 --cc=$TOOLCHAIN/bin/$TARGET$API-clang \ # C编译器 --cxx=$TOOLCHAIN/bin/$TARGET$API-clang++ \ # C++编译器 --enable-cross-compile \ # 启用交叉编译 --sysroot=$SYSROOT \ # 系统根目录 --extra-cflags="-O3 -fPIC" # 优化与位置无关代码 make -j$(nproc) && make install ``` --- ### **3. 关键配置解析** #### **3.1 必须启用的选项** ```bash --enable-shared # 生成 .so 动态库 --disable-avdevice # 通常Android不需要设备输入输出 --disable-swresample # 按需启用 --disable-postproc # 按需启用 ``` #### **3.2 按需开启编解码器** ```bash --enable-decoder=h264 \ # 启用H.264解码 --enable-decoder=mp3 \ # 启用MP3解码 --enable-parser=h264 \ # 启用H.264解析器 --enable-demuxer=mov \ # 支持MOV格式 --enable-muxer=mp4 # 支持MP4封装 ``` --- ### **4. 多ABI编译** #### **4.1 批量编译脚本** 创建 `build_all_abi.sh`: ```bash #!/bin/bash ABIS=("arm64-v8a" "armeabi-v7a" "x86_64") for ABI in ${ABIS[@]}; do case $ABI in arm64-v8a) ARCH=arm64 TARGET=aarch64-linux-android ;; armeabi-v7a) ARCH=arm TARGET=armv7a-linux-androideabi ;; x86_64) ARCH=x86_64 TARGET=x86_64-linux-android ;; esac ./build_ffmpeg.sh $ARCH $TARGET done ``` --- ### **5. 集成到Android项目** #### **5.1 目录结构** ``` app/ ├── src/main/ │ ├── jniLibs/ # 存放编译好的.so文件 │ │ ├── arm64-v8a/ │ │ ├── armeabi-v7a/ │ │ └── x86_64/ │ └── cpp/ │ └── ffmpeg_jni.c # JNI接口文件 ``` #### **5.2 CMake配置** 修改 `CMakeLists.txt`: ```cmake add_library(ffmpeg_jni SHARED ffmpeg_jni.c) # 链接FFmpeg库 target_link_libraries(ffmpeg_jni android log ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavcodec.so ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavformat.so ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavutil.so ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libswscale.so ) ``` --- ### **6. 常见问题解决** #### **6.1 符号找不到错误** ```log undefined reference to 'avcodec_register_all' ``` **解决方法**: 1. 检查 `--enable-shared` 是否配置 2. 确认链接顺序:`libavcodec → libavutil → libswscale` #### **6.2 API版本冲突** 在 `build.gradle` 中指定最低API: ```gradle android { defaultConfig { minSdkVersion 24 # 需与编译时的API版本一致 } } ``` #### **6.3 体积优化** 1. 剥离调试符号: ```bash $TOOLCHAIN/bin/llvm-strip --strip-unneeded libav*.so ``` 2. 在配置时禁用非必要模块: ```bash --disable-avfilter \ # 按需禁用滤镜 --disable-network \ # 禁用网络支持 --disable-bzlib \ # 禁用压缩库 --disable-zlib ``` --- ### **7. 验证编译结果** #### **7.1 查看库信息** ```bash file android/arm64/libavcodec.so # 应显示 ELF 64-bit LSB shared object, ARM aarch64 ``` #### **7.2 简单JNI调用测试** 在 `ffmpeg_jni.c` 中添加: ```c #include <libavcodec/avcodec.h> JNIEXPORT jstring JNICALL Java_com_example_FFmpegTest_getVersion(JNIEnv *env, jobject thiz) { return (*env)->NewStringUTF(env, av_version_info()); } ``` --- ### **8. 进阶配置** #### **8.1 启用硬件加速** ```bash --enable-mediacodec \ # Android MediaCodec 支持 --enable-jni \ # JNI硬件交互 --enable-opensles # OpenSL ES音频支持 ``` #### **8.2 定制编解码器** 通过 `--enable-encoder=...` 和 `--enable-decoder=...` 精确控制支持的编码格式,例如: ```bash --enable-libx264 \ # 集成x264编码 --enable-gpl \ # 启用GPL协议代码 --enable-libfdk-aac # 集成高质量AAC编码 ``` --- 如果需要具体某个架构的完整编译参数示例,或遇到特定编解码器集成问题,请提供更多细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值