directory

  1. Configure and install the Android cross-build tool chain
  2. Hand-written FFmpeg compilation scripts (for ffmpeg3.x and FFmPEG4.x versions)
  3. References in androidStudio use ffmpeg
  4. Problems encountered
  5. data
  6. harvest

In this article, we will learn the practice of ffMPEG cross-compilation, which will involve ffMPEG version, NDK version, compile scripts, Gradler ABI processing and cmakelists. TXT for different NDK version of the compilation of footsteps. Tools were needed to solve this problem, and various Toolchains emerged, known as Toolchains. And NDK provides a set of tools for cross-compilation, different versions and configuration will be different, it is easy to have a variety of problems, is a constant process,), this paper records the process of learning practice, FFMPEG3.3.9 + NDK16, And FFMPEG4.3.1 or FFMPEG4.2.4 + NDK21 welcome to discuss.

Configure and install the Android cross-build tool chain

  1. Download NDK there are many versions of NDK 14,16,21, etc. Which version should we choose? Now generally use 16 or above, 16 compiler tool chain made a lot of changes. Different FFMPEG versions support different NDK versions. For example, ffmpeg3.x uses Android-NdK-R16b, while FFmPEG4. x uses 16.

  2. Configure the NDK environment Android-NdK-R21E

    Configure the environment variable vim ~/.bash_profile

    export NDK_PATH=/Users/xxx/tools/android-ndk-r21e export PATH=
    P A T H : {PATH}:
    NDK_PATH

    After the edit is saved, execute the following statement for it to take effect. ~/.bash_profile

  3. Install the Android cross-build toolchain /Users/ XXX /tools/ Android-ndk-r The 21e/build/tools path has make-standalone- toolchain-sh and make_standalone_toolchain-py, and we used the py version to configure the android cross-build toolchain

Use make_standalone_toolchain. Py

/Users/ XXX /tools/ Android-ndk-r21e/Android-toolChains/Android-19 mkdir Android-toolchains CD android-toolchains mkdir android-19 cd android-19 with open(src, 'rb') as fsrc: Sudo./ make_standalone_toolchain-py --arch arm -- API 19 --install-dir.. /.. /android-toolchains/android-19/arm-archCopy the code

This step is equivalent to making a copy of arch and API configuration information in the specified folder, so that ffMPEG compilation scripts can be used in the specified toolchain.

This step can be omitted because it is also possible to specify toolchain paths for different ABis and apis in subsequent ffMPEG compilation scripts.

Second, handwritten FFmpeg compilation script to compile (for FFmpeg3.x and FFMPEG4.x version)

Download ffmpeg

Different ffMPEG versions will need different NDK versions for compilation. If you downloaded the NDK configuration 16 in the previous step, download ffmPEG 3.x. If the NDK is 21, download 4.x FFMPEG.

The compilation process took me two or three days to figure out why and to avoid subsequent stumps, recording both ffmpeg3.x and FFmPEG4.x.

Let’s take a look at the general steps for compiling third-party libraries

  1. See READMME. Md
  2. A Makefile is required to compile the project. If you try to compile it using make, if not, you need to write a Makefile or cmake build
  3. If there is an error that needs to be resolved, it is likely that some configuration files in the Makefile were not generated. Run configure
  4. After the configuration files are generated, run make again, but the compiled files (ELF, SO, A) will only run on the current system.
  5. If you need to run to Android or ios you need to cross-compile
  6. You need to pass some script compilation parameters to Configure (key!).

Don’t copy it. Write it by hand, for three reasons:

  1. Figure out what each configuration means by hand
  2. Avoid compilation failures caused by different paths.
  3. Avoid tab-space conversions causing compilations to fail.

Next, we write the corresponding configuration and compilation scripts of ffmpeg3.x and ffmPEG4. x respectively.

2.1 Compiling scripts for FFmpeg3. x **

ffmpeg3.x_build.sh

Scripting for android platform #! ARCH=arm CPU=armv7-a #so = $(PWD)/android # ANDROID_TOOLCHAINS_PATH=$NDK_PATH/ Android-ToolChains/Android-19 / ARCH-arm CROSS_PREFIX=$ANDROID_TOOLCHAINS_PATH/bin/ arm-linux-androideabi-sysroot =$NDROID_TOOLCHAINS_PATH/ SYSROOT (./configure) # run /configure --help /configure --prefix =${prefix} \ # to build the dynamic library --disable-static \ --enable-shared \ # Tailor as needed --enable-samall --disable-programs --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-doc --disable-ffserver # Specify CPU architecture --arch=$arch -- CPU =$CPU # specify cross-compile tool directory --cross-prefix=${CROSS_PREFIX} \ # enable cross-compile -- enable-cross-compile \ --target-os= Linux --sysroot=$sysroot --extra-cflags=" -os-fpic "\ # make clean make make install echo "end build ffmpeg for $ARCH"Copy the code

For this reason, modify the configure script, replace the following four lines, and recompile and generate the corresponding SO.

Modify the file name generated so, andorID is convenient to use

In the configure file, search for build set to find the location

# 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)'Copy the code

2.2 Version for FFMPEG4.x

#! /bin/bash # here we use the path for each installation of the android cross-build toolchain in section 1.3. We use the manually specified toolchain, noting that the configuration varies depending on the API and ABI. Note that darwin-x86_64 is the name of the darwin-x86_64 folder on MAC and linux-x86_64 folder on Linux. API=21 TOOLCHAIN=$NDK_PATH/toolchains/llvm/prebuilt/darwin-x86_64/ #armv8-a ARCH=arm64 CPU=armv8-a # r21 version of the NDK/android - all the compiler in the NDK - r21e/toolchains/LLVM/prebuilt/Darwin - x86_64 / directory (clang) # configuration. C file compile tools CC=$TOOLCHAIN/bin/aarch64-linux-android$api-clang #. CPP CXX=$TOOLCHAIN/bin/aarch64-linux-android$api-clang ++ # header file environment with not/android - the NDK - r21e/sysroot, but the compiler / / android - the NDK - r21e/toolchains/LLVM/prebuilt/Darwin - x86_64 / sysroot SYSROOT = $NDK_PATH toolchains/LLVM/prebuilt/Darwin - x86_64 / SYSROOT # cross compile tools directory, corresponding relationship is as follows (we are using a armv8a here, According to your own need to configure) # armv8a - > arm64 - > aarch64 - Linux - android - # armv7a - > arm - > arm - Linux - androideabi - # x86 - > x86 - > I686-linux-android - # x86_64- > x86_64- > x86_64-linux-android- CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android- # $CPU OPTIMIZE_CFLAGS="-march=$CPU" Make write to a function # run./configure --help TAB function build_android {echo "CC is $CC" echo "CROSS_PREFIX is $CROSS_PREFIX"./configure \ # specify the output path --prefix=$prefix \ # Build dynamic library --enable-shared --disable-static \ # trim as needed --disable-ffmpeg --disable-ffplay \ --disable-ffprobe --disable-avdevice --disable-doc --disable-symver # Specifies the cross-compile tool directory --cross-prefix=$CROSS_PREFIX \ Android -- target-OS = Android --arch=$arch -- CPU =$CPU --cc=$cc -- CXX =$CXX --sysroot=$sysroot --extra-cflags=" -os-fpic $OPTIMIZE_CFLAGS" \ make clean make make install } build_androidCopy the code

The version of ffmpeg4. x is compiled correctly (but without the version number) and can be used directly with the generated so without modifying configure.

Three, AS to introduce the use of FFMPEG dynamic library

First, specify the corresponding ndk.dir in local.properties. The reason why the NDK version configured automatically by AS is not used is that it is more flexible to specify different versions through manual configuration.

Different Camkelist versions and gradle versions have different apis

For FFmPEg3.x and Android-NdK-R16B

Cmake_minimum_required (VERSION 3.4.1) project(" myffmPEGdemo ") MESSAGE(STATUS "PROJECT_SOURCE_DIR =" ${PROJECT_SOURCE_DIR}) MESSAGE(STATUS "CMAKE_SOURCE_DIR =" ${CMAKE_SOURCE_DIR}) include_directories(${PROJECT_SOURCE_DIR}/ffmpeg/include) link_directories(${CMAKE_SOURCE_DIR}/.. /jniLibs/armeabi-v7a) add_library( native-lib SHARED native-lib.cpp ) find_library( log-lib log) target_link_libraries( native-lib avcodec-57 avfilter-6 avformat-57 avutil-55 swresample-2 swscale-4 avdevice-57 postproc-54 ${log-lib})Copy the code

For FFMPEG4.x and Android-NK-R21E

Cmake_minimum_required (VERSION 3.4.2) project(" myffmPEG42demo ") # Set up include_directories(${PROJECT_SOURCE_DIR}/ffmpeg/include) message("CMAKE_CXX_FLAGS:" + ${CMAKE_CXX_FLAGS}) ${CMAKE_SOURCE_DIR :" + ${CMAKE_SOURCE_DIR}) message("CMAKE_ANDROID_ARCH_ABI :" + ${CMAKE_ANDROID_ARCH_ABI}) #link_directories(${CMAKE_SOURCE_DIR}/.. /jniLibs/armeabi) # import FFmpeg library file, set internal way to import, -l set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -l ${CMAKE_SOURCE_DIR}/.. /jniLibs/${CMAKE_ANDROID_ARCH_ABI}") add_library( # Sets the name of the library. native-lib SHARED native-lib.cpp) find_library( # Sets the name of the path variable. log-lib log) target_link_libraries( # Specifies the target library. native-lib avformat avcodec avfilter avutil swresample swscale ${log-lib})Copy the code

How to fit SO architectures Each architecture corresponds to an ABI that is backward compatible

Such as: There is no armeabi-v7a folder in the project. If you have two folders armeabi and armeabi-v7a, armeabi has a.soo and B.soo, and armeabi-v7a has only A.soo, Armeabi-v7a: armeabi-v7a: armeabi-v7A: armeabi-v7A: armeabi-v7A: armeabi-v7A: armeabi-v7A: armeabi-v7A: armeabi-v7A: armeabi-v7A: armeabi-v7A: armeabi-v7A: armeabi-v7A: armeabi-v7A So either you don’t want to add Armeabi-v7a, or the so library that’s in Armeabi must be in Armeabi-v7a as well.

4. Problems encountered

1. ffbuild/config.mak: No such file or directory

./ffmpeg_build3.sh 
Unknown option "--disable-ffserver".
See ./configure --help for available options.
Makefile:2: ffbuild/config.mak: No such file or directory
Makefile:40: /tools/Makefile: No such file or directory
Makefile:41: /ffbuild/common.mak: No such file or directory
Makefile:94: /libavutil/Makefile: No such file or directory
Makefile:94: /ffbuild/library.mak: No such file or directory
Makefile:96: /fftools/Makefile: No such file or directory
Makefile:97: /doc/Makefile: No such file or directory
Makefile:98: /doc/examples/Makefile: No such file or directory
Makefile:163: /tests/Makefile: No such file or directory
make: *** No rule to make target `/tests/Makefile'.  Stop.
Makefile:2: ffbuild/config.mak: No such file or directory
Makefile:40: /tools/Makefile: No such file or directory
Makefile:41: /ffbuild/common.mak: No such file or directory
Makefile:94: /libavutil/Makefile: No such file or directory
Makefile:94: /ffbuild/library.mak: No such file or directory
Makefile:96: /fftools/Makefile: No such file or directory
Makefile:97: /doc/Makefile: No such file or directory
Makefile:98: /doc/examples/Makefile: No such file or directory
Makefile:163: /tests/Makefile: No such file or directory
make: *** No rule to make target `/tests/Makefile'.  Stop.
Makefile:2: ffbuild/config.mak: No such file or directory
Makefile:40: /tools/Makefile: No such file or directory
Makefile:41: /ffbuild/common.mak: No such file or directory
Makefile:94: /libavutil/Makefile: No such file or directory
Makefile:94: /ffbuild/library.mak: No such file or directory
Makefile:96: /fftools/Makefile: No such file or directory
Makefile:97: /doc/Makefile: No such file or directory
Makefile:98: /doc/examples/Makefile: No such file or directory
Makefile:163: /tests/Makefile: No such file or directory
make: *** No rule to make target `/tests/Makefile'.  Stop.
Copy the code

The solution: Usually the configure configuration is wrong, or the newline has Spaces, or the TAB copy has been converted to Spaces. The solution is to figure out why ffMPEG builds scripts and write them by hand.

2. 4. X version compiles so, against the incompatible target

/ Users/yabin/tools/android - the NDK - r21e/toolchains/LLVM/prebuilt/Darwin - x86_64 / lib/GCC/arm - Linux - androideabi / 4.9 x /.. /.. /.. /.. /arm-linux-androideabi/bin/ld: error: /Users/yabin/work/tmp/myffmpegDemo/app/src/main/cpp/.. /jniLibs/armeabi-v7a/libswscale.so: incompatible targetCopy the code

Changing the NDK version from 21 to 16 is the same mistake

ndk.dir=/Users/yabin/tools/android-ndk-r21e

ndk.dir=/Users/yabin/tools/android-ndk-r16b

/ Users/yabin/tools/android - the NDK - r16b/toolchains/arm - Linux - androideabi - 4.9 / prebuilt Darwin - x86_64 / lib/GCC/arm - Linux - androi Deabi / 4.9 x /.. /.. /.. /.. /arm-linux-androideabi/bin/ld: error: /Users/yabin/work/tmp/myffmpegDemo/app/src/main/cpp/.. /jniLibs/armeabi-v7a/libswscale.so: incompatible targetCopy the code

Solution: changed to ffMPEG version 3.3.9. The root cause is that different NDK versions of Cmakelist introduce so in different ways.

3. Armeabi is no longer supported. Use armeabi-v7a.

CMake Error at /Users/yabin/tools/android-ndk-r21e/build/cmake/android.toolchain.cmake:174 (message): Armeabi is no longer supported. Use armeabi - v7a. Error while executing process cmake / 3.10.2.4988404 / bin/cmake with arguments Unknown argument - abiFilters Collection contains no element matching the predicate. No valid Native abi found  to request!Copy the code

Solution: Using NDK21 without armeABI support, change to Armeabi-V7A instead

Error: undefined reference to ‘av_codec_next(AVCodec const

) ‘

**

Solution: The ffmPEG library interfaces are c functions, and extern “c” is not declared in the header file, so calling ffmpeg functions in CPP files requires extern “C.

Five, the data

  1. [1.0-FFMPEG-Android builds the latest ffMPEG4.2.1 with NDK (R20)] (juejin.cn/post/684490…)
  2. Shell Scripts – Do your own FFmpeg compilation
  3. AndroidStudio NDK access FFmpeg pit filling notes
  4. Raytheon – simplest ffMPEg-based mobile example: Android HelloWorld
  5. Error: undefined reference to ‘av…
  6. Recompile old projects using CMAKE
  7. Arm64-v8a, Armeabi-v7A, Armeabi, x86 so file compatibility issues

Six, harvest

  1. Configure and compile for NDK16 and NDK21 and ffmpeg3.x and FFmPEG4.x

  2. Handwritten FFMPEG configuration and compilation scripts

  3. AS references use the FFMPEG dynamic library and the introduction of different NDK versions

  4. Understand CPU architecture compatibility

  5. Different NDK versions and FFMPEG versions have different configuration and compilation methods. I still remember that at the beginning of last year, it took a day or two to compile ffmpeg3.x and FFMPEG4. x to generate the corresponding SO. And introduced in AS.

In addition, the ffMPEG and Android demo uploaded to Github for reference.

Github.com/ayyb1988/ff… .

Github.com/ayyb1988/ff…

Ffmpeg_build. sh is stored in the downloaded FFmpeg folder for configuration and compilation.

Thank you for reading

The next article we began to enter the use of FFMPEG, result-oriented, through FFMPEG to achieve a video decoder, welcome to pay attention to the public number “audio and video development journey”, learn to grow together.

Welcome to communicate