在Android中使用FFmpeg进阶2

在Android中使用FFmpeg进阶2

通过上一篇文章我们已经学习了如果通过源码编译出FFmpeg的动态库文件,这篇文章我们学习下如何将so文件集成到Android工程中。这篇文章主要包含以下几个内容:

  • 如何将FFMPEG 能力集成到native C++工程
  • 如何在一个现有的android 工程中添加JNI接口

编译构建

新建一个native C++工程

在Android Studio中新建一个native C++工程。

集成FFmpeg

将ffmpeg编译好的文件放到libs文件夹下,如下图,以armeabi-v7a为例。

1637480004900

如下面所示,将CmakeLists做一个简单配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# 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("ffmpegdemo")
set(CURRENT_DIR ${CMAKE_SOURCE_DIR})
message("CURRENT_DIR: " ${CMAKE_SOURCE_DIR})
set(LIBS_DIR D:/developProject/hangliebe/FFmpegDemo/app/libs)
# include_directories(${LIBS_DIR}/armeabi-v7a/include)

include_directories(${LIBS_DIR}/arm64-v8a/include/arm64-v8a)

# 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).
native-lib.cpp
FFmpegTest.cpp)

# 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.


add_library(avcodec
SHARED
IMPORTED)
set_target_properties(avcodec
PROPERTIES IMPORTED_LOCATION
${LIBS_DIR}/arm64-v8a/lib/arm64-v8a/libavcodec.so)

add_library(avdevice
SHARED
IMPORTED)
set_target_properties(avdevice
PROPERTIES IMPORTED_LOCATION
${LIBS_DIR}/arm64-v8a/lib/arm64-v8a/libavdevice.so)

add_library(avformat
SHARED
IMPORTED)
set_target_properties(avformat
PROPERTIES IMPORTED_LOCATION
${LIBS_DIR}/arm64-v8a/lib/arm64-v8a/libavformat.so)

add_library(avutil
SHARED
IMPORTED)
set_target_properties(avutil
PROPERTIES IMPORTED_LOCATION
${LIBS_DIR}/arm64-v8a/lib/arm64-v8a/libavutil.so)

add_library(swresample
SHARED
IMPORTED)
set_target_properties(swresample
PROPERTIES IMPORTED_LOCATION
${LIBS_DIR}/arm64-v8a/lib/arm64-v8a/libswresample.so)

add_library(swscale
SHARED
IMPORTED)
set_target_properties(swscale
PROPERTIES IMPORTED_LOCATION
${LIBS_DIR}/arm64-v8a/lib/arm64-v8a/libswscale.so)

add_library(avfilter
SHARED
IMPORTED)
set_target_properties(avfilter
PROPERTIES IMPORTED_LOCATION
${LIBS_DIR}/arm64-v8a/lib/arm64-v8a/libavfilter.so)


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 )

# 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
avfilter
avformat
avcodec
avdevice
avutil
swresample
swscale
# Links the target library to the log library
# included in the NDK.
${log-lib})

build_gradle中添加NDK配置

1
2
3
4
5
6
7
8
9
10
11
android {
……
defaultConfig {
……
ndk {
// 这里添加的对应cpu类型的.so库。下面以为例,初次外,可继续添加其他ABI等类型
abiFilters 'armeabi-v7a' /*, 'x86', 'x86_64' */
}
}
……
}

然后执行Sync构建,可以看到构建成功。

1637480598721

使用FFmpeg

FFmpegTest.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
//
// Created by Administrator on 2021/11/21.
//

#include "FFmpegTest.h"

extern "C" {
#include <libavformat/avformat.h>
}

unsigned FFmpegTest::getAvFormatVersion() {
return avformat_version();
}

MainActivity中将native代码返回值显示出来。

1
2
3
4
5
6
7
8
9
@Override
protected void onCreate(Bundle savedInstanceState) {
……
// Example of a call to a native method
TextView tv = binding.sampleText;
tv.setText("avFormat version:" + getAvFormtVersion());
}
// 该函数在native中实现会进一步调用FFmpegTest::getAvFormatVersion
public native int getAvFormtVersion();

效果

1637480598721

在现有的Android工程中添加JNI

添加cpp目录

在app/src/main中添加cpp目录,用于存放native源码文件。

添加CMakeLists文件

在app目录中添加CMakeLists文件,用于构建项目。

设置build.gradle

指定CMakeLists文件路径

1
2
3
4
5
6
7
8
9
10
android {
……
externalNativeBuild {
cmake {
path file('CMakeLists.txt')
version '3.10.2'
}
}
……
}

创建源码,编译的so在java中使用

在cpp中添加源码文件,并且对应修改CMakeLists文件,并将编译的结果在java代码中加载。以下是案例中的几个重要修改点:

java文件

1
2
3
4
5
static {
System.loadLibrary("native-lib");
}

public native String stringFromJNI();

c++文件

1
2
3
4
5
6
7
8
9
10
#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_hangliebe_medianeo_rtmp_RtmpActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}

CmakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cmake_minimum_required(VERSION 3.10.2)

project("native-lib")

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).
src/main/cpp/native-lib.cpp)


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

log )

编译通过后,就可以在java中通过JNI接口访问native代码

接下来,就可以在工程中集成FFmpeg能力。



关注博客或微信搜索公众号多媒体与图形,获取更多内容,欢迎在公众号留言交流!
扫一扫关注公众号
作者

占航

发布于

2021-11-21

更新于

2023-10-04

许可协议

评论