正确构建适用于所有Android架构的FFmpeg

fth*_*ins 13 java-native-interface android ffmpeg android-ndk

我为所有Android架构构建了ffmpeg库.但是有些细节令我困惑.首先让我逐步解释我是如何建立的.

  • libx264https://www.videolan.org/developers/x264.html下载了最新版本
  • 创建并运行build_all.sh脚本(在x264文件夹中),用于(几乎)所有Android平台创建库.然后我android在x264文件夹中找到了文件夹.例如android/arm android/arm64 android/x86 android/x86_64在x264文件夹中.
  • ffmpeg3.3.4https://ffmpeg.org/download.html下载
  • 我创建了4个ffmpeg3.3.4文件夹副本.用android架构名称命名它们.喜欢ffmpeg3.3.4-arm64 ffmpeg3.3.4-arm ffmpeg3.3.4-x86 ffmpeg3.3.4-x86_64
  • 为android的每个平台创建了build_(architecture-name).sh.然后'named'.sh files根据其架构名称将每个文件移动到指定的ffmpeg文件夹.例如build_android_x86.sh=>ffmpeg3.3.4-x86

build_android_arm64.sh

#!/bin/bash
#Change NDK to your Android NDK location
NDK=$HOME/Android/Sdk/ndk-bundle
PLATFORM=$NDK/platforms/android-21/arch-arm64/
PREBUILT=$NDK/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64

GENERAL="\
--enable-small \
--enable-cross-compile \
--extra-libs="-lgcc" \
--arch=aarch64 \
--cc=$PREBUILT/bin/aarch64-linux-android-gcc \
--cross-prefix=$PREBUILT/bin/aarch64-linux-android- \
--nm=$PREBUILT/bin/aarch64-linux-android-nm \
--extra-cflags="-I../x264/android/arm64/include" \
--extra-ldflags="-L../x264/android/arm64/lib" "

MODULES="\
--enable-gpl \
--enable-libx264"



function build_arm64
{
  ./configure \
  --logfile=conflog.txt \
  --target-os=linux \
  --prefix=./android/arm64-v8a \
  ${GENERAL} \
  --sysroot=$PLATFORM \
  --extra-cflags="" \
  --extra-ldflags="-lx264 -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib -lc -lm -ldl -llog" \
  --enable-shared \
  --disable-static \
  --disable-doc \
  --enable-zlib \
  ${MODULES}

  make clean
  make
  make install
}

build_arm64


echo Android ARM64 builds finished
Run Code Online (Sandbox Code Playgroud)
  • 将所有ffmpeg3.3.4-arm64 ffmpeg3.3.4-arm ffmpeg3.3.4-x86 ffmpeg3.3.4-x86_64文件夹移动到NDK_PATH(C:\Users\MyName\AppData\Local\Android\sdk\ndk-bundle)
  • x264文件夹放在层次结构的同一级别,并在(C:\Users\MyName\AppData\Local\Android\sdk\ndk-bundle)中使用ffmpeg文件夹
  • 每次运行的build_android_x86.sh,build_android_x86_64.sh在自己的ffmpeg文件夹..脚本,一个接一个.然后我android在ffmpeg文件夹中找到了文件夹.(创建的android文件夹有库文件夹)例如ffmpeg3.3.4-x86/android/x86/(bin,inlude,lib,share)
  • 创建Android.mk的所有文件创建的android文件夹和移动他们中的每一个到Android/armName文件夹.例如Android.mk=>ffmpeg3.3.4-x86/android/x86/

    LOCAL_PATH:= $(call my-dir)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libavcodec
    LOCAL_SRC_FILES:= lib/libavcodec-57.so
    LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
    include $(PREBUILT_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libavformat
    LOCAL_SRC_FILES:= lib/libavformat-57.so
    LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
    include $(PREBUILT_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libswscale
    LOCAL_SRC_FILES:= lib/libswscale-4.so
    LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
    include $(PREBUILT_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libavutil
    LOCAL_SRC_FILES:= lib/libavutil-55.so
    LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
    include $(PREBUILT_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libavfilter
    LOCAL_SRC_FILES:= lib/libavfilter-6.so
    LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
    include $(PREBUILT_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE:= libswresample
    LOCAL_SRC_FILES:= lib/libswresample-2.so
    LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
    include $(PREBUILT_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE := postproc
    LOCAL_SRC_FILES := lib/libpostproc-54.so
    LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
    include $(PREBUILT_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE := avdevice
    LOCAL_SRC_FILES := lib/libavdevice-57.so
    LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
    include $(PREBUILT_SHARED_LIBRARY)
    
    Run Code Online (Sandbox Code Playgroud)
  • 创建"arm named"文件夹,例如x86 x86_4 arm64 arm7在我的项目的jni文件夹中(myproject/app/jni/x86,myproject/app/jni/x86_64).

  • 转到ndk路径逐个打开名为ffmpeg的文件夹,并将ffmpeg.c ffmpeg_filter.c ffmpeg_opt.c cmdutils.c文件从ffmpeg文件夹复制到"arm named"文件夹.例如ffmpeg.c=>myproject/app/jni/x86

  • 在我的项目中创建了Android.mk文件.

    LOCAL_PATH := $(call my-dir)
    #$(warning $(LOCAL_PATH))
    
    include $(CLEAR_VARS)
    LOCAL_MODULE    := videoEdit
    LOCAL_LDLIBS := -llog -ljnigraphics -lz -landroid
    LOCAL_CFLAGS := -Wdeprecated-declarations
    ANDROID_LIB := -landroid
    
    $(info $(TARGET_ARCH_ABI))
    
    ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
        LOCAL_C_INCLUDES:=/Users/MyName/AppData/Local/Android/sdk/ndk-bundle/sources/ffmpeg-3.3.4-armeabi
        LOCAL_SRC_FILES :=  videoEdit.c arm7/ffmpeg.c arm7/ffmpeg_filter.c arm7/ffmpeg_opt.c arm7/cmdutils.c
        LOCAL_CFLAGS += -lx264 -Wl,--no-merge-exidx-entries
    else
    
        ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
                LOCAL_C_INCLUDES:=/Users/MyName/AppData/Local/Android/sdk/ndk-bundle/sources/ffmpeg-3.3.4-arm64-v8a
                LOCAL_SRC_FILES :=  videoEdit.c arm64/ffmpeg.c arm64/ffmpeg_filter.c arm64/ffmpeg_opt.c arm64/cmdutils.c
                LOCAL_CFLAGS += -funwind-tables -Wl,--no-merge-exidx-entries
        else
    
            ifeq ($(TARGET_ARCH_ABI),x86_64)
                   LOCAL_C_INCLUDES:=/Users/MyName/AppData/Local/Android/sdk/ndk-bundle/sources/ffmpeg3.3.4-x86_64
                   LOCAL_SRC_FILES :=  videoEdit.c x86_64/ffmpeg.c x86_64/ffmpeg_filter.c x86_64/ffmpeg_opt.c x86_64/cmdutils.c
            else
                    LOCAL_C_INCLUDES:=/Users/MyName/AppData/Local/Android/sdk/ndk-bundle/sources/ffmpeg3.3.4-x86
                    LOCAL_SRC_FILES :=  videoEdit.c x86/ffmpeg.c x86/ffmpeg_filter.c x86/ffmpeg_opt.c x86/cmdutils.c
            endif
    
        endif
    
    endif
    
    LOCAL_SHARED_LIBRARIES := libavformat libavcodec libswscale libavutil libswresample libavfilter libavdevice libpostproc
    
    include $(BUILD_SHARED_LIBRARY)
    
    ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
    
        $(call import-module,ffmpeg-3.3.4-armeabi/android/armeabi-v7a)
    
    else
    
        ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
                $(call import-module,ffmpeg-3.3.4-arm64-v8a/android/arm64-v8a)
        else
    
            ifeq ($(TARGET_ARCH_ABI),x86_64)
                   $(call import-module,ffmpeg3.3.4-x86_64/android/x86_64)
            else
                $(call import-module,ffmpeg3.3.4-x86/android/i686-diasm)
            endif
    
        endif
    
    endif
    
    Run Code Online (Sandbox Code Playgroud)
  • 在我的项目中创建了Application.mk文件.

    APP_ABI := armeabi-v7a, arm64-v8a, x86_64, x86
    APP_PLATFORM := android-14
    
    Run Code Online (Sandbox Code Playgroud)
  • 创建videoEdit.c而不是运行ndk-build构建命令.

内置没有错误.我可以运行ffmpeg命令,但我认为这需要太多时间.例如,当我尝试运行hflip它时,用15秒翻转视频.

代码示例:

JNIEXPORT jint JNICALL Java_com_name_app_library_VideoEditer_natives_VideoEditer_flipHorizontally
(JNIEnv *env, jclass someclass, jstring inputFile, jstring outFile) {

    int numberOfArgs = 14;

    char** arguments = calloc(numberOfArgs, sizeof(char*));
    const char *in, *out;

    in = (*env)->GetStringUTFChars(env, inputFile, 0);
    out = (*env)->GetStringUTFChars(env, outFile, 0);

    arguments[0] = "ffmpeg";
    arguments[1] = "-i";
    arguments[2] = in;
    arguments[3] = "-c:v";
    arguments[4] = "libx264";
    arguments[5] = "-preset";
    arguments[6] = "ultrafast";
    arguments[7] = "-threads";
    arguments[8] = "5";
    arguments[9] = "-c:a";
    arguments[10] = "copy";
    arguments[11] = "-vf";
    arguments[12] = "hflip";
    arguments[13] = out;

    int i;
    for (i = 0; i < numberOfArgs; i++) {
        log_message(arguments[i]);
    }
    log_message("Printed all");

    main(numberOfArgs, arguments);
    free(arguments);
    (*env)->ReleaseStringUTFChars(env, inputFile, in);
    (*env)->ReleaseStringUTFChars(env, outFile, out);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

FFmpeg在android上运行的命令,在电子邮件上运行速度非常快,但在真实设备上运行速度非常慢.

令我困惑的另一件事是输出./configure命令.当我在终端中打开(例如)ffmpeg-3.3.4-arm64-v8a文件夹并运行./configure命令时.输出说ARCH x86 (generic).对于所有平台输出都是一样的ARCH x86 (generic).

./configureffmpeg-3.3.4-arm64-v8a文件夹中输出命令

install prefix            /usr/local
source path               .
C compiler                gcc
C library                 glibc
ARCH                      x86 (generic)
big-endian                no
runtime cpu detection     yes
yasm                      yes
MMX enabled               yes
MMXEXT enabled            yes
3DNow! enabled            yes
3DNow! extended enabled   yes
SSE enabled               yes
SSSE3 enabled             yes
AESNI enabled             yes
AVX enabled               yes
XOP enabled               yes
FMA3 enabled              yes
FMA4 enabled              yes
i686 features enabled     yes
CMOV is fast              yes
EBX available             yes
EBP available             yes
debug symbols             yes
strip symbols             yes
optimize for size         no
optimizations             yes
static                    yes
shared                    no
postprocessing support    no
network support           yes
threading support         pthreads
safe bitstream reader     yes
texi2html enabled         no
perl enabled              yes
pod2man enabled           yes
makeinfo enabled          no
makeinfo supports HTML    no

External libraries:
iconv            xlib
Run Code Online (Sandbox Code Playgroud)

编辑在ubuntu上执行的所有这些步骤,然后将所有文件夹移动到窗口.所以不要混淆路径.

我想问的所有这些步骤是,我的步骤有什么不对.我应该遵循其他任何方式吗?为什么ffmpeg在真实设备上运行速度较慢.我想知道一件事,如何retrica,snapchat,instagram录制视频作为镜像翻转?它们是否在录制后翻转(如果它们是如何在一秒钟内完成此操作)或者是否在运行时录制视频?我觉得构建ffmpeg for android有点乱,做错事很容易.如果你看看我的步骤,问题并给我一个建议,我将不胜感激.

Ste*_*e M 3

ARCH                      x86 (generic)
Run Code Online (Sandbox Code Playgroud)

那绝对是错误的,它应该列出具体的架构。

我认为https://github.com/IljaKosynkin/FFmpeg-Development-Kit会对您有所帮助,我在第一次尝试时就能够正确构建所有架构。您正在使用命令行 ffmpeg,因此您需要启用该程序。