[✔️]ffmpeg Android 打包

362 阅读2分钟

一个jni调用ffmpeg的demo

The LOCAL_SRC_FILES for a prebuilt library should only contain one item

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := cocos_crypto_static
LOCAL_MODULE_FILENAME := crypto
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libcrypto.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../include/android
include $(PREBUILT_STATIC_LIBRARY)

LOCAL_MODULE := cocos_ssl_static
LOCAL_MODULE_FILENAME := ssl
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libssl.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../include/android
include $(PREBUILT_STATIC_LIBRARY)

CPU架构

1、armeabi-v7a:  第7代及以上的 32位ARM 处理器

2、arm64-v8a: 第8代、64位ARM处理器

3、armeabi: 第5代、第6代的32位ARM处理器,早期的手机在使用,现在基本很少了。

4、x86:  Intel 32位处理器,在平板、模拟器用得比较多。

5、x86_64: Intel 64位处理器,在平板、模拟器用得比较多。

ABI三元组
armeabi-v7aarmv7a-linux-androideabi
arm64-v8aaarch64-linux-android
x86i686-linux-android
x86-64x86_64-linux-android
NDK 操作系统变体主机标记
macOSdarwin-x86_64
Linuxlinux-x86_64
64 位 Windowswindows-x86_64

AArch64是ARMv8的一种执行状态。

若要使用 API 级别 21 的 minSdkVersion 针对 64 位 ARM Android 进行编译,可使用以下两种方法,您可以选择其中最方便的一种:

$ $NDK/toolchains/llvm/prebuilt/$HOST_TAG/bin/clang++ \
    -target aarch64-linux-android21 foo.cpp
$ $NDK/toolchains/llvm/prebuilt/$HOST_TAG/bin/aarch64-linux-android21-clang++ \
    foo.cpp

正确的写法是 

#32bit  
ARCH=arm  
CPU=armv7-a  

#64bit  
ARCH=arm64  
CPU=armv8-a
 Error while executing process
F:\android-ndk-r15c\ndk-build.cmd with arguments 
{
  NDK_PROJECT_PATH=null 
  APP_BUILD_SCRIPT=E:\proj\tank5\client\frameworks\runtime-src\proj.android-studio\app\jni\Android.mk 
  NDK_APPLICATION_MK=E:\proj\tank5\client\frameworks\runtime-src\proj.android-studio\app\jni\Application.mk 
  APP_ABI=armeabi 
  NDK_ALL_ABIS=armeabi 
  NDK_DEBUG=0 
  APP_PLATFORM=android-14 
  NDK_OUT=E:/proj/tank5/client/frameworks/runtime-src/proj.android-studio/app/build/intermediates/ndkBuild/release/obj 
  NDK_LIBS_OUT=E:\proj\tank5\client\frameworks\runtime-src\proj.android-studio\app\build\intermediates\ndkBuild\release\lib 
  NDK_TOOLCHAIN_VERSION=4.9 
  APP_PLATFORM=android-10 
  NDK_MODULE_PATH=
    E:/proj/tank5/client/frameworks/runtime-src/Classes;
    E:/proj/tank5/client/frameworks/cocos2d-x;
    E:/proj/tank5/client/frameworks/cocos2d-x/cocos;
    E:/proj/tank5/client/frameworks/cocos2d-x/external 
  NDK_DEBUG=0 clean
}
  
Android NDK: android-10 is unsupported. Using minimum supported version android-14.
Android NDK: WARNING: Ignoring unknown import directory: my_relative_path
Android NDK: ERROR:E:/proj/tank5/client/frameworks/cocos2d-x/external/ffmpeg/prebuilt/android/Android.mk:cocos_ffmpeg_libavcodec: LOCAL_SRC_FILES points to a missing file
Android NDK: Check that E:/proj/tank5/client/frameworks/cocos2d-x/external/ffmpeg/prebuilt/android/armeabi/libavcodec.a exists  or that its path is correct
F:/android-ndk-r15c/build//../build/core/prebuilt-library.mk:45: *** Android NDK: Aborting    .  Stop.

ninja: error:xxx, needed by xxx, missing and no known rule to make it

ninja: error: '/XXX/NDKApplication/app/src/main/cpp/src/main/cpp/armeabi-v7a/libavcodec.so',

needed by '/XXX/NDKApplication/app/build/intermediates/cmake/debug/obj/armeabi-v7a/libhf_code.so', missing and no known rule to make it

检查IMPORTED_LOCATION,底层不会自动补全lib,所以必须是存在的值

set_target_properties(${lib} PROPERTIES
        IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/lib${lib}.so
        #                                            ↑ 底层不会补全这个lib  
)

ndk build android.mk添加外部so

  • jni/Android.mk
LOCAL_SHARED_LIBRARIES += cocos_ffmpeg_libavformat
# ...
$(call import-add-path,$(LOCAL_PATH)) # 模块查找路径
$(call import-module,ffmpeg/)
  • ffmpeg/Android.mk
include $(CLEAR_VARS)
LOCAL_MODULE := cocos_ffmpeg_libavformat
LOCAL_MODULE_FILENAME := libavformat                 # 注意这个名字,要和下边的对应
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libavformat.so # 注意这个名字,要和上边的对应
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../include
include $(PREBUILT_SHARED_LIBRARY)

最终apk包里面会有这个文件: apk/lib/arm64-v8a/libavformat.so

Execution failed for task: externalNativeBuildDebug FAILED

有可能是编译so的ndk版本高于了项目使用的ndk版本

project ndk version >= so ndk version

ndk Unexpected native build target Valid values are:

so库有问题

externalNativeBuild {
    ndkBuild {
        if (!project.hasProperty("PROP_NDK_MODE") || PROP_NDK_MODE.compareTo('none') != 0) {
            // skip the NDK Build step if PROP_NDK_MODE is none
            targets 'cocos2dlua'
            arguments 'NDK_TOOLCHAIN_VERSION=4.9'
            arguments 'APP_PLATFORM=android-' + PROP_APP_PLATFORM

            def module_paths = [project.file("../../Classes").absolutePath,
                                project.file("../../../cocos2d-x").absolutePath,
                                project.file("../../../cocos2d-x/cocos").absolutePath,
                                project.file("../../../cocos2d-x/external").absolutePath]
            if (Os.isFamily(Os.FAMILY_WINDOWS)) {
                // should use '/'
                module_paths = module_paths.collect { it.replaceAll('\\', '/') }
                arguments 'NDK_MODULE_PATH=' + module_paths.join(";")
            } else {
                arguments 'NDK_MODULE_PATH=' + module_paths.join(':')
            }

            arguments '-j' + Runtime.runtime.availableProcessors()
            abiFilters.addAll(PROP_APP_ABI.split(':').collect { it as String })
        }
    }
}
  • gradlew.properties
PROP_APP_ABI=armeabi:armeabi-v7a:arm64-v8a

如果PROP_APP_ABI缺失arm64-v8a就会被过滤掉,build.gradle里面abiFilter就是写了arm64-v8a也没用,项目配置的一个大坑!