Правильно постройте структуру 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, поэтому вам нужно включить программу.