FFmpeg is introduced into Android Studio, which is the favorite of the white whoring party

Posted by Boxerman on Mon, 06 Sep 2021 06:46:11 +0200

Then let's see how to build an environment for compiling FFmpeg?

Build an environment for compiling FFmpeg

=========================================================================

FFmpeg provides a complete solution, but this solution is written in C. we download the source code of FFmpeg and decompress it to see what the source code of FFmpeg looks like

Here is the version 4.1.3. We will learn the operation with 4.2.1 later

From the very beginning to the current 4.x.x version of FFmpeg, the intermediate versions have changed greatly. For example, there are great differences between 2.0-3.0 and 3.0-4.0. The versions after 4.0 are compiled through NDK Clang and will not be compiled in gcc. Therefore, we mainly explain the cross compilation process of Clang

We open the source code of FFmpeg, click the folder and find that all the codes in it are some C and C + + codes and hundreds of files. If we put these files into Android Studio for compilation, it will take quite a long time for you to compile an Apk at this time, This is why we need to generate so through cross compilation and then put it into our project

So how do we use FFmpeg?

We download the source code of FFmpeg, and then compile it into Android system and compile it into dynamic library or static library. This compilation process requires our compilation environment, not Windows, but Linux. For this Linux, we use CentOS 7.3, and then compile the source code with Linux to generate a dynamic library or static library, put it into our App, and then call it through the header file

Enter FFmpeg's official website, where we can download the source code, but if we download it to Windows, it is useless. We must download it to Linux

Come back to the server we just started and download the FFmpeg source code

Create an FFmpeg. We also use FFmpeg when streaming audio and video live broadcast

In this way, we have finished downloading an FFmpeg. After downloading, we still need to decompress it

We call the decompression command xvf, and then decompress FFmpeg

In the process of decompression, you can find that there are many C files in it

This is the source code of FFmpeg. We need to compile the source code of FFmpeg. There is gcc in Linux. Can we compile FFmpeg through gcc in Linux?

Obviously, it should not, because gcc in Linux is different from gcc tools in Android. Linux compiles things that can only be used in Linux and cannot be transplanted to our Android system. At this time, we need to learn another technology - Cross compilation.

At present, after NDK 17, its recommended cross tool is called Clang. In previous versions, we all used Android gcc.

What's the difference between gcc and Clang for Android?

In order to make us compile faster and execute C code faster, we developed a very convenient compilation tool called Clang

Later, FFmpeg will be compiled through the latest NDK version and Clang

Now that the source code has been downloaded, we still need a compilation tool - NDK

NDK environment configuration

===================================================================

Because there are many C compilation tools in the NDK source file, we must use the NDK compilation tool instead of the Linux compilation tool. We call this compilation cross compilation.

Back to ECs, we need to download an NDK. You can choose NDKr20 when downloading. We will compile it with this version

Then we need to configure the environment of NDK

mkdir ndk creates an NDK directory

It is recommended that you buy a server in Hong Kong, because the server in Hong Kong can download these foreign software very quickly. For example, my server is actually a Hong Kong server

Then we can download the NDK by using the wget command. NDK is relatively large, but due to the Hong Kong server, the download is still very fast

After downloading, use the zip command to unzip the downloaded file

unzip, the decompression time may be a little long. According to the configuration of each server, the decompression time will be different

After decompression, we configure the NDK environment. This configuration environment is still somewhat different from Windows. In Windows, we can configure it directly on my computer, but in Linux, it is different. We need to edit etc/profile

Add our environment at the bottom. We set an NDK ROOT and add it to the PATH

Then exit and let the environment take effect

So far, our NDK environment has been configured. At this time, we need to compile FFmpeg and use shell script

shell script

===================================================================

shell script, which is specially designed for Linux, compiles syntax, similar to Java syntax

Speaking of which, shall we learn shell grammar?

Learning is definitely necessary, but we only need to understand how to write the shell script, which can meet the content we need to master in this series of articles

Let's look at the content of this script. The role of the script is to package the FFmpeg source code into. so files or. a static library files we want to use in Android for us to call in Android projects

Create an android in the FFmpeg source folder_ build.sh

Directly copy the following code

#!/bin/bash

export NDK=/root/ndk/android-ndk-r20

# Current system

export HOST_TAG=linux-x86_64

# Supported Android CUP architecture

# export ARCH=aarch64

# export CPU=armv8-a

export ARCH=armv7a

export CPU=armv7-a

# Minimum supported Android system version

export MIN=21

export ANDROID_NDK_PLATFORM=android-21



export PREFIX=$(pwd)/android/$CPU



export MIN_PLATFORM=$NDK/platforms/android-$MIN

export SYSROOT=$NDK/sysroot

export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/$HOST_TAG

export AR=$TOOLCHAIN/bin/arm-linux-androideabi-ar

export AS=$TOOLCHAIN/bin/arm-linux-androideabi-as

export CC=$TOOLCHAIN/bin/$ARCH-linux-androideabi$MIN-clang

echo "-----------------------------"

echo $CC

export CXX=$TOOLCHAIN/bin/$ARCH-linux-androideabi$MIN-clang++

export LD=$TOOLCHAIN/bin/arm-linux-androideabi-ld

export NM=$TOOLCHAIN/bin/arm-linux-androideabi-nm

export RANLIB=$TOOLCHAIN/bin/arm-linux-androideabi-ranlib

export STRIP=$TOOLCHAIN/bin/arm-linux-androideabi-strip



OPTIMIZE_CFLAGS="-DANDROID -I$NDK/sysroot/usr/include/arm-linux-androideabi/"

ADDI_LDFLAGS="-Wl,-rpath-link=$MIN_PLATFORM/arch-arm/usr/lib -L$MIN_PLATFORM/arch-arm/usr/lib -nostdlib"



sed  -i "" "s/SLIBNAME_WITH_MAJOR='\$(SLIBNAME).\$(LIBMAJOR)'/SLIBNAME_WITH_MAJOR='\$(SLIBPREF)\$(FULLNAME)-\$(LIBMAJOR)\$(SLIBSUF)'/" configure

sed  -i "" "s/LIB_INSTALL_EXTRA_CMD='\$\$(RANLIB) \"\$(LIBDIR)\\/\$(LIBNAME)\"'/LIB_INSTALL_EXTRA_CMD='\$\$(RANLIB) \"\$(LIBDIR)\\/\$(LIBNAME)\"'/" configure

sed  -i "" "s/SLIB_INSTALL_NAME='\$(SLIBNAME_WITH_VERSION)'/SLIB_INSTALL_NAME='\$(SLIBNAME_WITH_MAJOR)'/" configure

sed  -i "" "s/SLIB_INSTALL_LINKS='\$(SLIBNAME_WITH_MAJOR) \$(SLIBNAME)'/SLIB_INSTALL_LINKS='\$(SLIBNAME)'/" configure

sed -i -e 's/#define getenv(x) NULL/\/\*#define getenv(x) NULL\*\//g' config.h

# sed  -i "" "s/SHFLAGS='-shared -Wl,-soname,\$(SLIBNAME)'/SHFLAGS='-shared -soname \$(SLIBNAME)'/" configure

# sed  -i "" "s/-Wl//g" configure



./configure \

--prefix=$PREFIX \

--ar=$AR \

--as=$AS \

--cc=$CC \

--cxx=$CXX \

--nm=$NM \

--ranlib=$RANLIB \

--strip=$STRIP \

--arch=$ARCH \

--target-os=android \

--enable-cross-compile \

--disable-asm \

--enable-shared \

--disable-static \

--disable-ffprobe \

--disable-ffplay \

--disable-ffmpeg \

--disable-debug \

--disable-symver \

--disable-stripping \

--extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS"\

--extra-ldflags="$ADDI_LDFLAGS"



sed  -i "" "s/#define HAVE_TRUNC 0/#define HAVE_TRUNC 1/" config.h

sed  -i "" "s/#define HAVE_TRUNCF 0/#define HAVE_TRUNCF 1/" config.h

sed  -i "" "s/#define HAVE_RINT 0/#define HAVE_RINT 1/" config.h

sed  -i "" "s/#define HAVE_LRINT 0/#define HAVE_LRINT 1/" config.h

sed  -i "" "s/#define HAVE_LRINTF 0/#define HAVE_LRINTF 1/" config.h

sed  -i "" "s/#define HAVE_ROUND 0/#define HAVE_ROUND 1/" config.h

sed  -i "" "s/#define HAVE_ROUNDF 0/#define HAVE_ROUNDF 1/" config.h

sed  -i "" "s/#define HAVE_CBRT 0/#define HAVE_CBRT 1/" config.h

sed  -i "" "s/#define HAVE_CBRTF 0/#define HAVE_CBRTF 1/" config.h

sed  -i "" "s/#define HAVE_COPYSIGN 0/#define HAVE_COPYSIGN 1/" config.h

sed  -i "" "s/#define HAVE_ERF 0/#define HAVE_ERF 1/" config.h

sed  -i "" "s/#define HAVE_HYPOT 0/#define HAVE_HYPOT 1/" config.h

sed  -i "" "s/#define HAVE_ISNAN 0/#define HAVE_ISNAN 1/" config.h

sed  -i "" "s/#define HAVE_ISFINITE 0/#define HAVE_ISFINITE 1/" config.h

sed  -i "" "s/#define HAVE_INET_ATON 0/#define HAVE_INET_ATON 1/" config.h

sed  -i "" "s/#define getenv(x) NULL/\\/\\/ #define getenv(x) NULL/" config.h



Our shell script contains a lot of content, but the shell script actually has only one sentence, that is, it calls our. / configure file

This. / configure is the configure file in the same level directory of build.sh

We go directly to the FFmpeg source code. There is a thing called configure in the same level directory of the FFmpeg source code, and then we open it

This. / configure also belongs to the shell file. It is an executable SHELL file, similar to the main function in Java

How do we judge whether it is a shell file?

Its first sentence is #/ bin/sh means that it is a shell file. The shell file is executable, which is equivalent to that some parameters may be passed in the main function. For example, we often write some main functions in Java, and then there is a sting array in the main function. We can pass some parameters in by executing the java file on the command line. Similarly, it will pass these parameters in the shell file, but the parameters passed in configure are more complex

In short, we execute the shell file just to call such a sentence. / configure to execute the shell file we just mentioned

Parameter setting

================================================================

The following are all parameters

The above is to define some parameter variables, similar to global variables

Let's look at. / configure. The first – prefix represents the directory in which we want to output

What we finally compiled is a dynamic library, which must have a folder, but the file is placed in the prefix variable. We look up and find the place where the prefix defines the variable declaration, which is in our current directory

pwd is a command, shell syntax, which can directly call these commands. For example, pwd can output to the current directory

The Android CPU in the current directory is our currently compiled CPU. We compile armv7a. During the compilation process, an Android file will be generated, and then a sub file called armCPUv7a will be generated under the Android file. Finally, put our compilation results in this folder

– ar is a link compiler in Clang. We can open the NDK. I open it in the NDK of Android studio, and then we open its directory, Android/SDK

There is an NDK bundle in this directory. We directly open windows. Windows and Linux are similar because they are the same version, but the suffix is. exe and the executable file in Linux

Let's open NDK bundle and then toolchains

toolchains: it means tool chain

Go on, we can find many executable files. In Windows, the suffix name is. exe

Then it has the following files that need to be passed in FFmpeg, and the parameters are passed in

The paths ar, as, nm and strip need to be specified. They are mainly used for link compilation to speed up the compilation of so

Therefore, you will find that when passing parameters, the first one is - AR, and its value is the variable ar. above, we will define a variable called ar

His path is shown in the figure below, that is, the paths we just saw

These all play the role of a link compilation tool

In the previous NDK version, there were no these files. In the past, there was only gcc. Now, after cross compiling with Clang, we need to specify the contents of these cross compiling tool chains

The above five paths are to specify the specified tools in our cross tool chain, that is, after we specify these tools, we will use these tools to compile when FFmpeg is compiled

The two main parameters are the following – cc and – cxx. In the past, we were – gcc, and now it is cc. cc refers to Clang

$CC is the variable defined

Let's find out. We'll find a lot of Clang's compilation tools here

Topics: Linux Windows Android Design Pattern