ffmpeg-jni-example

ffmpeg-jni-example

This come from my github readmejava

  • 使用jni調用ffmpeg編譯生成的動態庫.so,編入apkandroid

  • jni的實現上使用直接傳遞ffmpeg command的方式,重寫了ffmpeg.cmain()接口,只須要傳入合適的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

how to use

Step 1

編寫FFmpegNativeHelper.javaapp

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);
}

Step 2

生成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)
{
}

Step 3

拷貝prebuilt shared libray
從個人另外一個項目ffmpeg-for-android-shared-library中生成的includelib分別拷貝到$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源碼中拷貝以後加以修改

Step 4

編寫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

Step 5

ndk-build 
ndk-build clean     # if needed, clean the cache, then rebuild

Step 6

$Project/app/src/main/java/jni下生成libs.armeabiobj.local.armeabi

拷貝libs.armeabi目錄下文件到$Project/app/src/main/jniLibs/armeabi

Step 7

如今須要補全以前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);
}

Step 8

MainActivity.java

Sring ffmpegCommand = "ffmpeg --version";>
    new FFmpegNativeHelper().ffmpegCommand(ffmpegCommand);

Todo

使用gradle把Android.mk集成到Android Studio

  • $PROJECT/app/src/main/jni/下添加c/c++文件便可

  • 配置NDK

References

本站公眾號
   歡迎關注本站公眾號,獲取更多信息