• ffmpeg for android编译全过程与遇到的问题


    编译前准备

    编译环境:Ubuntu16,可自行下载VMWare最新版并百度永久许可证或在服务器上安装Ubuntu

    ffmpeg源码:ffmpeg4.2.2

    NDK下载:Android NDK r21e

    有条件的最好还是在Liunx平台下编译吧,Windows平台下编译坑更多,文章末尾有Github源码可自取

    开始编译

    1.解压NDK,执行 unzip android-ndk-r21e-liunx-x86_64.zip

    如果提示没有unzip,执行此命令安装 sudo apt-get install unzip

    2.解压ffmepg,tar -xvjf ffmpeg-4.2.2.tar.bz2

    3.进入ffmpeg4.2.2目录,修改根目录下的 configure 文件

    搜索 LIB_INSTALL_EXTRA_CMD
     

    1. SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
    2. LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
    3. SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
    4. SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'

    替换为

    1. SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
    2. LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
    3. SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
    4. SLIB_INSTALL_LINKS='$(SLIBNAME)'

    此步骤主要是将so命名为Android通用的so名称

    4.在ffmpeg下创建文件android_build.sh脚本文件,此脚本文件用于配置、执行编译,根据需求进行配置,网上的配置均有不同,以实际需要为准,将以下代码copy到android_build.sh脚本文件中,执行 sudo sh android_build.sh
     

    1. #!/bin/bash
    2. API=21
    3. #arm64 x86 x86_64 <----> aarch64 i686 x86_64
    4. ARCH=arm64
    5. ARCH2=aarch64
    6. PREFIX=../out-ffmpeg/$ARCH
    7. #此处路径替换为当前NDK路径
    8. TOOLCHAIN=/home/jiang/ffmpeg/android-ndk-r21e-linux-x86_64/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64
    9. build()
    10. {
    11. #配置各个文件开关及NDK路径等
    12. ./configure \
    13. --prefix=$PREFIX \
    14. --disable-static \
    15. --enable-shared \
    16. --enable-small \
    17. --enable-gpl \
    18. --disable-doc \
    19. --disable-programs \
    20. --disable-avdevice \
    21. --enable-cross-compile \
    22. --target-os=android \
    23. --arch=$ARCH \
    24. --cc=$TOOLCHAIN/bin/$ARCH2-linux-android$API-clang \
    25. --cross-prefix=$TOOLCHAIN/bin/$ARCH2-linux-android-
    26. #清除上次编译
    27. make clean
    28. make -j4
    29. make install
    30. }
    31. #开始编译
    32. build

    android_build.sh脚本文件自取

    注:如果编译过程中出现错误(一般是在开头会有红色报错),部分需要安装其他库,具体可查阅

    5.编译后会在ffmpeg4.2.2同级目录下生成out-ffmpeg文件,将out-ffmpeg导出到项目中

    Android Studio配置

    1.新建一个C++项目

    • 将编译完成后的include头文件导入到cpp文件中
    • 将编译完成后的lib库文件导入到libs中

    2.配置build.gradle文件

    defaultConfig下增加

    1. externalNativeBuild {
    2. cmake {
    3. cppFlags '-frtti -fexceptions'
    4. abiFilters "arm64-v8a","armeabi-v7a"
    5. }
    6. }

    abiFilters是指定当前项目所支持的CPU架构,一般来说有arm64-v8a(arm64位)、armeabi-v7a(arm32位)足够,大部分手机都是这两种架构之一,要完全兼容可能会导致APP体积增大

    注意:如果你的Gradler版本足够高(大约>5.6.4),无须配置以下项,否则有可能报错
     

    1. sourceSets {
    2. main {
    3. jniLibs.srcDirs = ["libs"]
    4. }
    5. }

    【免费分享】音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击788280672加群免费领取~

    3.配置CMake

    由于android早已支持CMake,所以旧的android.mk配置此处不增加

    1. #声明cmake版本号
    2. cmake_minimum_required(VERSION 3.10.2)
    3. #此处导入头文件目录
    4. include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
    5. #将so库文件路径赋值ffmpeg_lib_dir,方便操作
    6. set(ffmpeg_lib_dir ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${ANDROID_ABI})
    7. #项目名称
    8. project("newffmpeg")
    9. add_library( newffmpeg
    10. SHARED
    11. native-lib.cpp)
    12. #初始化log库
    13. find_library( log-lib
    14. log)
    15. #江指定的源文件生成链接文件
    16. add_library( avutil
    17. SHARED
    18. IMPORTED )
    19. set_target_properties( avutil
    20. PROPERTIES IMPORTED_LOCATION
    21. ${ffmpeg_lib_dir}/libavutil.so )
    22. add_library( swresample
    23. SHARED
    24. IMPORTED )
    25. set_target_properties( swresample
    26. PROPERTIES IMPORTED_LOCATION
    27. ${ffmpeg_lib_dir}/libswresample.so )
    28. add_library( avcodec
    29. SHARED
    30. IMPORTED )
    31. set_target_properties( avcodec
    32. PROPERTIES IMPORTED_LOCATION
    33. ${ffmpeg_lib_dir}/libavcodec.so )
    34. add_library( avfilter
    35. SHARED
    36. IMPORTED)
    37. set_target_properties( avfilter
    38. PROPERTIES IMPORTED_LOCATION
    39. ${ffmpeg_lib_dir}/libavfilter.so )
    40. add_library( swscale
    41. SHARED
    42. IMPORTED)
    43. set_target_properties( swscale
    44. PROPERTIES IMPORTED_LOCATION
    45. ${ffmpeg_lib_dir}/libswscale.so )
    46. add_library( avformat
    47. SHARED
    48. IMPORTED)
    49. set_target_properties( avformat
    50. PROPERTIES IMPORTED_LOCATION
    51. ${ffmpeg_lib_dir}/libavformat.so )
    52. add_library( postproc
    53. SHARED
    54. IMPORTED)
    55. set_target_properties( postproc
    56. PROPERTIES IMPORTED_LOCATION
    57. ${ffmpeg_lib_dir}/libpostproc.so )
    58. #将目标文件与库文件进行链接
    59. target_link_libraries( # Specifies the target library.
    60. newffmpeg
    61. avutil
    62. swresample
    63. avcodec
    64. avfilter
    65. swscale
    66. avformat
    67. postproc
    68. ${log-lib}
    69. )

    若未能链接到库文件,则检查路径是否正常(点击libs路径左侧菜单能正常展开说明路径正确)

    4.测试ffmpeg

    在native-lib.cpp中增加或替换代码,注意JNI路径替换为你的包名路径或方法,在Java中调用,如能正常打印出配置信息,说明编译及导入完成
     

    1. #include <jni.h>
    2. #include <string>
    3. #include <unistd.h>
    4. extern "C" {
    5. #include <libavcodec/avcodec.h>
    6. #include <libavformat/avformat.h>
    7. #include <libavfilter/avfilter.h>
    8. #include <libavcodec/jni.h>
    9. JNIEXPORT jstring JNICALL
    10. Java_cn_jin_newffmpeg_MainActivity_getConfigurations(JNIEnv *env,
    11. jobject /* this */) {
    12. return env->NewStringUTF(avcodec_configuration());
    13. }
    14. }

    遇到的问题

    2 files found with path 'lib/arm64-v8a/libavcodec.so' from inputs:

    1. 2 files found with path 'lib/arm64-v8a/libavcodec.so' from inputs:
    2. - D:\ffmpeg\project\NewFFmpeg\app\build\intermediates\merged_jni_libs\debug\out\arm64-v8a\libavcodec.so
    3. - D:\ffmpeg\project\NewFFmpeg\app\build\intermediates\cxx\Debug\2xk41543\obj\arm64-v8a\libavcodec.so
    4. If you are using jniLibs and CMake IMPORTED targets, see
    5. https://developer.android.com/r/tools/jniLibs-vs-imported-targets

    解决办法:此处是由于在build.gradle中配置了jniLibs.srcDirs导致的文件冲突,gradle高版本已经不需要手动指定so库的路径,删除即可

    D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libavcodec.so: error adding symbols: File in wrong format clang++: error: linker command failed with exit code 1 (use -v to see invocation)
     

    1. [1/1] Linking CXX shared library D:\ffmpeg\project\FFmpegProject\app\build\intermediates\cxx\Debug\2c676z6h\obj\arm64-v8a\libffmpeg.so
    2. FAILED: D:/ffmpeg/project/FFmpegProject/app/build/intermediates/cxx/Debug/2c676z6h/obj/arm64-v8a/libffmpeg.so
    3. cmd.exe /C "cd . && C:\Users\as230\AppData\Local\Android\Sdk\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android21 --gcc-toolchain=C:/Users/as230/AppData/Local/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=C:/Users/as230/AppData/Local/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -std=c++11 -frtti -fexceptions -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libgcc_real.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,libffmpeg.so -o D:\ffmpeg\project\FFmpegProject\app\build\intermediates\cxx\Debug\2c676z6h\obj\arm64-v8a\libffmpeg.so CMakeFiles/ffmpeg.dir/native-lib.cpp.o -llog D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libavcodec.so D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libavfilter.so D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libavformat.so D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libavutil.so D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libpostproc.so D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libswresample.so D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libswscale.so -latomic -lm && cd ."
    4. D:/ffmpeg/project/FFmpegProject/app/src/main/cpp/../../main/jniLibs/arm64-v8a/libavcodec.so: error adding symbols: File in wrong format
    5. clang++: error: linker command failed with exit code 1 (use -v to see invocation)
    6. ninja: build stopped: subcommand failed.

    出现动态库中的问题导致链接器命令失败大概率是两个原因

    • 编译出来的so有问题,此时不要尝试,可下载其他已经编译好的so进行替换,如其他可正常运行则已经说明
    • so库中依赖其他库文件,其他库文件未导入或者已导入未进行链接,此时应该检查一下cmake

    java.lang.UnsatisfiedLinkError: dlopen failed: library “libxxx.so” not found

    此处错误是在运行之后出现的,原因是某些已经使用的库文件没有链接上,应该检查一下libs和cmkae,基本上能解决

    源码

    ffmpeg for android源码

    原文链接 ffmpeg for android编译全过程与遇到的问题

  • 相关阅读:
    学习笔记二十九:K8S配置管理中心Configmap实现微服务配置管理
    【毕业设计】大数据客户价值分析(RFM模型)
    ftplib模块--ftp密码爆破
    C++(STL容器适配器)
    年薪30万+的HR这样做数据分析!(附关键指标&免费模版)
    linux(软硬链接)
    开源生态企业反哺GitLink确实开源创新服务--DevOps引擎合作
    夯实网络安全基石,筑牢网络安全防线
    spring-security-oauth2之AuthorizationServerConfigurerAdapter浅析
    Linux 线程同步、互斥锁、避免死锁、条件变量
  • 原文地址:https://blog.csdn.net/qq_52703909/article/details/136173538