The premise

I’ve been working on this article for two weeks now, but I think it’s a good idea to look back at some of the simple FFmpeg commands in the previous article. You can download the static libraries of different platforms and run binary files to edit audio and video files. I just talked last time about compositing video images, using vstack and hstack. This time, I will teach you how to make video picture splicing on your Android phone and how to compile so library and static library of Android platform through the official library. This will probably cover a lot of things, and a lot of shell scripting language stuff. I hope old iron patience to see, will definitely help.

This is the previous series

FFmpeg is so interesting (1)

I’m going to show you some manipulations,

  • There is no need to implement FFmpeg methods through JNI at all. The Java language can play with FFmpeg directly, but some features are limited. (Static library)
  • Pack all the compiled SO libraries into a so to play, save trouble. (Dynamic library)

To prepare

Here is mainly for you to download the same version number, according to the script can be compiled successfully, otherwise each version may have to modify some parameters I here in accordance with my environment and you say it

  • Ubuntu (Ubuntu 18.10)

  • FFmpeg official library (4.0.2) X264 official library

  • This has been uploaded to Github (compile script and compile library, script common, but different platform library may be different).

Official FFmpeg

X264 official

Github download address

preheating

I will upload the compiled FFmpeg static library to Github so you can use it directly. Github download address

App executes static library scripts

In our app, if you want to execute binary files, you must put them in our private directory. Sdcard is just a folder out of the Android file system Linker, so it has no permission to execute binary files, while our app’s private directory is ok. I’ll give you the code below just for your reference.

The binary FFmpeg has been uploaded to Github. If you are interested in it, you can download it and run it in your App. You can put the file in assets folder and copy it to the private directory of the App when the App is running

 boolean isFileCopied = FileUtils.copyBinaryFromAssetsToData(App.getInstance(),
                        cpuArchNameFromAssets + File.separator + FileUtils.ffmpegFileName,
                        FileUtils.ffmpegFileName);

                // make file executable
                if (isFileCopied) {
                    if(! ffmpegFile.canExecute()) { Log.d(BuildInfo.TAG,"FFmpeg is not executable, trying to make it executable ...");
                        if (ffmpegFile.setExecutable(true)) {
                            Log.d(BuildInfo.TAG, "FFmpeg is executable"); }}else {
                        Log.d(BuildInfo.TAG, "FFmpeg is executable"); }}Copy the code

You can write the above code yourself. I’m not going to post all of them. When your App is running, you copy this file to your local, and then you call


ffmpegFile.setExecutable(true)

Copy the code

This allows FFmpeg to be executed. Android also provides a way to commend


 public static Process run(String[] commandString) {
        Process process = null;
        try {
            process = Runtime.getRuntime().exec(commandString);
            String output = Util.convertInputStreamToString(process.getErrorStream());
            Log.i("cuieney",output);
        } catch (IOException e) {
            Log.e(BuildInfo.TAG,"Exception while trying to run: " + commandString+e.toString());
        }
        return process;
    }
    

Copy the code

You just call runtime.exec and you just write the command in.

run({"ffmpeg".""})

Copy the code

That’s ok. If you’re successful you can see this in logcat, but there are so many logs that I didn’t copy it

Ffmpeg version 4.0.2 Copyright (c) 2000-2018 The ffmpeg developersbuilt with GCC 4.9.x (GCC) 20150123 (prerelease)........Copy the code

I’ve done a few things here based on the compiled library

Apk Download address

Scanning the QR code can also be downloaded

So here we go. Compile this thing.

Build FFmpeg for Android

About compiling Android platform library may have a lot of online, anyway, a search, there must be you need, here I mainly teach you to use static library rather than dynamic library, so you will save a lot of trouble, all kinds of so library paste back and forth, but also write cMakelist corpus, configure Gradle, For those of you who haven’t played FFmpeg, it might take a long time, but here’s another way to play it, right

The dynamic library

So a dynamic library is basically a compiled so library that links into our project and loads the library and then operates on the c through jNI, so this is a quick summary, so I know what I need, so what we’re going to do is compile this so library, You can see on the web that FFmpeg has compiled a lot of so’s and you want to put them one by one into our project. And then you add things in cMakelist. Here I’ll show you how to compile these libraries into a so, which will save you a lot of trouble

  • So if that’s all right, you’re ready to run the script and open up the FFmpeg package that you downloaded, and you can see the structure of the directory, and the main thing that we use to compile is the configure binary. You can see it in the figure below

I’m going to post some of the code here, and I’m going to post the whole thing on Github (the following script is called build_ffmpeg_android.sh, and you can find it in my address above), and I’m going to write some comments on it

You can see that there isa MODULE(enabel and disable) in the code below. GENERAL (which is used to set parameters and add additional libraries) and LIB_TYPE (which is used to set whether to compile shared or static)

function build
{
  pushd ffmpeg
  ./configure                           \
  --logfile=config.log                  \
  --target-os=android                   \
  --prefix=$PREFIX         \
  ${MODULE}                             \
  ${GENERAL}                            \
  ${LIB_TYPE}                           \
  --sysroot=$PLATFORM                   \
  --extra-cflags="-fPIE -fPIC -std=c11" \
  --extra-ldflags="$flags $shared_flag" \

  # essencial for dynamic library
  sed -i -E "s/^(#define HAVE_SYSCTL).*/\1 0/" config.h

  make clean
  make -j$NUM_OF_CORE
  make install

  popd
}

build

Copy the code

This is the argument to GENERAL

GENERAL=" \ --extra-libs="-lgcc"                                \
  --arch=${ARCH}                                      \
  --cc=$PREBUILT/bin/${BIN_PREFIX}-gcc        \
  --cross-prefix=$PREBUILT/bin/${BIN_PREFIX}- \
  --nm=$PREBUILT/bin/${BIN_PREFIX}-nm         \
  --extra-cflags="-I$X264_INCLUDE" \ --extra-ldflags="-L$X264_LIB"\"

Copy the code

The module argument is only part of the module argument, so you can use disable, which is not used by enable. Otherwise, the compiled library will be very large. Then our APK will be relatively large, and you can download the original file on Github

MODULE=" \ --enable-jni \ --enable-pic \ --enable-gpl \ --enable-zlib \ --enable-yasm \ --enable-small \ --enable-pthreads \ --enable-mediacodec \ --enable-libx264 \ --enable-cross-compile \ --disable-doc \ --disable-ffplay \ --disable-ffprobe \  --disable-network \ --enable-neon --disable-linux-perf \ --enable-encoder=libx264 \ --enable-encoder=aac \ --enable-encoder=mpeg4 \ --enable-encoder=mjpeg \ --enable-encoder=png \ --disable-muxers \Copy the code

Static library

The script is called build_ffmpeg_android.sh, so just follow the following command to compile the static library

./build_ffmpeg_andori.sh static
Copy the code

If you want to compile a dynamic library, just change static to shared.

Now the computer should compile quickly, successful execution should see the following directory, so has been compiled

The static library is out

Combine the compiled library into a so library

Simply add the following code to the compile script.

$TOOLCHAIN/bin/${BIN_PREFIX}-ld \
      -rpath-link=$PLATFORM/usr/lib \
      -L$PLATFORM/usr/lib \
      -L$PREFIX/lib \
      -L$X264_LIB \
      -soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o \
      $PREFIX/libffmpeg.so \
      $PREFIX/lib/libavcodec.a \
      $PREFIX/lib/libavfilter.a \
      $PREFIX/lib/libavformat.a \
      $PREFIX/lib/libavutil.a \
      $PREFIX/lib/libswresample.a \
      $PREFIX/lib/libswscale.a \
      $X264_ALIB/libx264.a \
      -lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker \
      $TOOLCHAIN/lib/gcc/${BIN_PREFIX}/ 4.9 x/libgcc. ACopy the code

As you can see from the script above, the linker library is equivalent to libffmpeg.so.

If you’re successful, you’ll see the so library in Android under ffmpeg

You can see that libffmpeg.so is out

Compile Lib264 library

role

Why do you use this library? If you’ve done all of the above, and you’ve run it on an Android machine, you’ll find that the resulting video files are obviously of poor quality, I shouldn’t say poor, but you’re definitely not happy with them. Having said that, you should know what this library is for, improving the quality of coding. The reason why the PC library I downloaded from the official website is good quality is because they already have this library in it and it is enabled. So what we need to do here is to download the official source code of Lib264, compile it for Android platform and then put the library into FFmpeg.

Compile Lib264

This library is easy to compile. There aren’t that many parameters and code. The script on Github is called (build_x264_andorid.sh) and you can download it

If you want to compile different versions, you can also use the shared or static suffix

LIB_TYPE=${1-static}
echo '@ @ @ # # # # #'${LIB_TYPE}
function build
{
  pushd x264

  # remove suffix of libx264.so
  sed -in 's/so\.\$API/so/g' configure
  ./configure                                           \
  --prefix=./android/$ABI                               \
  --enable-$LIB_TYPE                                    \
  --enable-pic                                          \
  --host=$BIN_PREFIX                                  \
  --cross-prefix=${PREBUILT}/bin/${BIN_PREFIX}- \
  --extra-cflags="-fPIC -fPIE -std=c11"                 \
  --sysroot=$PLATFORM

  sed -i 's/-f -s/-f/g' ./Makefile

  make clean
  make -j$NUM_OF_CORE
  make install
  tree android
  popd
}

build

printf "$success" "x264"


Copy the code
./build_x264_android.sh shared

Copy the code

You should see the following directory under x264/android/, so has been compiled

FFmpeg Lib264 synthesis

We’ve already compiled the libraries for each platform, so how do we put these two libraries together, and as you can see, I’ve already put the code in there, when we compiled the build_ffmpeg_android.sh script which is the GENERAL field

See that the following fields cflags and ldflags have compiled the X264 we compiled earlier.

X264_INCLUDE=.. /x264/android/$ABI/include X264_LIB=.. /x264/android/$ABI/lib X264_ALIB=.. /x264Copy the code

GENERAL=" \ --extra-libs="-lgcc"                                \
  --arch=${ARCH}                                      \
  --cc=$PREBUILT/bin/${BIN_PREFIX}-gcc        \
  --cross-prefix=$PREBUILT/bin/${BIN_PREFIX}- \
  --nm=$PREBUILT/bin/${BIN_PREFIX}-nm         \
  --extra-cflags="-I$X264_INCLUDE" \ --extra-ldflags="-L$X264_LIB"\"
Copy the code

Build different ARCH libraries (Armeabi-v7a arm64-V8a…)

This one is relatively simple, since one platform is successful, the others can change the compilation platform. You can modify a few parameters in our script,

I have made some judgments on my side. I can modify the following ARCH in our common.sh directory before compiling the script, and then execute build_ffmpeg_android.sh.


#ARCH=arm
ARCH=aarch64
[[ $ARCH = "arm" ]] && \
    { BIN_PREFIX=arm-linux-androideabi; ABI=armeabi-v7a; } ||     { BIN_PREFIX=aarch64-linux-android; ABI=arm64-v8a; }

NDK=~/Downloads/android-ndk-r14b
PLATFORM=$NDK/platforms/android-21/arch-arm64
PREBUILT=$NDK/toolchains/${BIN_PREFIX}4.9 / prebuilt/Linux - x86_64 TOOLCHAIN =$NDK/toolchains/${BIN_PREFIX}4.9 / prebuilt/Linux - x86_64 NUM_OF_CORE = $(nproc) success ="${BLACKB}${YELLOWF}build %s success${RESET}\n"


Copy the code

That is the common.sh script. If you want to change the “arm” parameter to the “PLATFORM” parameter, use the “64” parameter.

finishing

Maybe there is something that is not clear. You can ask questions in the comments or in your personal message. If there is a mistake above, you can actively and I said. I will correct it in the article.

To be continue….. I’ll bring you a little bit about apps next time. For example, picture splicing, add logo, add background music, video picture cutting… Have want to know also can mention in the message. I’ll do some research,