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();
}
以上是关于android ndk编译so库,脚本编译ffmpeg5.0示例的主要内容,如果未能解决你的问题,请参考以下文章