The original article was first published on the wechat official account Byteflow

Why learn FFmpeg development

FFmpeg is a well-known open source audio and video processing software, it provides a rich and friendly interface to support developers for secondary development.

FFmpeg is pronounced “ef ef em peg”, where “FF” stands for “Fast Forward” and “MPEG” stands for “Moving Picture Experts Group”.

FFmpeg project features complex and huge, basically support all common audio and video processing operations, such as packaging format conversion, audio and video transcoding, audio and video playback and editing, video adding watermark filter, etc.

Although FFmpeg is powerful, it uses the contagious LGPL/GPL open source protocol, so some major manufacturers have developed similar audio and video processing libraries on their own, even imitating FFmpeg in interface and organization modules.

Therefore, learning FFmpeg will not only help you master the relevant knowledge of audio and video development, but also allow you to quickly adapt to different audio and video processing frameworks.

FFmpeg compilation

FFmpeg has six common functional modules:

  • Libavformat: a library that encapsulates and unencapsulates multimedia files and protocols, such as Mp4 and Flv, and network protocols such as RTMP and RTSP.
  • Libavcodec: Audio and video codec library;
  • Libavfilter: Library for audio, video, and subtitles;
  • Libswscale: image format conversion library;
  • Libswresample: Audio resampling library;
  • Libavutil: tool library;

This article is mainly to help beginners quickly start FFmpeg compilation and integration, the FFmpeg project compilation and configuration details are not more than elaborated, which is not the content of this article can accommodate.

The main choice is ffMPEG V4.2.2, because there are more solutions on the web and most of them are available.

Compilation environment:

  • CentOS Linux release 7.6.1810 (Core)
  • android-ndk-r20b-linux-x86_64
  • Ffmpeg – 4.2.2

Preparation before compilation:

/ / 1. Download ffmpeg - 4.2.2
wget https:/ / ffmpeg.org/releases/ffmpeg-4.2.2.tar.bz2
/ / 2. Unzip the FFmpeg
tar -jxvf ffmpeg4.22..tar.bz2
//3. Configure items
./configure --disable-x86asm
Copy the code

Create the build_android_arm64-v8a_clang.sh script in FFmpeg 4.2.2:

#! /bin/bash

export NDK=/root/workspace/android-ndk-r20b Configure your NDK path here
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64


function build_android
{

./configure \
--prefix=$PREFIX \
--enable-neon  \
--enable-hwaccels  \
--enable-gpl   \
--disable-postproc \
--disable-debug \
--enable-small \
--enable-jni \
--enable-mediacodec \
--enable-decoder=h264_mediacodec \
--enable-static \
--enable-shared \
--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 -j16
make install

echo "============================ build android arm64-v8a success =========================="

}

#arm64-v8a
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
Copy the code

FFmpeg 64 bit dynamic library and static library for Android platform

Build_android_arm64-v8a_clang. sh executable permission
chmod +x build_android_arm64-v8a_clang.sh
Run the compile script
./build_android_arm64-v8a_clang.sh
Copy the code

After successful compilation, static libraries and dynamic libraries corresponding to six modules will be generated in the Android directory.

In addition, to compile to a 32-bit library, you need to modify the corresponding compilation script:

#armv7-a
ARCH=arm
CPU=armv7-a
API=21
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 "
Copy the code

FFmpeg integration

Based on the FFmpeg static library compiled in the previous section, we performed a simple integration test on Android Studio.

We can implement a JNI to obtain the version information of each module by placing the static libraries and header files of each FFmpeg module in a specified directory as shown in the figure above.

#include <cstdio>
#include <cstring>
#include "util/LogUtil.h"
#include "jni.h"

// Since the FFmpeg library is implemented in C, it tells the compiler to compile according to THE rules of C
extern "C" {
#include <libavcodec/version.h>
#include <libavcodec/avcodec.h>
#include <libavformat/version.h>
#include <libavutil/version.h>
#include <libavfilter/version.h>
#include <libswresample/version.h>
#include <libswscale/version.h>
};

#ifdef __cplusplus
extern "C" {
#endif
/* * Class: com_byteflow_learnffmpeg_media_FFMediaPlayer * Method: native_GetFFmpegVersion * Signature: ()Ljava/lang/String; * /
JNIEXPORT jstring JNICALL Java_com_byteflow_learnffmpeg_media_FFMediaPlayer_native_1GetFFmpegVersion
        (JNIEnv *env, jclass cls)
{
    char strBuffer[1024 * 4] = {0};
    strcat(strBuffer, "libavcodec : ");
    strcat(strBuffer, AV_STRINGIFY(LIBAVCODEC_VERSION));
    strcat(strBuffer, "\nlibavformat : ");
    strcat(strBuffer, AV_STRINGIFY(LIBAVFORMAT_VERSION));
    strcat(strBuffer, "\nlibavutil : ");
    strcat(strBuffer, AV_STRINGIFY(LIBAVUTIL_VERSION));
    strcat(strBuffer, "\nlibavfilter : ");
    strcat(strBuffer, AV_STRINGIFY(LIBAVFILTER_VERSION));
    strcat(strBuffer, "\nlibswresample : ");
    strcat(strBuffer, AV_STRINGIFY(LIBSWRESAMPLE_VERSION));
    strcat(strBuffer, "\nlibswscale : ");
    strcat(strBuffer, AV_STRINGIFY(LIBSWSCALE_VERSION));
    strcat(strBuffer, "\navcodec_configure : \n");
    strcat(strBuffer, avcodec_configuration());
    strcat(strBuffer, "\navcodec_license : ");
    strcat(strBuffer, avcodec_license());
    LOGCATE("GetFFmpegVersion\n%s", strBuffer);
    return env->NewStringUTF(strBuffer);
}

#ifdef __cplusplus
}
#endif
Copy the code

Java layer call logic:

package com.byteflow.learnffmpeg.media;

public class FFMediaPlayer {
    static {
        System.loadLibrary("learn-ffmpeg");
    }

    public static String GetFFmpegVersion(a) {
        return native_GetFFmpegVersion();
    }

    private static native String native_GetFFmpegVersion(a);
}

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((TextView)findViewById(R.id.text_view)).setText(FFMediaPlayer.GetFFmpegVersion()); }}Copy the code

Cmakelists.txt build script:

# Sets the minimum version of CMake required to build the native library.Cmake_minimum_required (VERSION 3.4.1 track)set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

set(jnilibs ${CMAKE_SOURCE_DIR}/.. /jniLibs)set(libname learn-ffmpeg)

include_directories(
        include
        ${CMAKE_SOURCE_DIR}/util
)

link_directories(
        ${jnilibs}/${ANDROID_ABI})

file(GLOB src-files
        ${CMAKE_SOURCE_DIR}/*.cpp)

add_library( # Sets the name of the library.
             ${libname}

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             ${src-files}
        )

set(third-party-libs
        avformat
        avcodec
        avfilter
        swresample
        swscale
        avutil
        )

set(native-libs
        android
        EGL
        GLESv3
        OpenSLES
        log
        m
        z
        )

target_link_libraries( # Specifies the target library.
                       ${libname}

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib}
                       ${third-party-libs}
                       ${native-libs}
                       )
Copy the code

After compiling, run App to obtain FFmpeg module version and compilation configuration information.

reference

Blog.csdn.net/leixiaohua1…

Juejin. Cn/post / 684490…

Technical question solving

Technical exchange or access to source code can add my wechat: byte-flow, access to audio and video development video tutorials