The original article was first published on wechat official account: byte flow
Why learn FFmpeg development
FFmpeg is a well-known open source audio and video processing software. It provides rich and friendly interfaces to support developers' secondary development.
FFmpeg reads "ef ef em peg", where "FF" refers to "Fast Forward" and "mpeg" refers to "Moving Picture Experts Group".
FFmpeg project has complex and huge functions, and basically supports 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, because it adopts the infectious LGPL/GPL open source protocol, some large manufacturers basically independently develop similar audio and video processing libraries, and even imitate FFmpeg in interface and organization modules.
Therefore, learning FFmpeg can not only help you master the relevant knowledge of audio and video development, but also enable you to quickly adapt to different audio and video processing frameworks.
FFmpeg compilation
FFmpeg has six common functional modules:
- libavformat: packaging and unpacking Library of multimedia files or protocols, such as Mp4, Flv and other file packaging formats, RTMP, RTSP and other network protocol packaging formats;
- libavcodec: audio and video codec library;
- libavfilter: audio, video and caption filter library;
- libswscale: image format conversion library;
- libswresample: Audio resampling library;
- libavutil: tool library;
This article is mainly to help beginners quickly get started with the compilation and integration of FFmpeg. There is no more detail on the compilation and configuration of FFmpeg project, which can not be accommodated in this article.
Here we mainly choose to compile ffmpeg v4 Version 2.2, because there are many online solutions in this version, and most of them are feasible.
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. Decompress FFmpeg tar -jxvf ffmpeg-4.2.2.tar.bz2 //3. Configuration items ./configure --disable-x86asm
Create the compilation script build in the FFmpeg 4.2.2 decompression directory_ android_ arm64-v8a_ clang. sh:
#!/bin/bash export NDK=/root/workspace/android-ndk-r20b #Configure your NDK path here first 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
Compile 64 bit dynamic library and static library of FFmpeg Android platform:
# Modify build_android_arm64-v8a_clang.sh executable permissions chmod +x build_android_arm64-v8a_clang.sh # Run compiled script ./build_android_arm64-v8a_clang.sh
After successful compilation, the static library and dynamic library corresponding to the six modules will be generated in the android directory.
In addition, if you want to compile into 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 "
FFmpeg integration
Based on the FFmpeg static library compiled in the previous section, we conduct a simple integration test on Android Studio.
As shown in the figure above, we can place the static libraries and header files of each module of FFmpeg in the specified directory to achieve a jni to obtain the version information of each module.
#include <cstdio> #include <cstring> #include "util/LogUtil.h" #include "jni.h" //Since the FFmpeg library is implemented in C language, tell 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
Calling logic of Java layer:
package com.byteflow.learnffmpeg.media; public class FFMediaPlayer { static { System.loadLibrary("learn-ffmpeg"); } public static String GetFFmpegVersion() { return native_GetFFmpegVersion(); } private static native String native_GetFFmpegVersion(); } 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()); } }
CMakeLists.txt build script:
# Sets the minimum version of CMake required to build the native library. cmake_minimum_required(VERSION 3.4.1) 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} )
After compilation, run App to obtain the version and compilation configuration information of each module of FFmpeg.
reference resources
https://blog.csdn.net/leixiaohua1020
https://juejin.im/post/5e1eace16fb9a02fec66474e
Contact and communication
Technical exchange to obtain the source code, you can scan the code and add my wechat: byte flow