NDK R20編譯Ffmpeg集成Android命令

本次編譯環境爲windows,linux和mac大同小異(windows都異類了,其他環境編譯沒啥問題)
下載好MINGW,咋個配置的,百度吧,忘了。

下載好NDK文件,我是R20版本的;在從ffmpeg的官方下載源碼,版本4.2.2

腳本編譯

ffmpeg從四點幾開始的不想了解了,就已經默認對android編譯進行了設置。
在這裏插入圖片描述
也默認開啓了clang編譯
在這裏插入圖片描述

所以只需要寫個編譯腳本就van事了。

#!/bin/bash
export TMPDIR=`dirname $0`/tmpdir
NDK=D:/technology/android-ndk-r20
API=16
# arm aarch64 i686 x86_64
ARCH=arm
# armv7a aarch64 i686 x86_64
PLATFORM=armv7a
TARGET=$PLATFORM-linux-androideabi
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/windows-x86_64/bin
SYSROOT=$NDK/sysroot
PREFIX=`dirname $0`/Android/$PLATFORM
 
CFLAG="-D__ANDROID_API__=$API -U_FILE_OFFSET_BITS -DBIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD -Os -fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm"
 
mkdir -p $TMPDIR
 
build_one()
{
./configure \
--ln_s="cp -rf" \
--prefix=$PREFIX \
--cc=$TOOLCHAIN/$TARGET$API-clang \
--cxx=$TOOLCHAIN/$TARGET$API-clang++ \
--ld=$TOOLCHAIN/$TARGET$API-clang \
--target-os=android \
--arch=$ARCH \
--cpu=$PLATFORM \
--cross-prefix=$TOOLCHAIN/$ARCH-linux-androideabi- \
--enable-cross-compile \
--enable-shared \
--disable-static \
--enable-runtime-cpudetect \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-doc \
--disable-symver \
--enable-small \
--enable-gpl --enable-nonfree --enable-version3 --disable-iconv --enable-neon --enable-hwaccels \
--enable-jni \
--enable-mediacodec \
--enable-avdevice  \
--disable-decoders --enable-decoder=vp9 --enable-decoder=h264 --enable-decoder=mpeg4 --enable-decoder=aac --enable-decoder=h264_mediacodec \
--disable-postproc \
--extra-cflags="$CFLAG" \
--extra-ldflags="-marm"
}
 
build_one
 
make clean
 
make -j4
 
make install

針對配置開開關關的到處打log看爲什麼錯誤。哎。最終這個配置能使用。
編譯結束後會直接有文件Android的生成,需要的動態庫和文件都在這裏面

PS:以上配置要用64位的需要重新編寫文件路徑(換成自己的就好了)

Android集成

將剛剛編譯好的包以及頭文件進行移動
在這裏插入圖片描述
整個最後的文件類似於這種,你也可以按照自己的喜好來,ffmpeg.c這個是爲了執行ffmpeg的各種命令
從之前的源碼包裏,在fftools這個文件夾裏能夠找到各個文件,然後導入進來
build.gradle的配置

    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt" //改成自己的路徑
        }
    }

編寫CMakaList.txt內容,可摘。

# 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(
        ${CMAKE_SOURCE_DIR}/include/
        ${CMAKE_SOURCE_DIR}/
        D:/technology/ffmpeg-422
)
#定義全局 my_source_path 變量
file(GLOB my_source_path
        ${CMAKE_SOURCE_DIR}/*.cpp
        ${CMAKE_SOURCE_DIR}/*.c
        )
# Creates and names a library, sets it as either STATICw
# 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).
        ${my_source_path})

add_library(avcodec SHARED IMPORTED)
add_library(avdevice SHARED IMPORTED)
add_library(avfilter SHARED IMPORTED)
add_library(avformat SHARED IMPORTED)
add_library(avutil SHARED IMPORTED)
add_library(swresample SHARED IMPORTED)
add_library(swscale SHARED IMPORTED)
#add_library(postproc SHARED IMPORTED)

set_target_properties(avcodec PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavcodec.so)
set_target_properties(avdevice PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavdevice.so)
set_target_properties(avfilter PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavfilter.so)
set_target_properties(avformat PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavformat.so)
set_target_properties(avutil PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavutil.so)
set_target_properties(swresample PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libswresample.so)
set_target_properties(swscale PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libswscale.so)
#set_target_properties(postproc PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libpostproc.so)

# 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
        avcodec
        avdevice
        avfilter
        avformat
        avutil
        swresample
        swscale
#        postproc
        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

接着需要改動一些東西,方法名隨意
ffmpeg.c裏的int main()改爲int ffmpeg_exec()
在該函數的末尾添加:

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

註釋掉exit_program()方法,可註釋掉該函數內的所有這個方法,不過注意一下if的作用域

//    exit_program(received_nb_signals ? 255 : main_return_code); // 退出程序,不過以報錯的形式

接着在ffmpeg.h頭文件裏,對方法進行添加
int ffmpeg_exec(int argc, char **argv);

然後按照JNI的方式調用方法進行命令行的執行
native-lib.cpp

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

extern "C" {
#include "ffmpeg.h"

JNIEXPORT jint JNICALL
Java_cn_krisez_vvv_FFmpegUtil_exec(JNIEnv *env, jclass, jobjectArray cmd) {
    int leng = env->GetArrayLength(cmd);
    char *argv[leng];
    for (int i = 0; i < leng; ++i) {
        argv[i] = (char*) env->GetStringUTFChars((jstring) env->GetObjectArrayElement(cmd, i), nullptr);
    }
    return ffmpeg_exec(leng,argv);
}
}

Java層:

public class FFmpegUtil {
    static {
        System.loadLibrary("avcodec");
        System.loadLibrary("avdevice");
        System.loadLibrary("avfilter");
        System.loadLibrary("avformat");
        System.loadLibrary("avutil");
        System.loadLibrary("swresample");
        System.loadLibrary("swscale");
//        System.loadLibrary("postproc");
        System.loadLibrary("native-lib");
    }
    public static native String stringFromJNI();
    public static native int exec(String[] cmd);
}

執行的時候直接調用FFmpegUtil.exec();

tv.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                String out = Environment.getExternalStorageDirectory() + "/" + System.currentTimeMillis() + ".mp4";
                //以數組的方式傳遞參數
                tv.setText("a  "+FFmpegUtil.exec(new String[]{
                        "ffmpeg",
                        "-i",
                        Environment.getExternalStorageDirectory()+"/ysgs.mp4",
                        "-ss","14",
                        "-c","copy","-t","10",
                        out
                }));
            }
        }).run();
    }
});

如此將ffmpeg的命令調用方式編譯進了Android
倉庫自取:Github

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章