本次編譯環境爲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