Я построил библиотеки 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 немного беспорядочно, и делать неправильные вещи очень легко. Если вы посмотрите мои шаги, вопросы и дайте мне совет, я буду очень благодарен.