Using FFMPEG in Android

1. JNI

First create an Android project that supports C++:

File->New->New Project->Phone and Tablet->Native C++ ->Then select the C++ version. If you don’t know the C++ versions, you can choose Toolchain Default. Click Finished. Finish creating.

After the creation is complete, we switch the view from Android to project. Compared with ordinary Android projects, there are two more folders here. One is the .cxx directory under the app directory. One is the src/main/cpp directory. The .cxx folder is a temporary file during our c compilation process. Look at the cpp directory again, there are two files here, one is CMakeLists.txt. This file is where we need to write all the C++ library files that we need to put into the project. The native-lib.cpp file is a transit method for C++ and JAVA to call each other. Quite a feeling of JS Bridge in cross-platform Android. We can look at the example method created for us in the system:

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

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_wfffmpeg_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

Here is an example created automatically by the system. We only need to follow this to write our own files. Note the format of the method name here:

Java_com_example_wfffmpeg_MainActivity_stringFromJNI

That is, stringFromJNI of MainActivity under the java.com.example.wfffmpeg package. Simply put, it is to locate a file through the naming rules. Because the method name cannot appear with a dot., the method name uses an underscore _ to replace the . in the package name

Then let's take a look at how to communicate with this method in MainActivity.java:

package com.example.wfffmpeg;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();
}

Look at this file, this is a normal Activity. In the static static area, use System.loadLibrary("native-lib") to import the nativie-lib library file, which is the bridge file we wrote above. That is to say, it is introduced when the Activity is just started. Next comes the declaration of the method. Note that the declaration here has a prefix native. The complete declaration is public native String stringFromJNI(); and in this Activity we can use this method to directly call stringFromJNI();

Now. We have seen how to use JNI. So let's take a look at FFMPEG as a C++ library, how do we use it in Android:

1. In the previous article, we compiled FFMPEG and generated some library files. Now we need to copy these library files to the project. First, we copy all the include folders into the libs folder.

There are several folders under the include folder:

1.libavcodec encoding/decoding

2.libavdevice multiplexing/demultiplexing library dedicated device (reading device)

3. libavfilter frame-based editing library map (plus special effects)

4.libavformat I/O multiplexing/demultiplexing library

5. libavutil common utility library

6. libpostproc post-processing library

7. libswresample audio resampling, format conversion and mixing

8. libswscale color conversion and scaling library (image stretching, pixel format conversion)

Next, under the libs folder, create a new armeabi folder. then put

libavcodec-57.so、libavdevice-57.so、libavfilter-6.so、libavformat-57.so、libavutil-55.so、libpostproc-54.so、libswresample-2.so libswscale-4.so

These 8 files are copied into the armeabi folder, and the copied project file structure directory is:

2. In the above paragraph, we said about the CMakeLists.txt file. It is to write the C++ library file that our project depends on. So we need to write relevant information in this file:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)
include_directories(libs/include)
set(DIR ../../../../libs)

project("wfffmpeg")


add_library(avcodec-57
        SHARED
        IMPORTED)
set_target_properties(avcodec-57
        PROPERTIES IMPORTED_LOCATION
        ${DIR}/armeabi/libavcodec-57.so)

add_library(avdevice-57
        SHARED
        IMPORTED)
set_target_properties(avdevice-57
        PROPERTIES IMPORTED_LOCATION
        ${DIR}/armeabi/libavdevice-57.so)

add_library(avformat-57
        SHARED
        IMPORTED)
set_target_properties(avformat-57
        PROPERTIES IMPORTED_LOCATION
        ${DIR}/armeabi/libavformat-57.so)

add_library(avutil-55
        SHARED
        IMPORTED)
set_target_properties(avutil-55
        PROPERTIES IMPORTED_LOCATION
        ${DIR}/armeabi/libavutil-55.so)

add_library(postproc-54
        SHARED
        IMPORTED)
set_target_properties(postproc-54
        PROPERTIES IMPORTED_LOCATION
        ${DIR}/armeabi/libpostproc-54.so)

add_library(swresample-2
        SHARED
        IMPORTED)
set_target_properties(swresample-2
        PROPERTIES IMPORTED_LOCATION
        ${DIR}/armeabi/libswresample-2.so)

add_library(swscale-4
        SHARED
        IMPORTED)
set_target_properties(swscale-4
        PROPERTIES IMPORTED_LOCATION
        ${DIR}/armeabi/libswscale-4.so)

add_library(avfilter-6
        SHARED
        IMPORTED)
set_target_properties(avfilter-6
        PROPERTIES IMPORTED_LOCATION
        ${DIR}/armeabi/libavfilter-6.so)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        native-lib
        avfilter-6
        avcodec-57
        avdevice-57
        avformat-57
        avutil-55
        postproc-54
        swresample-2
        swscale-4
        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

3. Modify the app build.gradle file

Add to the defaultConfig file:

defaultConfig{
      /...
  externalNativeBuild {
              cmake {
                  cppFlags "-frtti -fexceptions"
              }
        }
   ndk {
              //选择要添加的对应cpu类型的.so库。
              abiFilters 'armeabi-v7a'
              // 还可以添加 'x86', 'x86_64', 'mips', 'mips64'
        }
}

4. compile

Build -> clean project -> Refresh Linked C++ Projects

Then connect the mobile phone, run for a while, and try whether this function can be called. If there is a problem, you can check the following aspects:

1. Check whether the code configuration in CMakeLists.txt is correct.

2. Check whether the so library in CMakeLists.txt is consistent.

3. Check whether target_link_libraries() is missing in CMakeLists.txt

4. Check whether the configuration in the build.gradle file is correct.

5. Try to change the SDK version in Project Structure.

We will learn the specific functions of FFMPEG later.

Good luck to all my colleagues!

 

Guess you like

Origin blog.csdn.net/howlaa/article/details/112824965#comments_23883841