前言:经过前几篇的介绍,我们已经掌握在linux下编译ffmpeg.so。我们编译出so,目的是为了能够使用so达到使用ffmpeg相关功能的目的。本篇介绍如何在android上使用ffmpeg的so库的基础功能。本文要求读者有一定的jni基础。
本文开发环境:
ffmpeg版本:ffmpeg4.2.2
androidStudio:2022.1.1 Patch 1;gradle版本:7.4.1;ndk21(必须要有ndk环境)
ffmpeg专辑(一):linux编译ffmpeg.so入门
ffmpeg专辑(二):linux编译ffmpeg.so脚本改良与裁编
ffmpeg专辑(三):linux编译ffmpeg.so多架构编译
ffmpeg专辑(四):linux编译ffmpeg.so合并so篇
一、androidStudio新建jni(C++)项目
(新建后,这是默认的目录结构)
二、导入linux生成的ffmepg的7个so文件和头文件
1、在libs目录下新建文件夹arm64-v8a(本文只引入arm64-v8a版本,读者可以参照自行引入armeabi-v7a版本),在其中复制进来ffmepg相关的7个so文件,在cpp目录下导入include的C头文件:
2、编辑CMakeLists.txt联编脚本
cmake_minimum_required(VERSION 3.22.1)
#自动生成,自己的项目名
project("ffmpegndk")
message("start............................................................")
# 1. 定义so库和头文件所在目录相对与脚本的位置的变量,方面后面使用
set(ffmpeg_lib_dir_neway ${CMAKE_SOURCE_DIR}/../../../libs/${ANDROID_ABI})
set(ffmpeg_head_dir ${CMAKE_SOURCE_DIR}/include)
# 2. 添加头文件目录
include_directories(${ffmpeg_head_dir})
#==========================ffmpeg引入开始====================================
#add_library(配置模块so库编译信息),set_target_properties(为目标配置编译属性),对于三方so,这两个方法要成对出现
add_library( avcodec
SHARED
IMPORTED)
set_target_properties(
avcodec
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir_neway}/libavcodec.so)
add_library( avdevice
SHARED
IMPORTED)
set_target_properties(
avdevice
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir_neway}/libavdevice.so)
add_library( avfilter
SHARED
IMPORTED)
set_target_properties(
avfilter
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir_neway}/libavfilter.so)
add_library( avformat
SHARED
IMPORTED)
set_target_properties(
avformat
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir_neway}/libavformat.so)
add_library( avutil
SHARED
IMPORTED)
set_target_properties(
avutil
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir_neway}/libavutil.so)
add_library( swresample
SHARED
IMPORTED)
set_target_properties(
swresample
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir_neway}/libswresample.so)
add_library( swscale
SHARED
IMPORTED)
set_target_properties(
swscale
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir_neway}/libswscale.so)
#==========================ffmpeg引入结束====================================
#对最后一个自己的so(名称可以自定义),不需要再set_target_properties。这个so最终会生成到build中。
add_library(
ffmpegNdkCustom
SHARED
native-lib.cpp)
#查找代码中使用到的android系统预留(预构建)库(如log、zlib压缩库等)
find_library(
log-lib
log)
#指定编译最终目标库时,cmke要链接的库。
#解释:一般形式是:target_link_libraries(your-lib library1 library2 ...)
target_link_libraries(
#指定目标库
ffmpegNdkCustom
#连接 FFmpeg 相关的库
avcodec
avdevice
avfilter
avformat
avutil
swresample
swscale
${log-lib})
3、编辑native-lib.cpp文件,编写native方法。
下面的 stringFromJNI 是项目默认帮我们生成的默认方法,getConfiguration是我们测试ffmpeg获取版本号的一个方法
#include <jni.h>
#include <string>
extern "C" {
#include "libavcodec/avcodec.h"
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_neway_ffmpegndk_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C"
JNIEXPORT jstring JNICALL
Java_com_neway_ffmpegndk_MainActivity_getConfiguration(JNIEnv *env, jobject thiz) {
return env->NewStringUTF(avcodec_configuration());
}
三、app中使用
1、修改MainActivity方法:
package com.neway.ffmpegndk;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import com.neway.ffmpegndk.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
//用于在程序启动时加载cmake编译好的目标库ffmpegNdkCustom.so,注意大小写
static {
System.loadLibrary("ffmpegNdkCustom");
}
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
TextView tv = binding.sampleText;
//tv.setText(stringFromJNI());
tv.setText(getConfiguration());
}
/**
* 在 ffmpegNdkCustom.so 库中声明的原生c++的native方法,起连接作用
*/
public native String stringFromJNI();
public native String getConfiguration();
}
2、修改app级别的build.gradle文件,用以使app支持arm64-v8a架构:
android {
namespace 'com.neway.ffmpegndk'
compileSdk 33
defaultConfig {
applicationId "com.neway.ffmpegndk"
minSdk 21
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
abiFilters 'arm64-v8a'//,'armeabi-v7a'//,'x86','arm64-v8a',
}
}
}
...
}
3、运行(因为指定了arm64-v8a架构,故不能在电脑模拟器上运行,需要真机,电脑模拟器需要编译使用x86架构的),即展示了我们的ffmpeg版本号:
4、此时,我们也可以观察下,cmake联编的目标so同时也生成在了我们的build目录下:
后记:
本文使用了ffmpeg未合并的7个so文件方式,当然也可以使用合并so(见系列文章第四篇ffmpeg专辑(四):linux编译ffmpeg.so合并so篇)后的ffmpeg.so文件,此时libs文件夹和cmake联编文件需要变更,其余地方保持不变:
cmake_minimum_required(VERSION 3.22.1)
project("ffmpegndk")
message("start............................................................")
# 1. 定义so库和头文件所在目录,方面后面使用
set(ffmpeg_lib_dir_neway ${CMAKE_SOURCE_DIR}/../../../libs/${ANDROID_ABI})
set(ffmpeg_head_dir ${CMAKE_SOURCE_DIR}/include)
# 2. 添加头文件目录
include_directories(${ffmpeg_head_dir})
#==========================ffmpeg引入开始====================================
#ffmpegsofile为自定义名称,libffmpeg.so是libs目录下的linux编译出的so文件
add_library( ffmpegsofile
SHARED
IMPORTED)
set_target_properties(
ffmpegsofile
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir_neway}/libffmpeg.so)
#==========================ffmpeg引入结束====================================
#对最后一个自己的so,不需要再set_target_properties。这个so最终会生成到build中。
add_library(
ffmpegNdkCustom
SHARED
native-lib.cpp)
find_library(
log-lib
log)
target_link_libraries(
#指定目标库
ffmpegNdkCustom
#连接 FFmpeg 相关的库
ffmpegsofile
${log-lib})
好了,本次专辑(五)就讲到这里了,更多内容,请期待下次的讲述
欢迎有问题的伙伴及时留意讨论,有不足之处还望指正
祝大家生活工作愉快~
转自:
https://blog.csdn.net/minping9101/article/details/131804184