系统环境:ubuntu18.04
NDK版本: R19C
X264版本:x264-snapshot-20181217-2245
FFMPEG版本: 4.2.2
一、文件下载
X264库下载地址: http://www.videolan.org/developers/x264.html
NDK下载地址: https://developer.android.google.cn/ndk/downloads/index.html
注意,因为google在 NDK R19C中把GCC删除了。支持gcc版本的最高的ndk是 NDK R17C,后面的版本没有GCC编译器了,只有clang编译器,本文就是使用clang编译编译配置X264。
X264和FFMPEG编译好的库已经上传CSDN,如果不想编译直接使用可以去下载。
二、编译X264生成静态库
X264配置的情况可以在当前目录下的config.log文件中看到详细消息,包括出错的问题。
由于x264只是支持gcc的配置,如果想使用R17C版本的NDK编译,在x264目录下写一个脚本build_android.sh:
#!/bin/sh
ANDROID_NDK="/home/wbyq/work_pc/AndroidPath/android-ndk-r17c"
SDK_VERSION=27
ARCH=arm64
#ARCH=arm
if [ "$ARCH" = "arm64" ]
then
PLATFORM_PREFIX="aarch64-linux-android-"
HOST="aarch64"
PLATFORM_VERSION=4.9
else
PLATFORM_PREFIX="arm-linux-androideabi-"
HOST="arm"
PLATFORM_VERSION=4.9
fi
PREFIX=$(pwd)/android/${ARCH}
SYSROOT=$ANDROID_NDK/platforms/android-${SDK_VERSION}/arch-${ARCH}
TOOLCHAIN=$ANDROID_NDK/toolchains/${PLATFORM_PREFIX}${PLATFORM_VERSION}/prebuilt/linux-x86_64
CROSS_PREFIX=$TOOLCHAIN/bin/${PLATFORM_PREFIX}
echo "PREFIX=$PREFIX"
echo "SYSROOT=$SYSROOT"
echo "TOOLCHAIN=$TOOLCHAIN"
echo "CROSS_PREFIX=$CROSS_PREFIX"
./configure --prefix=$PREFIX --cross-prefix=$CROSS_PREFIX --sysroot=$SYSROOT --enable-static --enable-pic --disable-asm --host=arm-linux
这个脚本的目的是生成Makefile文件和config.mak文件,如果只是想使用R17C版本的NDK编译的话,生成Makefile之后就可以直接make && make install。
如果想使用R19C版本或者以上的NDK版本编译X264,那么就需要手动修改生成的config.mak文件。
config.mak文件修改的效果示例(只是支持静态库):
注意: 其中ndk相关的路径需要根据自己电脑上的NDK路径修改替换,这里的编译采用的是64位的。
SRCPATH=.
prefix=/home/wbyq/work/rk3399/x264-master/android/arm64
exec_prefix=${prefix}
bindir=${exec_prefix}/bin
libdir=${exec_prefix}/lib
includedir=${prefix}/include
SYS_ARCH=ARM
SYS=LINUX
CC=/home/wbyq/work_pc/AndroidPath/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang
CFLAGS= -D__ANDROID_API__=21 -target aarch64-none-linux-android -gcc-toolchain /home/wbyq/work_pc/AndroidPath/android-ndk-r19c/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64 -fno-limit-debug-info -DANDROID_HAS_WSTRING --sysroot=/home/wbyq/work_pc/AndroidPath/android-ndk-r19c/sysroot -isystem /home/wbyq/work_pc/AndroidPath/android-ndk-r19c/sysroot/usr/include/aarch64-linux-android -isystem /home/wbyq/work_pc/AndroidPath/android-ndk-r19c/sources/cxx-stl/llvm-libc++/include -isystem /home/wbyq/work_pc/AndroidPath/android-ndk-r19c/sources/android/support/include -isystem /home/wbyq/work_pc/AndroidPath/android-ndk-r19c/sources/cxx-stl/llvm-libc++abi/include -fstack-protector-strong -DANDROID -O2 -Wall -W -D_REENTRANT -fPIC $(DEFINES) -ffast-math -I. -I$(SRCPATH) -fomit-frame-pointer -fno-tree-vectorize -fvisibility=hidden
CFLAGSSO=
CFLAGSCLI=
COMPILER=GNU
COMPILER_STYLE=GNU
DEPMM=-MM -g0
DEPMT=-MT
LD=/home/wbyq/work_pc/AndroidPath/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang -o
LDFLAGS= --sysroot=/home/wbyq/work_pc/AndroidPath/android-ndk-r19c/platforms/android-21/arch-arm64 -lm -ldl
LDFLAGSCLI=-ldl
LIBX264=libx264.a
CLI_LIBX264=$(LIBX264)
AR=/home/wbyq/work_pc/AndroidPath/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar rc
RANLIB=/home/wbyq/work_pc/AndroidPath/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-ranlib
STRIP=/home/wbyq/work_pc/AndroidPath/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-strip
INSTALL=install
AS=
ASFLAGS= -I. -I$(SRCPATH) -DSTACK_ALIGNMENT=4 -DPIC
RC=
RCFLAGS=
EXE=
HAVE_GETOPT_LONG=1
DEVNULL=/dev/null
PROF_GEN_CC=-fprofile-generate
PROF_GEN_LD=-fprofile-generate
PROF_USE_CC=-fprofile-use
PROF_USE_LD=-fprofile-use
HAVE_OPENCL=yes
CC_O=-o $@
default: cli
install: install-cli
default: lib-static
install: install-lib-static
修改之后再编译安装,make && make install。
三、 配置编译ffmpeg支持x264编码库
先参照前面章节编译X264生成静态库,是静态库,不需要动态库。Ffmpeg只支持连接x264的静态库,动态库会报错找不到libx264。
Ffmpeg配置情况可以在ffbuild/config.log文件中查看到。
先下载ffmpeg源码之后在linux下解压。
(1). 第一步修改configure
进入源码根目录,用vim打开configure,找到
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,使能X264编码,并指定X264编码库的相关库文件头文件的路径:
FFMPEG配置示例:(ARM64-V8)
./configure --prefix=$PWD/android/arm64_v8 --toolchain=clang-usan --enable-cross-compile --target-os=android --arch=arm64 --cpu=armv8-a --sysroot=/home/wbyq/work_pc/AndroidPath/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/sysroot --cc=/home/wbyq/work_pc/AndroidPath/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang --cxx=/home/wbyq/work_pc/AndroidPath/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++ --strip=/home/wbyq/work_pc/AndroidPath/android-ndk-r19c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-strip --extra-cflags='-fPIE -pie -march=armv8-a -mfloat-abi=softfp -mfpu=vfp -marm' --extra-ldflags='-fPIE -pie' --enable-gpl --enable-ffmpeg --enable-libx264 --enable-shared --extra-cflags=-I/home/wbyq/work/rk3399/ffmpeg-4.2.2/x264/android/arm64/include --extra-ldflags=-L/home/wbyq/work/rk3399/ffmpeg-4.2.2/x264/android/arm64/lib
配置之后,make install
(注意: 如果每次改变配置重新编译,需要make clean 之后再make)
编译安装成功之后,在当前目录下会生成android/arm64_x264目录。
详细的文件如下:
wbyq@wbyq:~/work/rk3399/ffmpeg-4.2.2$ cd android/arm64_x264/
wbyq@wbyq:~/work/rk3399/ffmpeg-4.2.2/android/arm64_x264$ ls
bin include lib share
wbyq@wbyq:~/work/rk3399/ffmpeg-4.2.2/android/arm64_x264$ cd lib/
wbyq@wbyq:~/work/rk3399/ffmpeg-4.2.2/android/arm64_x264/lib$ ls
libavcodec.so libavfilter.so libavutil.so libswresample.so pkgconfig
libavdevice.so libavformat.so libpostproc.so libswscale.so
wbyq@wbyq:~/work/rk3399/ffmpeg-4.2.2/android/arm64_x264/lib$ file libavdevice.so
libavdevice.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, stripped
wbyq@wbyq:~/work/rk3399/ffmpeg-4.2.2/android/arm64_x264/lib$ cd ..
wbyq@wbyq:~/work/rk3399/ffmpeg-4.2.2/android/arm64_x264$ ls
bin include lib share
wbyq@wbyq:~/work/rk3399/ffmpeg-4.2.2/android/arm64_x264$ tree
.
├── bin
│ └── ffmpeg
├── include
│ ├── libavcodec
│ │ ├── ac3_parser.h
│ │ ├── adts_parser.h
│ │ ├── avcodec.h
│ │ ├── avdct.h
│ │ ├── avfft.h
│ │ ├── d3d11va.h
│ │ ├── dirac.h
│ │ ├── dv_profile.h
│ │ ├── dxva2.h
│ │ ├── jni.h
│ │ ├── mediacodec.h
│ │ ├── qsv.h
│ │ ├── vaapi.h
│ │ ├── vdpau.h
│ │ ├── version.h
│ │ ├── videotoolbox.h
│ │ ├── vorbis_parser.h
│ │ └── xvmc.h
│ ├── libavdevice
│ │ ├── avdevice.h
│ │ └── version.h
│ ├── libavfilter
│ │ ├── avfilter.h
│ │ ├── buffersink.h
│ │ ├── buffersrc.h
│ │ └── version.h
│ ├── libavformat
│ │ ├── avformat.h
│ │ ├── avio.h
│ │ └── version.h
│ ├── libavutil
│ │ ├── adler32.h
│ │ ├── aes_ctr.h
│ │ ├── aes.h
│ │ ├── attributes.h
│ │ ├── audio_fifo.h
│ │ ├── avassert.h
│ │ ├── avconfig.h
│ │ ├── avstring.h
│ │ ├── avutil.h
│ │ ├── base64.h
│ │ ├── blowfish.h
│ │ ├── bprint.h
│ │ ├── bswap.h
│ │ ├── buffer.h
│ │ ├── camellia.h
│ │ ├── cast5.h
│ │ ├── channel_layout.h
│ │ ├── common.h
│ │ ├── cpu.h
│ │ ├── crc.h
│ │ ├── des.h
│ │ ├── dict.h
│ │ ├── display.h
│ │ ├── downmix_info.h
│ │ ├── encryption_info.h
│ │ ├── error.h
│ │ ├── eval.h
│ │ ├── ffversion.h
│ │ ├── fifo.h
│ │ ├── file.h
│ │ ├── frame.h
│ │ ├── hash.h
│ │ ├── hdr_dynamic_metadata.h
│ │ ├── hmac.h
│ │ ├── hwcontext_cuda.h
│ │ ├── hwcontext_d3d11va.h
│ │ ├── hwcontext_drm.h
│ │ ├── hwcontext_dxva2.h
│ │ ├── hwcontext.h
│ │ ├── hwcontext_mediacodec.h
│ │ ├── hwcontext_qsv.h
│ │ ├── hwcontext_vaapi.h
│ │ ├── hwcontext_vdpau.h
│ │ ├── hwcontext_videotoolbox.h
│ │ ├── imgutils.h
│ │ ├── intfloat.h
│ │ ├── intreadwrite.h
│ │ ├── lfg.h
│ │ ├── log.h
│ │ ├── lzo.h
│ │ ├── macros.h
│ │ ├── mastering_display_metadata.h
│ │ ├── mathematics.h
│ │ ├── md5.h
│ │ ├── mem.h
│ │ ├── motion_vector.h
│ │ ├── murmur3.h
│ │ ├── opt.h
│ │ ├── parseutils.h
│ │ ├── pixdesc.h
│ │ ├── pixelutils.h
│ │ ├── pixfmt.h
│ │ ├── random_seed.h
│ │ ├── rational.h
│ │ ├── rc4.h
│ │ ├── replaygain.h
│ │ ├── ripemd.h
│ │ ├── samplefmt.h
│ │ ├── sha512.h
│ │ ├── sha.h
│ │ ├── spherical.h
│ │ ├── stereo3d.h
│ │ ├── tea.h
│ │ ├── threadmessage.h
│ │ ├── timecode.h
│ │ ├── time.h
│ │ ├── timestamp.h
│ │ ├── tree.h
│ │ ├── twofish.h
│ │ ├── tx.h
│ │ ├── version.h
│ │ └── xtea.h
│ ├── libpostproc
│ │ ├── postprocess.h
│ │ └── version.h
│ ├── libswresample
│ │ ├── swresample.h
│ │ └── version.h
│ └── libswscale
│ ├── swscale.h
│ └── version.h
├── lib
│ ├── libavcodec.so
│ ├── libavdevice.so
│ ├── libavfilter.so
│ ├── libavformat.so
│ ├── libavutil.so
│ ├── libpostproc.so
│ ├── libswresample.so
│ ├── libswscale.so
│ └── pkgconfig
│ ├── libavcodec.pc
│ ├── libavdevice.pc
│ ├── libavfilter.pc
│ ├── libavformat.pc
│ ├── libavutil.pc
│ ├── libpostproc.pc
│ ├── libswresample.pc
│ └── libswscale.pc
└── share
└── ffmpeg
├── examples
│ ├── avio_dir_cmd.c
│ ├── avio_reading.c
│ ├── decode_audio.c
│ ├── decode_video.c
│ ├── demuxing_decoding.c
│ ├── encode_audio.c
│ ├── encode_video.c
│ ├── extract_mvs.c
│ ├── filter_audio.c
│ ├── filtering_audio.c
│ ├── filtering_video.c
│ ├── http_multiclient.c
│ ├── hw_decode.c
│ ├── Makefile
│ ├── metadata.c
│ ├── muxing.c
│ ├── qsvdec.c
│ ├── README
│ ├── remuxing.c
│ ├── resampling_audio.c
│ ├── scaling_video.c
│ ├── transcode_aac.c
│ ├── transcoding.c
│ ├── vaapi_encode.c
│ └── vaapi_transcode.c
├── ffprobe.xsd
├── libvpx-1080p50_60.ffpreset
├── libvpx-1080p.ffpreset
├── libvpx-360p.ffpreset
├── libvpx-720p50_60.ffpreset
└── libvpx-720p.ffpreset
15 directories, 163 files
wbyq@wbyq:~/work/rk3399/ffmpeg-4.2.2/android/arm64_x264$
接下来就可以直接集成到AndroidAPP里调用。完成视频录制、转换、添加水印、推流等等。
下篇文章介绍,使用QT5.12调用编译的FFMPEG库部署到Android设备,完成摄像头视频采集、推流。
下面公众号里有全套QT、C、C++基础学习教程: