android ndk编译so库,脚本编译ffmpeg5.0示例

Posted markrenChina

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android ndk编译so库,脚本编译ffmpeg5.0示例相关的知识,希望对你有一定的参考价值。

今天收了份csdn小礼物,上来补篇博客。

环境配置

下载,安装什么的自己参考一下官网。
从 NDK r19 开始,NDK 默认安装的工具链可供使用。与任意构建系统进行交互时不再需要使用 make_standalone_toolchain.py 脚本。

简单示例(利用cmake)

demo工程图

sum.h

#ifndef FFMPEGDEMO_SUM_H
#define FFMPEGDEMO_SUM_H

//一定要extern "C" 不然会链接错误
extern "C"
int sum(int val1,int val2);

#endif

sum.c

#include "sum.h"

int sum(int val1,int val2)
    return val1+val2;

CMakeLists.txt

#指定CMake最低的编译版本
CMAKE_MINIMUM_REQUIRED(VERSION 3.14)

# 定义一个工程名
PROJECT(MAKE_SO)

#搜集src目录下的所有的 源文件
AUX_SOURCE_DIRECTORY($PROJECT_SOURCE_DIR/src SRC_LIST) #找到src目录下所有源文件赋值给SRC_LIST
#另一种写法
#FILE(GLOB SRC_LIST "$PROJECT_SOURCE_DIR/src/*.c" "$PROJECT_SOURCE_DIR/src/*.cpp")

#指定头文件目录
INCLUDE_DIRECTORIES($PROJECT_SOURCE_DIR/include)

#指定 so的生成目录 lib
SET(LIBRARY_OUTPUT_PATH $PROJECT_SOURCE_DIR/lib)

# 打印
MESSAGE(STATUS "srclist: " $SRC_LIST)
#-- srclist: /home/ubuntu/learnC/learnCMakeList/make-so/src/main.c/home/ubuntu/learnC/learnCMakeList/make-so/src/sum.c

#生成动态库 默认生成静态库,SHARED指定动态库
ADD_LIBRARY(make_so SHARED $SRC_LIST)

as_build.sh:

#!/bin/bash
rm -rf build
mkdir build
cd build
#设置交叉编译的参数
echo $NDK_ROOT
cmake \\
-Dandroid_NDK=$NDK_ROOT \\
-DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake \\
-DANDROID_ABI="arm64-v8a" \\
-DANDROID_NATIVE_API_LEVEL=19 \\
..
make

第三方编译示例,ffmpeg5.0

ndk版本 :android-ndk-r23b
基础依赖参考:centos 安装 ffmpeg 并添加 libx264库 libfdk-aac库 openssl库
编译参考文章:使用Android Studio开发FFmpeg的正确姿势
适配后编译脚本

#!/bin/bash
# 用于编译android平台的脚本

# NDK所在目录,这里要自定义一下
NDK_PATH=$NDK_ROOT
HOST_PLATFORM=linux-x86_64
HOST_PLATFORM=$HOST_PLATFORM
# minSdkVersion 
API=23

TOOLCHAINS="$NDK_PATH/toolchains/llvm/prebuilt/$HOST_PLATFORM"
SYSROOT="$NDK_PATH/toolchains/llvm/prebuilt/$HOST_PLATFORM/sysroot"
# 生成 -fpic 与位置无关的代码
CFLAG="-D__ANDROID_API__=$API -Os -fPIC -DANDROID "
LDFLAG="-lc -lm -ldl -llog "

# 输出目录
PREFIX=`pwd`/android-build
# 日志输出目录
CONFIG_LOG_PATH=$PREFIX/log
# 公共配置
COMMON_OPTIONS=
# 交叉配置
CONFIGURATION=

build() 
  APP_ABI=$1
  echo "======== > Start build $APP_ABI"
  case $APP_ABI in
  armeabi-v7a)
    ARCH="arm"
    CPU="armv7-a"
    MARCH="armv7-a"
    TARGET=armv7a-linux-androideabi
    CC="$TOOLCHAINS/bin/$TARGET$API-clang"
    CXX="$TOOLCHAINS/bin/$TARGET$API-clang++"
    LD="$TOOLCHAINS/bin/$TARGET$API-clang"
    # 交叉编译工具前缀
    CROSS_PREFIX="$TOOLCHAINS/bin/arm-linux-androideabi-"
    EXTRA_CFLAGS="$CFLAG -mfloat-abi=softfp -mfpu=vfp -marm -march=$MARCH "
    EXTRA_LDFLAGS="$LDFLAG"
    EXTRA_OPTIONS="--enable-neon --cpu=$CPU "
    ;;
  arm64-v8a)
    ARCH="aarch64"
    TARGET=$ARCH-linux-android
    CC="$TOOLCHAINS/bin/$TARGET$API-clang"
    CXX="$TOOLCHAINS/bin/$TARGET$API-clang++"
    LD="$TOOLCHAINS/bin/$TARGET$API-clang"
    CROSS_PREFIX="$TOOLCHAINS/bin/$TARGET-"
    EXTRA_CFLAGS="$CFLAG"
    EXTRA_LDFLAGS="$LDFLAG"
    EXTRA_OPTIONS=""
    ;;
  x86)
    ARCH="x86"
    CPU="i686"
    MARCH="i686"
    TARGET=i686-linux-android
    CC="$TOOLCHAINS/bin/$TARGET$API-clang"
    CXX="$TOOLCHAINS/bin/$TARGET$API-clang++"
    LD="$TOOLCHAINS/bin/$TARGET$API-clang"
    CROSS_PREFIX="$TOOLCHAINS/bin/$TARGET-"
    #EXTRA_CFLAGS="$CFLAG -march=$MARCH -mtune=intel -mssse3 -mfpmath=sse -m32"
    EXTRA_CFLAGS="$CFLAG -march=$MARCH  -mssse3 -mfpmath=sse -m32"
    EXTRA_LDFLAGS="$LDFLAG"
    EXTRA_OPTIONS="--cpu=$CPU "
    ;;
  x86_64)
    ARCH="x86_64"
    CPU="x86-64"
    MARCH="x86_64"
    TARGET=$ARCH-linux-android
    CC="$TOOLCHAINS/bin/$TARGET$API-clang"
    CXX="$TOOLCHAINS/bin/$TARGET$API-clang++"
    LD="$TOOLCHAINS/bin/$TARGET$API-clang"
    CROSS_PREFIX="$TOOLCHAINS/bin/$TARGET-"
    #EXTRA_CFLAGS="$CFLAG -march=$CPU -mtune=intel -msse4.2 -mpopcnt -m64"
    EXTRA_CFLAGS="$CFLAG -march=$CPU -msse4.2 -mpopcnt -m64"
    EXTRA_LDFLAGS="$LDFLAG"
    EXTRA_OPTIONS="--cpu=$CPU "
    ;;
  esac

  echo "-------- > Start clean workspace"
  make clean

  echo "-------- > Start build configuration"
  CONFIGURATION="$COMMON_OPTIONS"
  CONFIGURATION="$CONFIGURATION --logfile=$CONFIG_LOG_PATH/config_$APP_ABI.log"
  CONFIGURATION="$CONFIGURATION --prefix=$PREFIX"
  CONFIGURATION="$CONFIGURATION --libdir=$PREFIX/libs/$APP_ABI"
  CONFIGURATION="$CONFIGURATION --incdir=$PREFIX/includes/$APP_ABI"
  CONFIGURATION="$CONFIGURATION --pkgconfigdir=$PREFIX/pkgconfig/$APP_ABI"
  CONFIGURATION="$CONFIGURATION --cross-prefix=$CROSS_PREFIX"
  CONFIGURATION="$CONFIGURATION --arch=$ARCH"
  CONFIGURATION="$CONFIGURATION --sysroot=$SYSROOT"
  CONFIGURATION="$CONFIGURATION --cc=$CC"
  CONFIGURATION="$CONFIGURATION --cxx=$CXX"
  CONFIGURATION="$CONFIGURATION --ld=$LD"
  # nm 和 strip
  CONFIGURATION="$CONFIGURATION --nm=$TOOLCHAINS/bin/llvm-nm"
  CONFIGURATION="$CONFIGURATION --strip=$TOOLCHAINS/bin/llvm-strip"
  CONFIGURATION="$CONFIGURATION $EXTRA_OPTIONS"

  echo "-------- > Start config makefile with $CONFIGURATION --extra-cflags=$EXTRA_CFLAGS --extra-ldflags=$EXTRA_LDFLAGS"
  ./configure $CONFIGURATION \\
  --extra-cflags="$EXTRA_CFLAGS" \\
  --extra-ldflags="$EXTRA_LDFLAGS"

  echo "-------- > Start make $APP_ABI with -j1"
  make -j1

  echo "-------- > Start install $APP_ABI"
  make install
  echo "++++++++ > make and install $APP_ABI complete."



build_all() 
  #配置开源协议声明
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-gpl"
  #目标android平台
  COMMON_OPTIONS="$COMMON_OPTIONS --target-os=android"
  #取消默认的静态库
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-static"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-shared"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-protocols"
  #开启交叉编译
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-cross-compile"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-optimizations"
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-debug"
  #尽可能小
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-small"
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-doc"
  #不要命令(执行文件)
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-programs"  # do not build command line programs
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-ffmpeg"    # disable ffmpeg build
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-ffplay"    # disable ffplay build
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-ffprobe"   # disable ffprobe build
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-symver"
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-network"
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-x86asm"
  COMMON_OPTIONS="$COMMON_OPTIONS --disable-asm"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-pthreads"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-mediacodec"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-jni"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-zlib"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-pic"
  #COMMON_OPTIONS="$COMMON_OPTIONS --enable-avresample"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-decoder=h264"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-decoder=mpeg4"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-decoder=mjpeg"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-decoder=png"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-decoder=vorbis"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-decoder=opus"
  COMMON_OPTIONS="$COMMON_OPTIONS --enable-decoder=flac"
  echo "COMMON_OPTIONS=$COMMON_OPTIONS"
  echo "PREFIX=$PREFIX"
  echo "CONFIG_LOG_PATH=$CONFIG_LOG_PATH"
  mkdir -p $CONFIG_LOG_PATH
  #    build $app_abi
  build "armeabi-v7a"
  build "arm64-v8a"
  build "x86"
  build "x86_64"


echo "-------- Start --------"

build_all

echo "-------- End --------"

安卓工程测试用CMakeLists.txt

cmake_minimum_required(VERSION 3.18.1)

project("ffmpeg5")

MESSAGE(STATUS "this is SOURCE dir " $HELLO_SOURCE_DIR)

include_directories($CMAKE_SOURCE_DIR/include/$ANDROID_ABI)
include_directories($CMAKE_SOURCE_DIR/include)

#link_directories($CMAKE_SOURCE_DIR/jnilibs/$ANDROID_ABI)

AUX_SOURCE_DIRECTORY($CMAKE_SOURCE_DIR/src SRC_LIST)

add_library(ffmpeg5 SHARED $SRC_LIST)

add_library(avcodec SHARED IMPORTED )
set_target_properties(
        avcodec
        PROPERTIES IMPORTED_LOCATION
        $CMAKE_SOURCE_DIR/jniLibs/$ANDROID_ABI/libavcodec.so
)
add_library(avdevice SHARED IMPORTED )
set_target_properties(
        avdevice
        PROPERTIES IMPORTED_LOCATION
        $CMAKE_SOURCE_DIR/jniLibs/$ANDROID_ABI/libavdevice.so
)
add_library(avfilter SHARED IMPORTED )
set_target_properties(
        avfilter
        PROPERTIES IMPORTED_LOCATION
        $CMAKE_SOURCE_DIR/jniLibs/$ANDROID_ABI/libavfilter.so
)

add_library(avformat SHARED IMPORTED )
set_target_properties(
        avformat
        PROPERTIES IMPORTED_LOCATION
        $CMAKE_SOURCE_DIR/jniLibs/$ANDROID_ABI/libavformat.so
)

add_library(avutil SHARED IMPORTED )
set_target_properties(
        avutil
        PROPERTIES IMPORTED_LOCATION
        $CMAKE_SOURCE_DIR/jniLibs/$ANDROID_ABI/libavutil.so
)

add_library(swresample SHARED IMPORTED )
set_target_properties(
        swresample
        PROPERTIES IMPORTED_LOCATION
        $CMAKE_SOURCE_DIR/jniLibs/$ANDROID_ABI/libswresample.so
)

add_library(swscale SHARED IMPORTED )
set_target_properties(
        swscale
        PROPERTIES IMPORTED_LOCATION
        $CMAKE_SOURCE_DIR/jniLibs/$ANDROID_ABI/libswscale.so
)


find_library(log-lib log)

target_link_libraries(ffmpeg5
        # 编解码(最重要的库)
        avcodec
        # 设备信息
        avdevice
        # 滤镜特性处理库
        avfilter
        # 封装格式处理库
        avformat
        # 工具库(大部分库都需要这个库的支持)
        avutil
        # 音频采样数据格式转换库
        swresample
        # 视频像素数据格式转换
        swscale
        $log-lib )

测试代码ffmpeg5.cpp

#include <jni.h>
#include <string>

extern "C" 
#include "libavcodec/avcodec.h"


extern "C" JNIEXPORT jstring JNICALL
Java_com_zhipuchina_ffmpeg5_NativeLib_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) 

    char str[25];
    sprintf(str,"%d",avcodec_version());
    return env->NewStringUTF(str);

NDK交叉编译及so库导入Android项目

前言
记录 NDK交叉编译及so库导入Android项目 的简单步骤,以备后续用到时查看。

环境
在Linux和Mac环境下,分别编译输出so库。

Red Hat Enterprise Linux 8 64 位 使用GCC编译(也可以用CLANG,这里演示用GCC)

macOS Big Sur 11.3.1 使用CLANG编译(也可以用GCC,这里演示用CLANG)

下载NDK
这里只演示下载NDK17,项目中Mac用到的NDK版本为NDK21

下载NDK

wget https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip

NDK18及之后的NDK版本,建议使用CLANG编译。

解压NDK

unzip android-ndk-r17c-linux-x86_64.zip

解压后得到android-ndk-r17c文件夹

编写头文件及c文件
GCC编译

#include "get.h"

int get(){
  return 666;
}
#include "get.h"

int get(){
  return 666;
}

CLANG编译

#include <stdio.h>

int hi();

#include "hi.h"

int hi(){
  return 888;
}

配置NDK
Linux(使用GCC编译)
编辑Home/用户 目录下的.bashrc

vim /home/wangyz/.bashrc

添加以下内容

# 配置NDK的目录
export NDK_HOME=/home/wangyz/NDK/android-ndk-r17c
# 将NDK目录加入PATH中
export PATH=$PATH:$NDK_HOME

# x86 CPU架构的gcc
export NDK_GCC_x86=$NDK_HOME/toolchains/x86-4.9/prebuilt/linux-x86_64/bin/i686-linux-android-gcc

# x86_64 CPU架构的gcc
export NDK_GCC_x64=$NDK_HOME/toolchains/x86_64-4.9/prebuilt/linux-x86_64/bin/x86_64-linux-android-gcc

# ARM CPU架构的gcc
export NDK_GCC_ARM=$NDK_HOME/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc

# ARM64 CPU架构的gcc
export NDK_GCC_ARM_64=$NDK_HOME/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc

# x86 CPU架构 配置sysroot,isystem,否则会找不到头文件
export NDK_GCC_CONFIG_x86="--sysroot=$NDK_HOME/platforms/android-21/arch-x86 -isystem $NDK_HOME/sysroot/usr/include -isystem $NDK_HOME/sysroot/usr/include/i686-linux-android"

# x86_64 CPU架构 配置sysroot,isystem,否则会找不到头文件
export NDK_GCC_CONFIG_x64="--sysroot=$NDK_HOME/platforms/android-21/arch-x86_64 -isystem $NDK_HOME/sysroot/usr/include -isystem $NDK_HOME/sysroot/usr/include/x86_64-linux-android"

# ARM CPU架构 配置sysroot,isystem,否则会找不到头文件
export NDK_GCC_CONFIG_ARM="--sysroot=$NDK_HOME/platforms/android-21/arch-arm -isystem $NDK_HOME/sysroot/usr/include -isystem $NDK_HOME/sysroot/usr/include/arm-linux-androideabi"

# ARM64 CPU架构 配置sysroot,isystem,否则会找不到头文件
export NDK_GCC_CONFIG_ARM_64="--sysroot=$NDK_HOME/platforms/android-21/arch-arm64 -isystem $NDK_HOME/sysroot/usr/include -isystem $NDK_HOME/sysroot/usr/include/aarch64-linux-android"

Mac(使用CLANG编译)
修改~/.bash_profile

vim ~/.bash_profile

添加以下内容

# NDK目录
export NDK_HOME=/Users/ringle/Library/Android/sdk/ndk/21.1.6352462

# CLANG目录
export CLANG=${NDK_HOME}/toolchains/llvm/prebuilt/darwin-x86_64/bin

# 添加到PATH中
export PATH=${PATH}:${NDK_HOME}:${CLANG}

编译
这里编译ARM64构架的so

GCC

$NDK_GCC_ARM_64 $NDK_GCC_CONFIG_ARM_64 -fPIC -shared get.c -o libndk-linux.so

CLANG

aarch64-linux-android21-clang -fPIC -shared hi.c -o libndk-mac.so

导入Android Studio

复制so到项目中

在app/src/main 目录下新建jniLibs目录,再新建arm64-v8a目录,将编译生成的libndk-linux.so及libndk-mac.so复制到目录下

配置cmake

在app/src/main 目录下新建cpp目录,新建CMakeLists.txt,配置如下:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.10.2)

# Declares and names the project.

project("ndk")

# 包含所有CPP文件
file(GLOB allCPP *.cpp)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
        native-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        ${allCPP})

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}")

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        native-lib

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib}
        # 链接libndk-mac
        ndk-mac
        # 链接libndk-linux
        ndk-linux
        )

配置gradle

配置app模块下的build.gralde文件

android {

    defaultConfig {
        //...
        
        externalNativeBuild {
            cmake {
                abiFilters "arm64-v8a"
            }
        }
        ndk {
            abiFilters "arm64-v8a"
        }
    }

    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
}

引用so中的方法

在cpp目录下,新建native-lib.cpp

#include <jni.h>
#include <string>
#include <android/log.h>

#define TAG "Wangyz"

#define LOG_I(...) __android_log_print(ANDROID_LOG_INFO, TAG,  __VA_ARGS__);

extern "C" int get();

extern "C" int hi();

extern "C" JNIEXPORT jstring JNICALL
Java_com_wangyz_ndk_MainActivity_stringFromJNI(
        JNIEnv *env,jobject /* this */) {
    int a = get();
    LOG_I("hello:%d", a);

    int b = hi();
    LOG_I("hi:%d", b);

    return env->NewStringUTF("hello");
}

Activity中调用

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("ndk-mac");
        System.loadLibrary("ndk-linux");
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();
}

更多NDK相关资料可以点此处免费获取
在这里插入图片描述

以上是关于android ndk编译so库,脚本编译ffmpeg5.0示例的主要内容,如果未能解决你的问题,请参考以下文章

NDK交叉编译及so库导入Android项目

用ndk环境编译android可用的so库

ndk编译生成so

最新版FFmpeg移植Android:编译so库(基于NDK r20和FFmpeg-4.1.0)

ndk编译android的lame库

解决Android Studio使用CMake无法编译出32位armeabi平台so库