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

标签 android ffmpeg android-ndk java-native-interface

我为所有 android 架构构建了 ffmpeg 库。但是有些细节让我很困惑。首先让我一步一步解释我是如何构建的。

  • 我下载了最新版本的libx264
    https://www.videolan.org/developers/x264.html
  • 创建并运行 build_all.sh用于为(几乎)所有 android 平台创建库的脚本(在 x264 文件夹中)。然后我得到了android x264 文件夹中的文件夹。例如 android/arm android/arm64 android/x86 android/x86_64在 x264 文件夹中。
  • 我下载了ffmpeg3.3.4来自 https://ffmpeg.org/download.html
  • 我创建了 ffmpeg3.3.4 的 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
    
  • 全部移动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与 ffmpeg 文件夹处于同一层次结构的文件夹
    在 ( C:\Users\MyName\AppData\Local\Android\sdk\ndk-bundle )
  • 运行每个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)
    
  • 创建“ ARM 命名”文件夹,例如 x86 x86_4 arm64 arm7在我项目的 jni 文件夹中( myproject/app/jni/x86myproject/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
    
  • 在我的项目中创建了 Application.mk 文件。
    APP_ABI := armeabi-v7a, arm64-v8a, x86_64, x86
    APP_PLATFORM := android-14
    
  • 创建 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;
    }
    

    在 android 上运行的 FFmpeg 命令,在 emulator 上运行速度非常快,但在真实设备上运行速度非常慢。

    另一个让我困惑的事情是 ./configure 的输出。命令。
    当我打开(例如)ffmpeg-3.3.4-arm64-v8a文件夹并运行 ./configure终端中的命令。输出显示 ARCH x86 (generic) .所有平台的输出都相同ARCH x86 (generic) .

    ./configure 的输出ffmpeg-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
    

    编辑 在 ubuntu 上进行的所有这些步骤然后将所有文件夹移动到 Windows。所以不要混淆路径。

    对于所有这些步骤,我想问的是,我的步骤有什么问题吗?我应该遵循其他方式吗?为什么 ffmpeg 在真实设备上运行速度较慢。我很想知道一件事,retrica、snapchat、instagram 如何将视频录制为镜像翻转?他们是在录制后翻转(如果他们在一秒钟内如何做到这一点)还是在录制运行时翻转的视频?我想为 android 构建 ffmpeg 有点乱,而且做错事很容易。如果您查看我的步骤,问题并给我建议,我将不胜感激。

    最佳答案

    ARCH                      x86 (generic)
    

    那肯定是错的,应该列出具体的架构。

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

    关于android - 正确构建适用于所有 Android 架构的 FFmpeg,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46871831/

    相关文章:

    android - Flutter SetState 不更新文本

    Android的cardView + RecyclerView布局中的滚动功能

    android - 如何让编译器等待OnCompleteListener Kotlin

    ffmpeg 提示参数不正确

    ffmpeg - 更改默认 h264 配置文件

    visual-studio-2010 - 为Android编译C++项目时权限被拒绝

    android - 将 unsigned char* 转换为 const char* - Android

    Android 联系人选择器 : pick phone or email

    java ffmpeg 包装器未知解码器 'copy'

    android - 在没有渲染器的情况下使用 C 在 Android 上开发 OpenGL