Правильно постройте структуру FFmpeg для всех Android

Я построил библиотеки ffmpeg для всей архитектуры Android. Но некоторые детали путают мой разум. Прежде всего позвольте мне объяснить шаг за шагом, как я построил.

  • Я загрузил последнюю версию libx264 из https://www.videolan.org/developers/x264.html
  • Создал и запустил build_all.sh script (в папке x264) для создания libs для (почти) всех платформ Android. Затем я получил папку android в папке x264. например, android/arm android/arm64 android/x86 android/x86_64 в папке x264.
  • Загружаю ffmpeg3.3.4 из https://ffmpeg.org/download.html
  • Я создал 4 копии папки ffmpeg3.3.4. Назвали их именами андроидных архитектур. Как ffmpeg3.3.4-arm64 ffmpeg3.3.4-arm ffmpeg3.3.4-x86 ffmpeg3.3.4-x86_64
  • Создано build_ (имя-архитектуры).sh для каждой платформы android. Затем переместите каждый из '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 in (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)
    
  • Создайте папки с именем "рука", например 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
    
  • Создал файл Application.mk в моем проекте.

    APP_ABI := armeabi-v7a, arm64-v8a, x86_64, x86
    APP_PLATFORM := android-14
    
  • Создан videoEdit.c, чем выполнить команду ndk-build 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;
}

Команды FFmpeg, которые работают на android, работают очень быстро на эмуляторе, но очень медленны на реальном устройстве.

Еще одна вещь, которая меня путает, - вывести команду ./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

EDIT все эти шаги, сделанные на ubuntu, затем переместили все папки в окна. Поэтому не путайте пути.

Со всеми этими шагами я хочу спросить, есть ли что-то не так на моих шагах. Должен ли я следовать другим способом или нет? Почему ffmpeg работает медленнее на реальном устройстве. Мне интересно что-то плохое, как retrica, snapchat, instagram записывать видео как зеркальное отражение? Перебрасываются ли они после записи (если они так делают это за секунду), или они записывают видео как перевернутое во время выполнения? Я думаю, что построение ffmpeg для android немного беспорядочно, и делать неправильные вещи очень легко. Если вы посмотрите мои шаги, вопросы и дайте мне совет, я буду очень благодарен.

Ответ 1

ARCH                      x86 (generic)

Это определенно неправильно, это должно быть перечисление конкретной архитектуры.

Я думаю, https://github.com/IljaKosynkin/FFmpeg-Development-Kit поможет вам, я смог правильно построить все архитектуры с первой попытки. Вы используете командную строку ffmpeg, поэтому вам нужно включить программу.