ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

JNI(三) - FFmpeg for android

2022-02-09 13:59:48  阅读:238  来源: 互联网

标签:bin ffmpeg FFmpeg -- linux JNI android x86


ffmpeg 编译 Android 动态库,静态库

1. 环境

  • 编译系统环境

    • win10 自带Ubuntu 子系统(linux)

    • 执行如下命令安装 一些工具

      • apt-get install yasm
        apt-get install nasm
        apt-get install pkg-config
        
  • ndk版本 r20b

    • 下载 android-ndk-r20b-linux-x86_64.zip

      • # 1 执行scp命令 将下载下来的ndk 文件复制到 linux 子系统中 比如我安装再子系统的/usr/bin位置
        scp -r [/mnt/ndk路径] [要放在linux子系统中的位置]
        # 2 执行unzip 来解压 ndkzip
        unzip android-ndk-r20b-windows-x86_64.zip
        
        # 3 配置 ndk路径 执行如下命令
        vim /etc/profile  # 打开配置文件 按i 进入编辑模式
        # 4 在文件最后配置path处 添加ndk配置 按ESC 输入:WQ 保存并退出
        export NDK=/usr/bin/android-ndk-r20b
        export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$NDK:$PATH
        # 5 执行如下命令 立即 更新配置
         source /etc/profile
        
    • 可选最新ndk版本 在配置文件中注意对应路径即可(比如r17b 之后不支持mips 等区别)

  • ffmpeg 版本 4.0.2

    • 下载 ffmpeg-4.0.2.tar.bz2

      • # 如上述ndk 
        # 1 scp 命令 复制 ffmpeg 到 linux 子系统
        scp -r [/mnt/ffmpeg存在windows目录] [要放在linux子系统中的位置]
        # 2 执行tar 解压缩命令 解压ffmpeg 压缩包
        tar -jxvf ffmpeg-4.2.2.tar.bz2
        # 3 cd 命令进入到ffmpeg 目录下
        cd [ffmpeg 路径]
        # 执行 如下命令  生成一些编译时需要的文件
        ./configure --disable-x86asm
        
    • 当然可官网选最新版本或者稳定版

2 编译ffmpeg

  • 编写 编译脚本 build_ffmpeg.sh 内容如下

    • #!/bin/bash
      
      export NDK=/usr/bin/android-ndk-r20b #这里配置先你的 NDK 路径
      TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
      
      
      function build_android
      {
      
      ./configure \
      --prefix=$PREFIX \
      --enable-neon  \
      --enable-hwaccels  \
      --enable-gpl   \
      --disable-postproc \
      --disable-debug \
      --enable-small \
      --enable-jni \
      --enable-mediacodec \
      --enable-decoder=h264_mediacodec \
      --enable-static \
      --enable-shared \
      --disable-doc \
      --enable-ffmpeg \
      --disable-ffplay \
      --disable-ffprobe \
      --disable-avdevice \
      --disable-doc \
      --disable-symver \
      --cross-prefix=$CROSS_PREFIX \
      --target-os=android \
      --arch=$ARCH \
      --cpu=$CPU \
      --cc=$CC \
      --cxx=$CXX \
      --enable-cross-compile \
      --sysroot=$SYSROOT \
      --extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS" \
      --extra-ldflags="$ADDI_LDFLAGS"
      
      make clean
      make -j16
      make install
      
      echo "============================ build android arm64-v8a success =========================="
      
      }
      
      #arm64-v8a -> arm64-v8a
      ARCH=arm64
      CPU=armv8-a
      API=21
      CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
      CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
      SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
      CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
      PREFIX=$(pwd)/android/$CPU
      OPTIMIZE_CFLAGS="-march=$CPU"
      
      build_android
      
      #armv7-a -> armeabi-v7a
      # ARCH=arm
      # CPU=armv7-a
      # API=21
      # CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang
      # CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++
      # SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
      # CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
      # PREFIX=$(pwd)/android/$CPU
      # OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
      
      # build_android
      
      
      #i686 -> x86
      # ARCH=x86
      # CPU=i686
      # API=21
      # CC=$TOOLCHAIN/bin/i686-linux-android$API-clang
      # CXX=$TOOLCHAIN/bin/i686-linux-android$API-clang++
      # SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
      # CROSS_PREFIX=$TOOLCHAIN/bin/i686-linux-android-
      # PREFIX=$(pwd)/android/$CPU
      # OPTIMIZE_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32 -mno-stackrealign"
      
      # build_android
      
      # #x86-64 -> x86-64
      # ARCH=x86_64 
      # CPU=x86_64 
      # API=21
      # CC=$TOOLCHAIN/bin/x86_64-linux-android$API-clang
      # CXX=$TOOLCHAIN/bin/x86_64-linux-android$API-clang++
      # SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
      # CROSS_PREFIX=$TOOLCHAIN/bin/x86_64-linux-android-
      # PREFIX=$(pwd)/android/$CPU
      # OPTIMIZE_CFLAGS="-march=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel"
      
      # build_android
      
      #armv5-a ->armeabi  r20b ndk 里没有armv5
      # ARCH=arm
      # CPU=armv5te
      # API=21
      # CC=$TOOLCHAIN/bin/armv-linux-androideabi$API-clang
      # CXX=$TOOLCHAIN/bin/armv-linux-androideabi$API-clang++
      # SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
      # CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
      # PREFIX=$(pwd)/android/$CPU
      # OPTIMIZE_CFLAGS="-march=$CPU"
      
      # build_android
      
    • --enable-static \ # 编译静态库
      --enable-shared \  # 编译动态库 我们这里都编译
      PREFIX=$(pwd)/android/$CPU # 输出路径 当前目录下android 以cpu为子文件夹的位置
      
  • 执行scp 命令将 build_ffmpeg.sh 复制到linux子系统中ffmpeg安装目录下

    • 执行 如下命令开始编译 等待编译结束即可

      • ./buildFfmpeg 
        
      • 编译结束后会在当前目录的android目录下根据cpu架构生成的目录

        • 其中 include下 为头文件
        • lib 下为编译好的库

3.导入android项目中使用

由于ffmpeg 是c,c++ 编译的要使用 我们需要使用ndk 所以新建项目需要支持 native 这里我们打印下版本号 ----- 步骤如下

  • 新建支android项目 player Phone and table 中选择 Native c++

  • 将main->cpp 目录下的CMakeLists.txt 文件复制到 main 目录下

    • 这一步是方便CMakeLists.txt 中设置库路径
  • 将第二步编译好的include文件夹复制到cpp目录下

    • 这一步将头文件复制到项目中
  • main 目录下新建jniLibs 将 对应架构的ffmpeg 的 静态文件 复制到该文件夹下

    • 导入静态库
  • 配置cmake

    • 指定头文件路径

    • 指定静态库路径

    • 连接静态库

    • 具体配置文件如下

    • cmake_minimum_required(VERSION 3.10.2)
      
      # Declares and names the project.
      set(CMAKE_VERBOSE_MAKEFILE on)
      project("player")
      
      
      
      add_library( # Sets the name of the library.
              player
      
              # Sets the library as a shared library.
              SHARED
      
              # Provides a relative path to your source file(s).
              cpp/native-lib.cpp)
      
      # 引入当前头文件
      include_directories(${CMAKE_SOURCE_DIR}/cpp/include)
      #打印当前 cmakeLists 的路径
      message("当前cmakel路径: ${CMAKE_SOURCE_DIR} \n cpu架构:${CMAKE_ANDROID_ARCH_ABI}")
      #设置C++ 编译 -L 设置库路径 -L设置的路径与下面的link_directories 应该类似
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/jniLibs/${CMAKE_ANDROID_ARCH_ABI}")
      #指定静态库或动态库的搜索路径 该指令的作用主要是指定要链接的库文件的路径
      # 自己写的动态库文件放在自己新建的目录下时,可以用该指令指定该目录的路径以便工程能够找到。
      link_directories(
              ${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}
      )
      find_library(
              log-lib
              log)
      #将指定的静态库连接到可执行文件上
      target_link_libraries(
              player
      
              avformat avcodec avfilter avutil swresample swscale
      
              ${log-lib})
      
  • 在MainActivity中声明native函数

    • public native String stringFromJNI();
      
  • 在native-lib.cpp中实现

    • #include <jni.h>
      #include <string>
      
      //由于 FFmpeg 库是 C 语言实现的,我们这里是c++文件,所以要告诉编译器按照 C 的规则进行编译
      //导入 version头文件
      extern "C" {
      #include "libavformat/version.h"
      }
      extern "C" JNIEXPORT jstring JNICALL
      Java_com_example_player_MainActivity_stringFromJNI(
              JNIEnv *env,
              jobject /* this */) {
          std::string hello = "Hello from C++";
      	// 读取version
          return env->NewStringUTF(AV_STRINGIFY(LIBAVFORMAT_VERSION));
      }
      
  • 在MainActivity 中调用

    •     @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
      
              binding = ActivityMainBinding.inflate(getLayoutInflater());
              setContentView(binding.getRoot());
      
              // 调用native 方法获取版本信息
              TextView tv = binding.sampleText;
              tv.setText(stringFromJNI());
          }
      
  • 图就不加了 代码库在下面的连接里

标签:bin,ffmpeg,FFmpeg,--,linux,JNI,android,x86
来源: https://blog.csdn.net/Applicaton/article/details/122840335

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有