preface

Based on the WSL function provided by WIN10, you can quickly build a Linux (Unbuntu) development environment. The most important thing is that the files between the two systems can communicate with each other! File interchange! File interchange! Here we will use this capability to compile the link library of FFMPEG (this article uses the static library as an example).

Open the WSL

You need to restart the system for this function to take effect. Please save the data.

Open control panel

Toggle viewing to a small icon to find and open programs and features

Sidebar entry – Enable or disable Windows features

Open the WSL

Find and enable the subsystem

Downloading the Linux OS

Open the Windows App Store, search for Ubuntu, and download and install one of them. I’m using the highest version 20.04 LTS here. After verification, downloading and installing multiple versions at the same time will not cause any adverse effects, and each version runs independently of each other.

Start the ubuntu

Here we find and start Unbuntu. Note: The first boot will require you to create a new user and password. (HERE I have created it, so I will skip it, you can try it yourself)

If the following screen is displayed, the Ubuntu system is running successfully. You can start compiling FFMPEG!

Pay attention to

The file path of the unbuntu system is shown below:

Start compiling FFMEPG

Here we use NDK-R17C + FFMPEG-4.0.5 as the standard for compilation. The reason for choosing R17C is that Google has removed the GCC compiler from the R18 release, so R17C is the highest NDK version of GCC available, as shown below. If you need to compile the latest version of FFMPEG, use a later version of NDK (R18 and above) and use the CLANG compiler. For details, please refer to the link:
1.0-FFMPEG-Android leverages NDK (R20) to compile the latest version of FFMPEG4.2.1

Note:

1. You can paste content into the Unbuntu window by right mouse button. 2. The following junt is the user name created by me! Please replace by yourself! 3. Perform all the following operations as an administrator: a. Sudo-sB. Enter the created password to enter the administrator mode. See the following figure:Copy the code

Download and configure the NDK

Using wget command to download the NDK: wget https://dl.google.com/android/repository/android-ndk-r17c-windows-x86_64.zip using unzip command decompress compressed package:  unzip android-ndk-r17c-linux-x86_64.zipCopy the code

Use the ls command to view the NDK folder after decompression: (there are a few folders here, because I tried different versions of FFmpeg, please ignore for now.)Copy the code

Configure NDK environment variables

Edit profile: Enter the command vim /etc/profile and press insert to go into edit mode. Add the NDK path at the end of the profile, as shown below:Copy the code

Press Esc, type :wq, and press Enter to save the configuration.Copy the code

usingsourceThe command makes an environment variable take effect:source/etc/profile If the following startup message is displayed, the environment variable has taken effect:Copy the code

Verify the ndk-build command, if the project path can not be found, it means that the NDK is running properly:Copy the code

Download ffmpeg

(It is not recommended to use the latest version of FFmpeg if it is used in real projects, especially on 4.2.) Wget https://ffmpeg.org/releases/ffmpeg-4.0.5.tar.bz2 using the tar command to extract the compressed package: the tar - JXVF ffmpeg - 4.0.5. Tar..bz2Copy the code

Use the ls command to view the decompressed FFmpeg folder:Copy the code

Compile FFMPEG

Enter the FFmpeg folder:cdFfmpeg - 4.0.5Copy the code

Build. Sh: vim build. Sh: vim build. Sh: vim build.#! /bin/bash
# Note that the NDk path here needs to be replaced by itself
NDK_ROOT=/home/junt/android-ndk-r17c
The #TOOLCHAIN variable points to the directory where cross-compiled GCC is in the NDK
TOOLCHAIN=$NDK_ROOT/ toolchains/arm - Linux - androideabi - 4.9 / prebuilt/Linux - x86_64 /# FLAGS and INCLUDES variables from engineering. AS the NDK externativeBuild/cmake/debug/armeabi v7a/build. The ninja in the copy, it is important to note address * * * *
FLAGS="-isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security -std=c++11  -O0 -fPIC"
INCLUDES="-isystem $NDK_ROOT/sources/cxx-stl/llvm-libc++/include -isystem $NDK_ROOT/sources/android/support/include -isystem $NDK_ROOT/sources/cxx-stl/llvm-libc++abi/include"

#--prefix: installation directory
#--enable-small: optimize the size
#--disable-programs: Instead of compiling ffmpeg programs (command-line tools), we need static (dynamic) libraries.
#--disable-avdevice: Disables the avdevice module, which is useless in Android
#--disable-encoders: Disable all encoders (just play without encoding)
#--disable-muxers: Disable all multiplexers (wrappers). You don't need to generate files like MP4, so disable
#--disable-filters: Turn off the video filters
#--enable-cross-compile: enable cross-compile (ffmPEG is ** cross-platform **, not all libraries have such a happy option)
GCC = XXX/XXX/XXX - GCC = XXX/XXX/XXX -
#disable-shared enable-static This is the default value.
#--sysroot: 
#--extra-cflags: arguments passed to GCC
#--arch --target-os :
PREFIX=./android/armeabi-v7a
bash ./configure \
	--prefix=$PREFIX \
	--prefix=$PREFIX\ --enable-small \ --disable-programs \ --disable-avdevice \ --disable-encoders \ --disable-muxers \ --disable-filters \  --enable-cross-compile \ --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
	--enable-shared \
	--disable-static \
	--sysroot=$NDK_ROOT/platforms/android-21/arch-arm \
	--extra-cflags="$FLAGS $INCLUDES" \
	--extra-cflags="-isysroot $NDK_ROOT/sysroot"\ --arch=arm \ --target-os= Android make clean make install Press Esc, type :wq, and press Enter to save the configuration. After compiling, the android folder will be generated under ffmpeg. Here we can view the static library file under Windows:Copy the code

For details about how to find FLAGS and INCLUDES, see the following figure. Replace NDK paths by yourself:Copy the code

Import AndroidStudio to run

New native c++ project

Since the above compilation is using version 21, please select the SDK version 21 and uploaded!

Import ffmpeg

Both header files and.a static libraries are required

Edit CMakeLists. TXT

Cmake_minimum_required (VERSION 3.4.1) add_library(native-lib # package all CPP files into so dynamic library(apK decompression can be found in lib directory) SHARED native-lib.cpp ) include_directories(include) set(my_lib_path ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${my_lib_path}") target_link_libraries( native-lib -Wl,--start-group avformat avcodec avutil avfilter swresample swscale -Wl,--end-group z OpenSLES log )Copy the code

To configure the build. Gradle (Module: app)

        externalNativeBuild {
            cmake {
                cppFlags ""
                abiFilters "armeabi-v7a"
            }
        }
        ndk{
            abiFilters "armeabi-v7a"
        }

Copy the code

Validation of ffmpeg

// Modify native-lib. CPP to return ffmpeg version information

#include <jni.h>
#include <string>

extern "C"{
#include <libavutil/avutil.h>
}

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_ffmpegdemo_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    returnenv->NewStringUTF(av_version_info()); } If the effect of running app is as follows, ffMPEG is successfully run:Copy the code

Adapter AndroidQ

    /** * Select a video file */ through the system's default file picker
    public void selectMedia(View view) {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("video/*");
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        startActivityForResult(intent, 99);
    }
    
    /** * get the Uri and do the following conversion */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(data ! =null) {
            try {
                Uri uri = data.getData();
                ParcelFileDescriptor parcelFileDescriptor = getContentResolver().openFileDescriptor(uri, "r");
                int pid = android.os.Process.myPid();
                String path = "/proc/" + pid + "/fd/" + parcelFileDescriptor.dup().getFd();
                
                // pass to the CPP of native layer
                //const char *dataSource = env->GetStringUTFChars(path, 0);
                //avformat_open_input(&avFormatContext, dataSource, 0, &dictionary);
                // Release ReleaseStringUTFChars(data_source_, dataSource);
                
            } catch(Exception e) { e.printStackTrace(); }}}Copy the code