FFmpeg compilation and integration

Java is write once, run anywhre, but C is different, and each platform has differences, so it cannot be written only once, and the compilation of each platform is different. For example, the ndk tool chain of android, the libraries of different platforms are different

This article mainly explains the compilation and integration of ffmpeg under the win platform

1. Cross-compilation

Cross-compilation: Cross-compilation means that the compilation environment of the program is inconsistent with the actual operating environment, that is, executable code on one platform is generated on another platform.

Why do you need to cross-compile, in fact, the reason has already been said before, because of the difference between different platforms, the instruction set is different, for example, the above win is the intel instruction set, but almost 100% of the android mobile phone is the arm instruction set, so It is definitely not possible to use the library compiled on win directly for android, so cross-compilation is required.

Cross-compilation is mainly based on the android ndk toolkit

The following is a general list of commonly used components.

  • ARM cross compiler

  • build tool

  • Java native interface header file

  • C library

  • Math library

  • Minimal C++ library

  • ZLib compression library

  • POSIX threads

  • Android logging library

  • Android Native Application API

  • OpenGL ES library

  • OpenSL ES library

Let's take a look at the structure of the NDK and directory provided by Android.

  • ndk-build: This shell script is the starting point of the Android NDK build system. Generally, only executing this command in a project can compile the corresponding dynamic link library.

  • ndk-gdb: This shell script allows to debug Native code with GUN debugger, and can be configured in AS to debug Native code like Java code.

  • ndk-stack: This shell script can help the group analyze the stack information when the Native code crashes.

  • build: This directory contains all modules of the NDK build system.

  • platforms: This directory contains header files and library files that support different Android target versions. The NDK build system will refer to the header files and library files under the specified platform according to the specific configuration.

  • toolchains: This directory contains cross-compilers for different platforms currently supported by NDK - ARM, X86, MIPS, currently ARM is more commonly used. The build system will select different cross compilers according to the specific configuration.

Toolchains generally provide such tools:

  • CC: Compiler, which compiles and processes C source files to generate assembly files.

  • AS: Generate the target file from the assembly file (the assembly file uses the instruction mnemonic, and AS translates it into machine code).

  • AR: Packer, used for library operations, can remove or add object code modules from a library through this tool.

  • LD: linker, which allocates address space for the previously generated object code, and links multiple object files into a library or executable file.

  • GDB: A debugging tool that can perform code debugging on programs during operation.

  • STRIP: Take the final generated executable or library file as input, and then eliminate the source code in it.

  • NM: View the symbol table in the static library file.

  • Objdump: View the method signature of a static library or a dynamic library.

However, the tools in different versions of ndk are different. Some new ndk may not have ar, strip, etc. These tools may be named differently or placed in other places in the new ndk, such as I found 21.1.6352462 (win) contains strip and ar, but there is no related library in version 24.0.8215888, and there is no nm library in these versions. When compiling ffmpeg, it will prompt that nm cannot be found. Fortunately, nm is not necessary , don't panic, if you can't find the relevant tools, it means that there is a problem with the path setting, or there is no such tool in the current version of ndk or it has been renamed, you need to find information to see what the new version of the tool is called or Simply download the old version ndk

 [Learning address]: FFmpeg/WebRTC/RTMP/NDK/Android audio and video streaming media advanced development https://link.zhihu.com/?target=https%3A//ke.qq.com/course/3202131%3FflowToken% 3D1042495 [Article Benefits]: Get more audio and video learning materials packages, Dachang interview questions, technical videos and learning roadmaps for free. The materials include (C/C++, Linux, FFmpeg webRTC rtmp hls rtsp ffplay srs, etc.) if needed You can click 1079654574 to join the group to receive it~

2. Compile FFmpeg

An excellent C++ developer must have a certain understanding of C++ compilation. Cross-compilation has been introduced in the previous article, so let's learn how to compile ffmpeg now

Download the source code on the ffmpeg official website:

git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg

According to your own needs, switch the version you want.

The compilation of ffmpeg is actually very simple, because the awesome ffmpeg developer provides a script called configure. In fact, the compilation script we wrote is to specify the location of the compilation tool, and then call the configure script to compile

I am compiling ffmpeg on win11. I need to download the msys2 tool and configure the relevant environment. I must run msys2 as an administrator to configure the environment, otherwise an exception will be reported.

pacman -S make yasm diffutils pkg-config #在msys2上安装必要软件

Then build the script file in the ffmpeg folder, and paste the following content:

 #!/bin/sh
NDK_PATH=/c/workspace/android_sdk/ndk/21.1.6352462
BUILD_PLATFORM=windows-x86_64
API=21
ANDROID_ARMV5_CFLAGS="-march=armv5te"
ANDROID_ARMV7_CFLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=neon"
ANDROID_ARMV8_CFLAGS="-march=armv8-a"
ANDROID_X86_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"
ANDROID_X86_64_CFLAGS="-march=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel"
# params($1:arch,$2:arch_abi,$3:compiler,$4:cross_prefix,$5:cflags)
build_bin() {
    echo "-------------------star build $2-------------------------"
    ARCH=$1         # arm arm64 x86 x86_64
    # CPU
    ANDROID_ARCH_ABI=$2     # armeabi armeabi-v7a x86 mips
    COMPILER=$3
    PREFIX=$(pwd)/dist/${ANDROID_ARCH_ABI}/
    TOOLCHAIN=${NDK_PATH}/toolchains/llvm/prebuilt/${BUILD_PLATFORM}
    CC=${TOOLCHAIN}/bin/${COMPILER}-clang
    CXX=${TOOLCHAIN}/bin/${COMPILER}-clang++
    SYSROOT=${TOOLCHAIN}/sysroot
    CROSS_PREFIX=${TOOLCHAIN}/bin/$4-
    CFLAGS=$5
    echo "pwd==$(pwd)"
    echo "ARCH==${ARCH}"
    echo "PREFIX==${PREFIX}"
    echo "SYSROOT=${SYSROOT}"
    echo "CFLAGS=${CFLAGS}"
    echo "CC==${CC}"
    echo "CROSS_PREFIX=${CROSS_PREFIX}"
    sh ./configure \
        --prefix=${PREFIX} \
        --enable-neon \
        --enable-hwaccels \
        --enable-gpl \
        --disable-postproc \
        --disable-debug \
        --enable-small \
        --enable-jni \
        --enable-mediacodec \
        --enable-decoder=h264_mediacodec \
        --disable-static \
        --enable-shared \
        --disable-doc \
        --enable-ffmpeg \
        --disable-ffplay \
        --disable-ffprobe \
        --disable-avdevice \
        --disable-doc \
        --disable-symver \
        --target-os=android \
        --arch=${ARCH} \
        --cc=$CC \
        --sysroot=$SYSROOT \
        --enable-cross-compile \
        --cross-prefix=${CROSS_PREFIX} \
        --extra-cflags="-Os -fPIC -DANDROID -Wfatal-errors -Wno-deprecated $CFLAGS" \
        --extra-cxxflags="-D__thumb__ -fexceptions -frtti" \
        --extra-ldflags="-L${SYSROOT}/usr/lib" \
    make clean
    make -j8
    make install
    echo "-------------------$2 build end-------------------------"
}
# build armeabi
# build_bin arm armeabi arm-linux-androideabi arm-linux-androideabi "$ANDROID_ARMV5_CFLAGS"
#build armeabi-v7a
#build_bin arm armeabi-v7a armv7a-linux-androideabi${API} arm-linux-androideabi "$ANDROID_ARMV7_CFLAGS"
#build arm64-v8a
 build_bin arm64 arm64-v8a aarch64-linux-android${API} aarch64-linux-android "$ANDROID_ARMV8_CFLAGS"
#build x86
# build_bin x86 x86 i686-linux-android${API} i686-linux-android "$ANDROID_X86_CFLAGS"
#build x86_64
# build_bin x86_64 x86_64 x86_64-linux-android${API} x86_64-linux-android "$ANDROID_X86_64_CFLAGS"

Related explanation:

  • CC: Specify the c compiler path

  • CROSS_PREFIX: Specifies the uniform prefix of the cross-compilation tool file path. The final file path of each tool is: cross-prefix + tool name. For example, the prefix of the above script is TOOLCHAIN/bin/arm-linux-androideabi-, then the path of the ar tool is TOOLCHAIN/bin/arm-linux-androideabi-ar

  • target-os: Specify the target platform, because ffmpeg can run on each platform, and some configurations on each platform are different, so it needs to be specified

In addition, there are a lot of enable and disable in the compilation script, these are the compilation options in the configure script, for example --enable-shared means to compile the dynamic library, so the above script will eventually generate the so file instead of the a file .

These compilation options can be found using configure --help, you can try

Whether it is these enable compilation options or options like CC, they are configuring the configure script. Open the configure file in text mode, and you can see:

--cc=CC                  use C compiler CC [$cc_default]
--target-os=OS           compiler targets OS [$target_os]
--enable-shared          build shared libraries [no]

After running the compilation script, if the compilation is successful, you will see the relevant so library, which is in the lib folder

3. FFmpeg integration

First look at how cmakelist is written:

# 设置最小使用版本
cmake_minimum_required(VERSION 3.18.1)
project("demo")
include_directories(include)
# 添加本地so库 native-lib:这个是声明引用so库的名称 SHARED:表示共享so库文件
# 构建so库的源文件
add_library(
        demo
        SHARED
        native-lib.cpp
)
set(SO_DIR ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
# 使用系统ndk 提供的库,如 log库
# log-lib 这个指定的是在NDK库中每个类型的库会存放一个特定的位置,而log库存放
# 在log-lib中
# log 指定使用log库
find_library(
        log-lib
        log
)
message("c_CMAKE_SOURCE_DIR:" ${CMAKE_SOURCE_DIR} )
# 加载avcodec-57库
add_library( avcodec
        SHARED
        IMPORTED)
set_target_properties( avcodec
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libavcodec.so)
add_library( avutil
        SHARED
        IMPORTED)
set_target_properties( avutil
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libavutil.so)
add_library( swresample
        SHARED
        IMPORTED)
set_target_properties( swresample
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libswresample.so)
add_library( avfilter
        SHARED
        IMPORTED)
set_target_properties( avfilter
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libavfilter.so)
add_library( avformat
        SHARED
        IMPORTED)
set_target_properties( avformat
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libavformat.so)
add_library( swscale
        SHARED
        IMPORTED)
set_target_properties( swscale
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libswscale.so)
#----------------------end-----------------------
# 如果你本地的库(native-lib)想要调用log库的方法,
# 那么就需要配置这个属性,意思是把NDK库关联到本地库。
# 第一个参数表示本地的库 native-lib 要调用到log库的方法,即要被关联的库名称,log-lib 要关联的库名称
target_link_libraries(
        demo
        #ffmpeg------start----------
        avcodec
        avutil
        swresample
        avfilter
        avformat
        swscale
        #ffmpeg------end------------
        ${log-lib}
)

In fact, these writing methods are very simple. If you make a mistake, you must have written it incorrectly. Just pay attention to the relevant details. All codes have been uploaded to my github

Original link: FFmpeg compilation and integration - Nuggets

Guess you like

Origin blog.csdn.net/irainsa/article/details/130773521