Android Studio+NDK+Cmake Porting FFmpeg-4.0.2 Command Line Tool

Keywords: Android cmake Vmware SDK

First, compile

Refer to Dashen's post and test the compilation successfully: https://blog.csdn.net/bobcat_kay/article/details/80889398

In view of previous experience in documentation, here is the time for writing examples: 22 July 2018.

I use ubantu. Notes:

1. The path here, home/ndk is wrong, the real path is home/computer name/ndk, specifically based on the cd ls command.

2. Documents must be downloaded in ubantu. The first time I downloaded them in win, and then passed them through VMware. The result was that something went wrong. Then Baidu found the problem and downloaded one directly from ubantu. Then it was OK.

3. When editing these two files, build.sh and confinger, make sure that the format of the text is not doc but unit (the word should be wrong).

Two. Transplantation

The god's post uses mk, but I prefer cmake here.

The process is basically the same, but there are some minor details. Maybe Dashen has deep skills and has not encountered any problems. I have been stuck in this step for most of the night.

1. Create new projects

(1) Environment

        Android Studio 3.2 

        NDK 17.1.4828580

        SDK 28

(2) New projects

Look at the screenshots. The main thing is to tick this thing. Everything else is default.

2. Copy files

(1) copy so file

I created a new folder ffmpeg/armeabi-v7a under the cpp directory, and copied all so packages in.

(2) Copy fftools code

Create a new folder included under the ffmpeg folder, then copy some files in the folder fftools into the include folder, and copy config.h in the outermost layer of the source code.

(3) Copy source code

In line with the principle of killing the wrong, I copied all the folders (except fftools) in the source directory into include. (Referring to God's practice, many files are missing header files, and then have been compiled incorrectly.)

3. Create jni's call class

(1) Java classes

Create FFmpegCmd class

(2) Create class c

Look at the picture above. Direct alt+enter can create related methods. Android Studio is very smart.

Then rename class C ffmpeg_cmd_utils.c

(3) Special description

The reason is that c is not cpp, I am also helpless, if it is cpp, compiling time exploded a lot of warnings, and not compiled, at present, no problem has been found, after all, my level is limited.

4, configuration

(1)build.gradle

Major areas have been marked.

(2) CMakeLists.txt file

The main thing is to load all so packages, and there are ffmpeg_cmd_utils.c and ffmpeg.c and other classes in the fftools folder (not all of them need to be used, if all of them are loaded, they will report some inexplicable errors, depending on the cmake file).

If I remember the steps correctly, I can basically compile through this step, and the next step is to start with the cmd tool.

cmake_minimum_required(VERSION 3.4.1)

add_library( # Sets the name of the library.
             ffmpegcmd

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
              src/main/cpp/ffmpeg/include/cmdutils.c
              src/main/cpp/ffmpeg/include/ffmpeg.c
              src/main/cpp/ffmpeg/include/ffmpeg_filter.c
              src/main/cpp/ffmpeg/include/ffmpeg_hw.c
              src/main/cpp/ffmpeg/include/ffmpeg_opt.c
             src/main/cpp/ffmpeg_cmd_utils.c
              )

#Add libavcodec-57.so
add_library( avcodec
             SHARED
             IMPORTED)
set_target_properties( avcodec
                       PROPERTIES IMPORTED_LOCATION
                       ${CMAKE_SOURCE_DIR}/src/main/cpp/ffmpeg/armeabi-v7a/libavcodec.so)

#Add libavdevice-57.so
add_library( avdevice
             SHARED
             IMPORTED)
set_target_properties( avdevice
                       PROPERTIES IMPORTED_LOCATION
                       ${CMAKE_SOURCE_DIR}/src/main/cpp/ffmpeg/armeabi-v7a/libavdevice.so)

add_library( avfilter
             SHARED
             IMPORTED)
set_target_properties( avfilter
                       PROPERTIES IMPORTED_LOCATION
                       ${CMAKE_SOURCE_DIR}/src/main/cpp/ffmpeg/armeabi-v7a/libavfilter.so)

add_library( avformat
             SHARED
             IMPORTED)
set_target_properties( avformat
                       PROPERTIES IMPORTED_LOCATION
                       ${CMAKE_SOURCE_DIR}/src/main/cpp/ffmpeg/armeabi-v7a/libavformat.so)

add_library( avutil
             SHARED
             IMPORTED)
set_target_properties( avutil
                       PROPERTIES IMPORTED_LOCATION
                       ${CMAKE_SOURCE_DIR}/src/main/cpp/ffmpeg/armeabi-v7a/libavutil.so)

add_library( swresample
             SHARED
             IMPORTED)
set_target_properties( swresample
                       PROPERTIES IMPORTED_LOCATION
                       ${CMAKE_SOURCE_DIR}/src/main/cpp/ffmpeg/armeabi-v7a/libswresample.so)

add_library( swscale
             SHARED
             IMPORTED)
set_target_properties( swscale
                       PROPERTIES IMPORTED_LOCATION
                       ${CMAKE_SOURCE_DIR}/src/main/cpp/ffmpeg/armeabi-v7a/libswscale.so)



include_directories(src/main/cpp/ffmpeg/include)



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 )

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

target_link_libraries( # Specifies the target library.

                       ffmpegcmd
                       avcodec
                       avdevice
                       avfilter
                       avformat
                       avutil
                       swresample
                       swscale

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

5. Modify the code

(1)cmdutils.c

Comment out the exit_program method:

        

(2)cmdutils.h

        void show_help_children(const AVClass *class, int flags);

Change to:

        void show_help_children(const AVClass *clazz, int flags);

(3)ffmpeg.c

The entrance is the main function, renamed, followed by the God ffmpeg_exec

        

Comment out the code at the end of the ffmpeg_exec function:

        

Find the ffmpeg_cleanup function and add:

    nb_filtergraphs = 0;
    nb_output_files = 0;
    nb_output_streams = 0;
    nb_input_files = 0;
    nb_input_streams = 0;

Add the following as follows:

        

The nb_filtergraphs declaration is assigned a value of 0 for insurance purposes.

        

Add at the end of the ffmpeg_exce function, or your phone will explode the second time you run the command line.

    nb_filtergraphs = 0;
    progress_avio = NULL;

    input_streams = NULL;
    nb_input_streams = 0;
    input_files = NULL;
    nb_input_files = 0;

    output_streams = NULL;
    nb_output_streams = 0;
    output_files = NULL;
    nb_output_files = 0;

The following step can be exempted on demand, mainly for printing the output information after the command line runs:

Add a statement:


#include "android/log.h"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG  , "ffmpeg.c", __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR  , "ffmpeg.c", __VA_ARGS__)

Add content to the log_callback_null function:

static void log_callback_null(void *ptr, int level, const char *fmt, va_list vl)
{
    static int print_prefix = 1;
    static int count;
    static char prev[1024];
    char line[1024];
    static int is_atty;

    av_log_format_line(ptr, level, fmt, vl, line, sizeof(line), &print_prefix);

    strcpy(prev, line);
    //sanitize((uint8_t *)line);

    if (level <= AV_LOG_WARNING) {
        LOGE("Output:%s", line);
    } else {
        LOGE("Output:%s", line);
    }
}

(4)ffmpeg.h

Add the function declaration of ffmpeg_exec function at the end

        

(5)ffmpeg_cmd_utils.c

Call code directly

#include <android/log.h>
#include <ffmpeg.h>
#define LOGE(FORMAT,...) __android_log_print(ANDROID_LOG_ERROR,"8858",FORMAT,##__VA_ARGS__);

JNIEXPORT jint JNICALL
Java_com_imxiaoyu_test_FFmpegPlayer_playMyMedia(JNIEnv *env, jobject instance,jint cmdLen,
                                                jobjectArray cmd) {


    int argc = (*env)->GetArrayLength(env, cmd);
    char *argv[argc];
    int i;
    for (i = 0; i < argc; i++) {
        jstring js = (jstring) (*env)->GetObjectArrayElement(env, cmd, i);
        argv[i] = (char*) (*env)->GetStringUTFChars(env, js, 0);
        LOGE("command line argCmd=%s",argv[i]);
    }
    ffmpeg_exec(argc, argv);
    return 1;
}

If you remember correctly, that's ok ay.

6. Call

(1) Authority

The right to read and write the memory of the cell phone must be tucking out. I am a millet 6 in my cell phone. In line with the principle of laziness, after clicking the permission management to app permissions on the application details page, it will not work. If the command line runs, it will crash. It must be the application of the code to be useful. I thought it was a compilation or code problem, at least here. Three or four hours were wasted in one step. I'm not sure if it's MIUI or Android 8.0. Do your best to do your job and not be lazy.

Later, when I ran up, you should all know my mood at that time. You can't laugh or cry with joy.

I won't post the code to apply for permission.

        

(2) Call

 final String cmd[]=str.split(" ");//
        new Thread(){
            @Override
            public void run() {
                PathUtils pathUtils=new PathUtils();
                String str="ffmpeg -i "+pathUtils.getMusicCacheEditorPath()+"/12.mp3 -y "+pathUtils.getMusicCacheEditorPath()+"/haha1.wav";//Specific path, free play
                long startTime = System.currentTimeMillis();
                try {
                    fFmpegPlayer.playMyMedia(cmd.length,cmd);
                }catch (Exception e){
                    Log.e("Wrong:",e.toString());
                }
                Log.e("FFmpegTest", "run: Time consuming:"+(System.currentTimeMillis()-startTime));
            }
        }.start();

(3) Results

(4) Notes

The names of all files on the command line should not be given special characters, such as spaces, newlines, emoji, etc.

I always feel that I have left out nothing to say, no matter what, when I encounter problems, remember that the problems will always be solved if I grow up indecently and keep quiet.

Crap

To be honest, I've been interested in this since ffmpeg 3.0, but I've been stuck in compiling so package. I'm not familiar with linux system, and I can't get the gist. This time, I compiled so package directly according to God's footsteps, once or twice, and I knew it was a good time.

The command-line tools of ffmpeg can actually do a lot of interesting things, I wish you all a happy time.

Posted by MrCool on Thu, 03 Jan 2019 16:21:10 -0800