This come from my github readmejava
使用jni調用ffmpeg編譯生成的動態庫.so
,編入apkandroid
jni的實現上使用直接傳遞ffmpeg command的方式,重寫了ffmpeg.c
的main()
接口,只須要傳入合適的ffmpeg命令便可使用c++
獲取手機cpu平臺git
adb shell cat /proc/cpuinfo
個人手機是aarch64,即arm64-v8a,因此動態庫應該放置在$Project/app/src/main/jniLibs/arm64-v8a
,可是我嘗試沒有成功github
好在是兼容32位的,因此能夠編譯支持arm的庫,動態庫放置在$Project/app/src/main/jniLibs/armeabi
,爲了兼容32位,就不能有arm64-v8a目錄的存在shell
編寫FFmpegNativeHelper.java
app
package com.muqing.android.ffmpeg_jni_example; public class FFmpegNativeHelper { public FFmpegNativeHelper() { } static { System.loadLibrary("..."); } public int ffmpegCommand(String comand) { if (comand.isEmpty()) { return 1; } String args[] = comand.split(" "); for (int i = 0; i < args.length; i++) { Log.d("ffmpeg-jni", args[i]); } return ffmpeg_entry(args.length, args); } public native int ffmpeg_entry(int argc, String[] args); }
生成jni cpp headerpost
cd $Project/app/src/main/java javah -jni com.muqing.android.ffmpeg_jni_example.FFmpegNativeHelper
在該目錄下生成com_muqing_android_ffmpeg_jni_example_FFmpegNativeHelper.h
,聲明瞭ffmpeg_entry
拷貝到$Project/app/src/main/java/jni
目錄下gradle
新建com_muqing_android_ffmpeg_example_FFmegNativeHelper.c
,以下ui
#include "com_muqing_android_ffmpeg_jni_example_FFmpegNativeHelper.h" # this method change the main() in ffmpeg.c JNIEXPORT jint JNICALL Java_com_muqing_android_ffmpeg_1jni_1example_FFmpegNativeHelper_ffmpeg_1entry (JNIEnv * env, jobject thiz, jint argCount, jobjectArray strArray) { }
拷貝prebuilt shared libray
從個人另外一個項目ffmpeg-for-android-shared-library中生成的include
和lib
分別拷貝到$PROJECT/app/src/main/jni/include
和$PROJECT/app/src/main/jni/prebuilt
目錄下
由於com_muqing_android_ffmpeg_example_jni_example_FFmpegNativeHelper.c
只修改了ffmpeg.c
, 因此爲了編譯經過,須要添加如下文件
include/compat/va_copy.h libavcodec/arm/mathops.h OR libavutil/x86/mathops.h libavcodec/mathops.h libavresample/avresample.h libavresample/version.h libavutil/x86/asm.h libavutil/libm.h libpostproc/postprocess.h libpostproc/version.h
這些文件能夠從ffmpeg源碼中拷貝以後加以修改
編寫Android.mk
由於是fork了別人的項目,原始項目支持arm,x86平臺,因此它的mk文件是這樣的
ifeq ($(APP_ABI), x86) include Android.x86.mk else ifeq ($(APP_ABI), arm64-v8a) include Android.arm64-v8a.mk else include Android.arm.mk endif
根據Application.mk
來判斷
# APP_ABI := arm64-v8a APP_ABI := armeabi
下面,咱們看看Android.arm.mk
首先,LOCAL_PATH := $(call my-dir)
接着,報杭shared library的module nam和位置,以下
include $(CLEAR_VARS) LOCAL_MODULE:= avcodec-prebuilt-armeabi LOCAL_SRC_FILES:= prebuilt/libavcodec.so include $(PREBUILT_SHARED_LIBRARY)
而後,指定將要生成的module name,此處是
LOCAL_MODULE := libffmpegjni
緊接着,包含了須要編譯的src文件,不須要包含頭文件
LOCAL_SRC_FILES := com_muqing_android_ffmpeg_jni_example_FFmpegNativeHelper.c \ cmdutils.c \ ffmpeg_opt.c \ ffmpeg_filter.c
在接着,LOCAL_SHARED_LIBRARIES
最後,包含include頭文件
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
ndk-build ndk-build clean # if needed, clean the cache, then rebuild
在$Project/app/src/main/java/jni
下生成libs.armeabi
和obj.local.armeabi
拷貝libs.armeabi
目錄下文件到$Project/app/src/main/jniLibs/armeabi
如今須要補全以前FFmpegNativeHelper.java
中的lib庫
public class FFmpegNativeHelper { public FFmpegNativeHelper() { } static { System.loadLibrary("avcodec"); System.loadLibrary("avdevice"); System.loadLibrary("avfilter"); System.loadLibrary("avformat"); System.loadLibrary("avutil"); System.loadLibrary("ffmpegjni"); System.loadLibrary("swresample"); System.loadLibrary("swscale"); } public int ffmpegCommand(String comand) { if (comand.isEmpty()) { return 1; } String args[] = comand.split(" "); for (int i = 0; i < args.length; i++) { Log.d("ffmpeg-jni", args[i]); } return ffmpeg_entry(args.length, args); } public native int ffmpeg_entry(int argc, String[] args); }
在MainActivity.java
中
Sring ffmpegCommand = "ffmpeg --version";> new FFmpegNativeHelper().ffmpegCommand(ffmpegCommand);
使用gradle把Android.mk集成到Android Studio
在$PROJECT/app/src/main/jni/
下添加c/c++文件便可
配置NDK