ubuntu环境 ffmpeg 6.1.4
坑采完了,拿走不谢!
#!/usr/bin/env bash
set -e
# ==========================================
# 配置区域 (请根据实际情况修改)
# ==========================================
# NDK 安装路径 (请修改为你自己的路径)
export NDK_ROOT=/home/xbin/Android/Sdk/ndk/28.2.13676358
# 目标架构 (这里演示 arm64-v8a,也是目前最通用的)
ARCH=aarch64
CPU=armv8-a
API=21
ANDROID_ARCH=arm64-v8a
HOST_TAG=linux-x86_64 # Ubuntu 系统
# 编译生成目录
ROOT=$(pwd)/build
SRC=$ROOT/src
INSTALL=$ROOT/install
TOOLCHAIN=$NDK_ROOT/toolchains/llvm/prebuilt/$HOST_TAG
# 检查 NDK 是否存在
if [ ! -d "$NDK_ROOT" ]; then
echo "Error: NDK_ROOT not found at $NDK_ROOT"
exit 1
fi
# 设置编译器别名 (Clang)
export AR=$TOOLCHAIN/bin/llvm-ar
export CC=$TOOLCHAIN/bin/aarch64-linux-android${API}-clang
export CXX=$TOOLCHAIN/bin/aarch64-linux-android${API}-clang++
export AS=$CC
export LD=$TOOLCHAIN/bin/ld
export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
export STRIP=$TOOLCHAIN/bin/llvm-strip
# 放入 Path 方便调用
export PATH=$TOOLCHAIN/bin:$PATH
JOBS=$(nproc)
mkdir -p $SRC $INSTALL
echo "使用 NDK: $NDK_ROOT"
echo "编译架构: $ANDROID_ARCH (API $API)"
################################
# 1. build x264 (Static)
################################
echo "==== build x264 ===="
cd $SRC
if [ ! -d x264 ]; then
git clone https://code.videolan.org/videolan/x264.git -b stable
fi
cd x264
make clean || true
# x264 交叉编译配置
./configure \
--prefix=$INSTALL \
--enable-static \
--disable-shared \
--enable-pic \
--disable-cli \
--disable-asm \
--host=aarch64-linux-android \
--sysroot=$TOOLCHAIN/sysroot \
--cross-prefix="$TOOLCHAIN/bin/llvm-" \
--extra-cflags="-fPIC"
make -j$JOBS
make install
################################
# 2. build x265 (Static)
################################
echo "==== build x265 ===="
cd $SRC
if [ ! -d x265 ]; then
git clone https://bitbucket.org/multicoreware/x265_git.git x265
fi
cd x265/build/linux
make clean || true
# x265 使用 CMake,利用 NDK 自带的 toolchain 文件最方便
cmake ../../source \
-DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake \
-DANDROID_PLATFORM=android-$API \
-DANDROID_ABI=$ANDROID_ARCH \
-DENABLE_SHARED=OFF \
-DENABLE_ASSEMBLY=OFF \
-DENABLE_CLI=OFF \
-DENABLE_PIC=ON \
-DCMAKE_INSTALL_PREFIX=$INSTALL
make -j$JOBS
make install
sed -i 's/-l-l:libunwind.a//g' $INSTALL/lib/pkgconfig/x265.pc
################################
# 3. build ffmpeg with x264+x265
################################
echo "==== build ffmpeg ===="
cd $SRC
if [ ! -d ffmpeg ]; then
git clone https://git.ffmpeg.org/ffmpeg.git
# 建议 checkout 一个稳定版本,例如 6.0
cd ffmpeg && git checkout release/6.1.4 && cd ..
fi
cd ffmpeg
make distclean || true
# 关键:x265是C++库,FFmpeg是C,链接时需要 explicitly 链接 C++ 运行时
# 并且要告诉 pkg-config 只看我们编译的目录
export PKG_CONFIG_PATH=$INSTALL/lib/pkgconfig
export PKG_CONFIG_LIBDIR=$PKG_CONFIG_PATH
./configure \
--prefix=$INSTALL/out \
--target-os=android \
--arch=$ARCH \
--cpu=$CPU \
--cc=$CC \
--cxx=$CXX \
--ar=$AR \
--ranlib=$RANLIB \
--strip=$STRIP \
--sysroot=$TOOLCHAIN/sysroot \
--enable-pic \
--enable-gpl \
--enable-small \
--enable-neon \
--enable-jni \
--enable-cross-compile \
--enable-pthreads \
--enable-libx264 \
--enable-libx265 \
--enable-mediacodec \
--enable-encoder=h264_mediacodec \
--enable-encoder=hevc_mediacodec \
--enable-decoder=h264_mediacodec \
--enable-decoder=hevc_mediacodec \
--enable-decoder=aac_mediacodec \
--enable-static \
--disable-shared \
--disable-encoders \
--disable-doc \
--disable-htmlpages \
--disable-manpages \
--disable-podpages \
--disable-txtpages \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-symver \
--disable-asm \
--disable-x86asm \
--disable-avdevice \
--disable-postproc \
--disable-cuvid \
--disable-nvenc \
--disable-vaapi \
--disable-vdpau \
--disable-videotoolbox \
--disable-audiotoolbox \
--disable-appkit \
--disable-avfoundation \
--extra-cflags="-I$INSTALL/include -fPIC -DPIC" \
--extra-cxxflags="-I$INSTALL/include -fPIC -DPIC" \
--extra-ldflags="-L$INSTALL/lib" \
--extra-libs="-lc++_shared" \
--pkg-config="pkg-config --static"
make -j$JOBS
make install
echo "================================="
echo " Android Build Success!"
echo " Output: $INSTALL/out"
echo "================================="
################################
# 4. 合并所有 .a 文件为单个 .so
################################
echo "==== 正在合并生成 libffmpeg.so ===="
# 定义输出文件路径
OUTPUT=$INSTALL/out/lib
# 这里的顺序有一定影响,通常 ffmpeg 基础库在后,插件库在前
# 使用 -Wl,--whole-archive 确保所有符号都被强制包含
$CC -shared -fPIC -Wl,-soname,libffmpeg.so \
-Wl,--allow-multiple-definition \
-Wl,--whole-archive \
$INSTALL/lib/libx264.a \
$INSTALL/lib/libx265.a \
$OUTPUT/libavformat.a \
$OUTPUT/libavcodec.a \
$OUTPUT/libavfilter.a \
$OUTPUT/libswresample.a \
$OUTPUT/libswscale.a \
$OUTPUT/libavutil.a \
-Wl,--no-whole-archive \
-lc++_static \
-lm -lz -ldl -llog -landroid \
-lmediandk \
-o $OUTPUT/libffmpeg.so
# 去除符号表减小体积
$STRIP --strip-unneeded $OUTPUT/libffmpeg.so
echo "================================="
echo " Android Build Success!"
echo " 合并后的库文件: $OUTPUT/libffmpeg.so"
echo "================================="
集成到Android项目中,会报错:
java.lang.UnsatisfiedLinkError: dlopen failed: library "libc++_shared.so" not found:
externalNativeBuild {
cmake {
cppFlags '-std=c++11'
arguments "-DANDROID_STL=c++_shared" // 增加这行就能解决
}
}
检测是否集成成功,将编译之后的so集成到项目中,JNI中执行如下代码即可检测:
const char *config = avcodec_configuration();
__android_log_print(ANDROID_LOG_INFO, "FFmpegConfig", "%s", config);
// 或者检查特定的编码器是否存在
const AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_HEVC);
if (codec) {
__android_log_print(ANDROID_LOG_INFO, "FFmpegConfig", "libx265 encoder found!");
} else {
__android_log_print(ANDROID_LOG_ERROR, "FFmpegConfig", "libx265 encoder NOT found!");
}
// codec = avcodec_find_decoder(AV_CODEC_ID_HEVC);
codec = avcodec_find_decoder_by_name("libx265");
if (codec) {
__android_log_print(ANDROID_LOG_ERROR, "FFmpegConfig", "✓ H265解码器可用\n");
}