preface
2020/5/20
- Added hardware decoding compiler scripts
- Centos + NDK20b + FFmpeg4.2.2 + Android-21/16
2020/4/26
- Updated compiling 64-bit scripts
- Centos + NDK17C + FFmpeg4.2.2 + Android-21
The article officially entered the audio and video learning, before entering the audio and video learning we must first learn FFmpeg this library, this library is very powerful, powerful to what point? It can be said that no one does not know it as long as the audio and video, including some of the more famous players at home and abroad also used FFmpeg this library.
FFmpeg definition
FFmpeg is not only an audio and video codec tool, but also a set of audio and video codec development kit. As a codec development kit, it provides developers with rich audio and video processing call interfaces.
FFmpeg provides a variety of media formats to encapsulate and unencapsulate, including a variety of audio and video coding, a variety of protocol streaming media, a variety of color format conversion, a variety of sampling rate conversion, a variety of code rate conversion; FFmpeg framework provides a variety of rich plug-in modules, including encapsulation and decoding plug-in, encoding and decoding plug-in, etc.
FFmpeg history
The first version of FFmpeg was developed in 2000 by Fabrice Bellard, a brilliant French programmer; Then, in 2004, Fabrice Bellard found a replacement, who still maintains FFmpeg’s Michael Niedermayer. Michael Niedermayer made a big contribution to FFmpeg by adding the filter subsystem LibavFilter to the FFmpeg project, making FFmpeg’s multimedia processing more diverse and convenient. After FFmpeg released version 0.5, there was no release of a new version until FFmpeg adopted Git as a version control server, which was many years later. In March 2011, some submitters in the FFmpeg project were not satisfied with FFmpeg’s project management, so they created a new project named Libav. Although the project has not developed as fast as FFmpeg, the submission permissions are more open than FFmpeg. In August 2015, Michael Niedermayer voluntarily resigned as head of the FFmpeg project. Michael Niedermayter, who ported a lot of the code and functionality from Libav to FFmpeg, resigned in the hope that the two projects would eventually grow together, or better yet, merge. Today, FFmpeg is used for multimedia processing in most Linux distributions.
FFmpeg source code is freely available in the following ways:
- The official website
- Git.videolan.org/?p=ffmpeg.g…
- GitHub
The FFmpeg module is introduced
The basic components of FFmpeg framework include libavcodec, libavformat, libavfilter, libavDevice, libavutil and other modules.
Here is an overview of these modules.
-
libavcodec:
FFmpeg does not add libraries like libx264, FDK-aAC, Lame by default, but FFmpeg is like a platform. Other third-party CoDecs can be added as plug-ins to provide a unified interface for developers
-
libavformat:
File formats and Protocol libraries encapsulate the Protocol layer and Demuxer and Muxer layers, making protocols and formats transparent to developers
-
libavfilter:
Audio and video filter library, this module contains audio effects and video effects processing, in the process of using FFmpeg API encoding and decoding, you can use this module efficiently for audio and video data processing
-
libavdevice:
Input/output device libraries, such as ffplay, need to be enabled, and libsdl needs to be pre-compiled, which uses the libsDL library for sound and video playback
-
libavutil:
Core tool library, one of the most basic modules, other modules will rely on this library to do some basic audio and video processing operations
-
libswresample:
For audio resampling, digital audio can be used for channel number, data format, sampling rate and other basic information conversion
-
libswscale
This module is used for image format conversion, which can convert YUV data into RGB data
-
libpostproc
This module is used for post-processing. When we use filter, we need to open this module, and filter will use some basic functions of this module
Older FFMPEG also compiles the Avresamle module, which was also used for resampling the original audio presentation, but is deprecated and recommended to use libswresample instead
In addition, the library can also contain the H.264/MPEG-4 AVC video encoding X264 library, is the most commonly used lossy video encoder, support CBR, VBR mode, can directly change the bit rate setting in the process of coding, in the live scene is very suitable! Can do bit rate adaptive function.
Download FFmpeg
FFmpeg official website to download the source code
In Linux, command download:
/ / 1. The wget command to download https://ffmpeg.org/releases/ffmpeg-4.2.2.tar.bz2 / / 2. Yum -y install bzip2 //3. Unzip FFmpeg tar-jxvf ffmPEG-4.2.2.tar.bz2Copy the code
Compile FFmpeg
Compile environment
- Ffmpeg – 4.2.2
- Centos 7
- android-ndk-r17c-linux-x86_64.zip
Configure Script introduction
#! /bin/sh.
#Help set of options
Help options:
--help print this message
--quiet Suppress showing informative output
--list-decoders show all available decoders
--list-encoders show all available encoders
--list-hwaccels show all available hardware accelerators
--list-demuxers show all available demuxers
--list-muxers show all available muxers
--list-parsers show all available parsers
--list-protocols show all available protocols
--list-bsfs show all available bitstream filters
--list-indevs show all available input devices
--list-outdevs show all available output devices
--list-filters show all available filters
#Standard options
#--disableRepresents the closed state; --enableRepresents the open state
Standard options:
--logfile=FILE log tests and output to FILE [ffbuild/config.log]
--disable-logging do not log configure debug information
--fatal-warnings fail if any configure warning is generated
#We finally compiled the dynamic static library location, must be set
--prefix=PREFIX install in PREFIX [$prefix_default]
--bindir=DIR install binaries in DIR [PREFIX/bin]
--datadir=DIR install data files in DIR [PREFIX/share/ffmpeg]
--docdir=DIR install documentation in DIR [PREFIX/share/doc/ffmpeg]
--libdir=DIR install libs in DIR [PREFIX/lib]
--shlibdir=DIR install shared libs in DIR [LIBDIR]
--incdir=DIR install includes in DIR [PREFIX/include]
--mandir=DIR install man page in DIR [PREFIX/share/man]
--pkgconfigdir=DIR install pkg-config files in DIR [LIBDIR/pkgconfig]
--enable-rpath use rpath to allow installing libraries in paths
not part of the dynamic linker search path
use rpath when linking programs (USE WITH CARE)
--install-name-dir=DIR Darwin directory name for installed targets
Licensing options:
--enable-gpl allow use of GPL code, the resulting libs
and binaries will be under GPL [no]
--enable-version3 upgrade (L)GPL to version 3 [no]
--enable-nonfree allow use of nonfree code, the resulting libs
and binaries will be unredistributable [no]
Configuration options:
#Open the static library
--disable-static do not build static libraries [no]
#Closing the dynamic library
--enable-shared build shared libraries [no
#You can optimize the size of the library
--enable-small optimize for size instead of speed
--disable-runtime-cpudetect disable detecting CPU capabilities at runtime (smaller binary)
--enable-gray enable full grayscale support (slower color)
--disable-swscale-alpha disable alpha channel support in swscale
--disable-all disable building components, libraries and programs
--disable-autodetect disable automatically detected external libraries [no]
Program options:
#We don't need to use a program, we don't need to run an.exe program on Windows, we just need to use it in our code.
--disable-programs do not build command line programs
#Use the FFmpeg command
--disable-ffmpeg disable ffmpeg build
#player--disable-ffplay disable ffplay build --disable-ffprobe disable ffprobe build Documentation options: --disable-doc do not build documentation --disable-htmlpages do not build HTML documentation pages --disable-manpages do not build man documentation pages --disable-podpages do not build POD documentation pages --disable-txtpages do not build text documentation pages
#Module options
Component options:
#Can control our camera - (Android is not supported)
--disable-avdevice disable libavdevice build
#Audio Video Codec
--disable-avcodec disable libavcodec build
#Audio and video format generation and parsing related
--disable-avformat disable libavformat build
#Audio resampling (if you want to change mono to two-channel)
--disable-swresample disable libswresample build
#Related to video display (zoom in, zoom out)
--disable-swscale disable libswscale build
#Post processing, rarely used, can be turned off
--disable-postproc disable libpostproc build
#Watermarking, captioning, special effects
--disable-avfilter disable libavfilter build
--enable-avresample enable libavresample build (deprecated) [no]
--disable-pthreads disable pthreads [autodetect]
--disable-w32threads disable Win32 threads [autodetect]
--disable-os2threads disable OS/2 threads [autodetect]
--disable-network disable network support [no]
--disable-dct disable DCT code
--disable-dwt disable DWT code
--disable-error-resilience disable error resilience code
--disable-lsp disable LSP code
--disable-lzo disable LZO decoder code
--disable-mdct disable MDCT code
--disable-rdft disable RDFT code
--disable-fft disable FFT code
--disable-faan disable floating point AAN (I)DCT code
--disable-pixelutils disable pixel utils in libavutil
Individual component options:
--disable-everything disable all components listed below
--disable-encoder=NAME disable encoder NAME
--enable-encoder=NAME enable encoder NAME
#The code can be turned off--disable-encoders disable all encoders --disable-decoder=NAME disable decoder NAME --enable-decoder=NAME enable decoder NAME --disable-decoders disable all decoders --disable-hwaccel=NAME disable hwaccel NAME --enable-hwaccel=NAME enable hwaccel NAME --disable-hwaccels disable all hwaccels --disable-muxer=NAME disable muxer NAME --enable-muxer=NAME enable muxer NAME #Mixed package (audio and video equals one piece of audio and one piece of video combined together is.mp4, you can turn it off if you don't want to)--disable-muxers disable all muxers --disable-demuxer=NAME disable demuxer NAME --enable-demuxer=NAME enable demuxer NAME --disable-demuxers disable all demuxers --enable-parser=NAME enable parser NAME --disable-parser=NAME disable parser NAME --disable-parsers disable all parsers --enable-bsf=NAME enable bitstream filter NAME --disable-bsf=NAME disable bitstream filter NAME --disable-bsfs disable all bitstream filters --enable-protocol=NAME enable protocol NAME --disable-protocol=NAME disable protocol NAME --disable-protocols disable all protocols --enable-indev=NAME enable input device NAME --disable-indev=NAME disable input device NAME --disable-indevs disable input devices --enable-outdev=NAME enable output device NAME --disable-outdev=NAME disable output device NAME --disable-outdevs disable output devices --disable-devices disable all devices --enable-filter=NAME enable filter NAME --disable-filter=NAME disable filter NAME --disable-filters disable all filters ...Copy the code
Write 32/64-bit FFmpeg4.2.2 shell scripts
Ndk20b + FFmpeg4.2.2 clang compiling scripts
#! /bin/bashEcho "> > > > > > > > > compile hardware decoding version < < < < < < < <" echo "> > > > > > > > > note: the compiler environment currently only in NDK20b + ffmpeg4.2.2 tested < < < < < < < <" echo "> > > > > > > > > note: The build environment is currently only tested in NDK20b + FFmpeg4.2.2 <<<<<<<<"
#Your own NDK path.export NDK=/root/android/ndk/android-ndk-r20b TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64 function Build_android {echo "build $CPU"./configure \ --prefix=$prefix \ --enable-neon \ --enable-hwaccels \ --enable-gpl \ --enable-postproc \ --enable-shared \ --disable-debug \ --enable-small \ --enable-jni \ --enable-mediacodec \ --enable-decoder=h264_mediacodec \ --disable-static \ --disable-doc \ --enable-ffmpeg \ --disable-ffplay \ --disable-ffprobe \ --disable-avdevice \ --disable-doc \ --disable-symver \ --cross-prefix=$CROSS_PREFIX \ --target-os=android \ --arch=$ARCH \ --cpu=$CPU \ --cc=$CC \ --cxx=$CXX \ --enable-cross-compile \ --sysroot=$SYSROOT \ --extra-cflags=" -os-fpic $OPTIMIZE_CFLAGS" \ --extra-ldflags="$ADDI_LDFLAGS" make clean make make install echo $CPU" }
#armv8-a
ARCH=arm64
CPU=armv8-a
API=21
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=$CPU"
build_android
#armv7-a
ARCH=arm
CPU=armv7-a
API=16
CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang
CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
build_android
Copy the code
Ndk17c + FFmpeg4.2.2 GCC compiles scripts
#! /bin/bashEcho "> > > > > > > > > note: the compiler environment currently only in NDK17c + ffmpeg4.2.2 tested < < < < < < < <" echo "> > > > > > > > > note: The compiler environment currently only in NDK17c + ffmpeg4.2.2 tested < < < < < < < < "echo" > > > > > > > > > note: the compiler environment currently only in NDK17c + ffmpeg4.2.2 tested < < < < < < < <"
#The NDK_ROOT variable points to the NDK directory
NDK_ROOT=$NDK_HOME
#Specify the Android API version
ANDROID_API=21
#Start compiling by calling the passed parameter belowFunction build_ffmpeg() {echo "$PREFIX_CPU" echo" $PREFIX" echo "$TOOLCHAIN"./configure \ --prefix=$PREFIX \ --enable-small \ --disable-programs \ --disable-avdevice \ --disable-encoders \ --disable-muxers \ --disable-filters \ --enable-cross-compile \ --cross-prefix=$CROSS_PREFIX \ --disable-shared \ --enable-static \ --sysroot=$NDK_ROOT/platforms/android-$ANDROID_API/arch-$ARCH \ --extra-cflags="$CFLAGES" \ --arch=$ARCH \ --target-os=android
#After running the script above to generate the makefile, use make to execute the scriptMake clean make make install echo "$PREFIX_CPU "echo "$PREFIX_CPU" echo "$PREFIX_CPU "echo "$PREFIX_CPU"
#armeabi-v7aPREFIX =. / result/armeabi - v7a TOOLCHAIN = $NDK_ROOT toolchains/arm - Linux - androideabi - 4.9 / prebuilt/Linux - x86_64 ARCH = arm CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi- CFLAGES="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=$ANDROID_API -U_FILE_OFFSET_BITS -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security -O0 -fPIC" build_ffmpeg
#arm64-v8aPREFIX =. / result/arm64 - v8a TOOLCHAIN = $NDK_ROOT toolchains/aarch64 - Linux - android - 4.9 / prebuilt/Linux - x86_64 ARCH = arm64 CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android- CFLAGES="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/aarch64-linux-android -D__ANDROID_API__=$ANDROID_API -U_FILE_OFFSET_BITS -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security -O0 -fPIC" build_ffmpeg
#Jump directly to the compiled path
cd /result
Copy the code
Pits encountered by compiler:
-
arm-linux-androideabi-gcc is unable to create an executable file
Cause 1: FFmpeg 4.2.2 uses CLang for compilation by default
Solution:
//1. Configure vim //2. GCC if test "$target_OS "= android; then # cc_default="clang" cc_default="gcc" fi Copy the code
Reason 2:
Check whether the path is correct
-
nasm/yasm not found or too old. Use –disable-x86asm for a crippled build.
Analysis: YASM is an assembly compiler, ffMPEG uses assembly instructions, such as MMX and SSE, to improve efficiency.
Therefore, if yASM is not installed in the system, the preceding error is reported.
Resolve error: Install yASM compiler. Installation method is as follows: 1) to download: [yasm download link] wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz 2) extract: Decompress the downloaded package tar -zxvf yASM-1.3.0.tar. gz 3) Switch to the directory CD yasm-1.3.0 4) Run the configuration./configure 5) Compile: make 6) install: make installCopy the code
-
Lib64 libc so 6 version ‘GLIBC_2 18’ not found (required by lib…
Curl -o http://ftp.gnu.org/gnu/glibc/glibc-2.18.tar.gz tar ZXF glibc 2.18, tar. Gz glibc 2.18 CD/mkdir build CD build /.. /configure --prefix=/usr --disable-profile --enable-add-ons --with-headers=/usr/include --with-binutils=/usr/bin make Make install See if successful ll/lib64 / libc * then can continue to check the version of glibc support strings/lib64 / libc. So. 6 | grep glibc / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- / / don't have to refer to below, this is my the libc - when upgrade glibc 2.17, so to accidentally deleted, And basically paralyzed, LD_PRELOAD=/lib64/libc-2.17.so ln -s /lib64/libc-2.17.so /lib64/libc.so // Unset LD_LIBRARY_PATH can be removed by using the following command if an environment variable is accidentally definedCopy the code
-
The config.mak file was not generated
Solution: run./configure –disable-x86asm to generate config.mak
Click here for more pit errors
After the error is resolved, press Enter. If the following output is displayed, the compilation begins:
It will take about 10 minutes for the static library to compile.
-
If openSSL is added, report OpenSSL not found
- www.jianshu.com/p/5b3cf2054…
If you want to compile the dynamic library, just modify the parameters as follows:
#Enabling the Dynamic Library
--enable-shared \
#Closing static libraries
--disable-static \
Copy the code
Compression:
tar -zcvf ffmpeg_android.tar.gz android
Copy the code
FileZill is used to export the compiled static file from the server side to the local computer. After exporting, we will test whether the compiled.a file is wrong in AS.
Android integrates cross-compiled FFmpeg static libraries
-
Create an Android project for C/C++ project and import the compiled static library into the project as follows:
-
Write JNI code
#include <jni.h> // There is a pit, the error will be reported, must be mixed compilation //#include <libavutil/avutil.h> extern "C" { #include <libavutil/avutil.h> } /** * get the current version of ffmpeg * @return */ const char *getFFmpegVer(a) { return av_version_info(a); }extern "C" JNIEXPORT jstring JNICALL Java_com_devyk_ffmpeg_MainActivity_getFFmpegVersion(JNIEnv *env, jclass type) { return env->NewStringUTF(getFFmpegVer()); } Copy the code
-
Write the cmakelists.txt script
# specify the lowest version of Cmake cmake_minimum_required(VERSION 3.4.1) Find all CPP files file(GLOB allCpp *.cpp) Print the path of the current cmakeLists message(${CMAKE_SOURCE_DIR} \n CPU architecture: ${CMAKE_ANDROID_ARCH_ABI}") add_library( ffmpeg_lib SHARED ${allCpp}) find_library( log-lib log) # import FFmpeg header files include_directories(${CMAKE_SOURCE_DIR}/include) # import FFmpeg library file, set the internal way to import, specify the library directory is -l specify the specific library -l set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/${CMAKE_ANDROID_ARCH_ABI}") target_link_libraries( ffmpeg_lib # Specific library file, link to the main library # this will cause an error # avcodec avfilter avformat avutil swresample swscale # add libraries that have dependencies first avformat avcodec avfilter avutil swresample swscale ${log-lib}) Copy the code
-
App/build. Gradle configuration
apply plugin: 'com.android.application' android { compileSdkVersion 29 buildToolsVersion "29.0.2". defaultConfig { ... externalNativeBuild(){ cmake{ abiFilters"armeabi-v7a" // Specify to compile to armeabi-v7a}}}... externalNativeBuild(){ cmake{// specifies to build the C++ code script path 'src/main/cpp/CMakeLists.txt'}}}...Copy the code
-
MainActivity test code
public class MainActivity extends AppCompatActivity { static { System.loadLibrary("ffmpeg_lib"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView ffmpegVer = findViewById(R.id.ffmpeg_ver); ffmpegVer.setText("The current FFmpeg version is: + getFFmpegVersion()); } / * * *@returnReturns the current */ public native static String getFFmpegVersion(a); } Copy the code
Effect:
To here FFmpeg compilation and import AS use has been all introduced, dynamic library compilation and use need to start their own practice, the use of the way are similar.
conclusion
There are a lot of pitfalls when compiling FFmpeg, and basically every version of the shell is written differently, so if you don’t know much about shells, you are advised to review them first.
In this article, we use the knowledge of cross-compilation, Shell script, JNI and Cmake. If you don’t know the basics, you must learn the basics well first. You can also check out my previous series of basic articles.
Code in the article
Thank you
- FFmpeg
About me
- Email: [email protected]
- Personal blog: www.devyk.top
- Making: github.com/yangkun1992…
- Nuggets blog: juejin.cn/user/336855…
Scan the code to pay attention to my public number, let us from more into some!