在系列一中讲述了如何编译FFmpeg的源码,如今就在Android项目中引入咱们编译出来的库,并实现播放一个在线视频的功能java
新建一个支持ndk的Android工程,在AS中新建工程就再也不详述了,详细的新建ndk工程,能够参考AndroidStudio中使用JNI/NDK示例 须要注意的一点就是在新建导航中注意勾选Support C++这个选项,这样新建的Android工程就会有CMakeLists等进行NDK编译时必要的东东了。android
新建的Android工程须要对项目中的app/build.gradle作一些修改,其中主要修改的地方以下:git
android {
……
defaultConfig {
……
externalNativeBuild {
// -Wno-deprecated-declarations 添加这个保证编译出的不少文件再也不报错
cmake {
cppFlags "-frtti -fexceptions -Wno-deprecated-declarations"
cFlags "-DSTDC_HEADERS"
}
}
ndk { // 声明编译的架构类型,指定为armeabi-v7a便可
abiFilters "armeabi-v7a"
}
}
externalNativeBuild {
cmake { // 配置咱们本身的CMakeLists文件
path file('CMakeLists.txt')
}
}
sourceSets {
main {
// 指定存放native代码的目录,这里指定为jni和cpp皆可
jni.srcDirs = ['src/main/jni', 'src/main/cpp/']
// 指定jni库的存放目录为libs
jniLibs.srcDirs = ['libs']
}
}
}
复制代码
上面配置须要特别说明的一点是,在cmake配置中的cppFlags务必添加-Wno-deprecated-declarations,这样确保咱们能使用一些过时的接口。另外在后面导入FFmpeg编译生成的代码到AS中会有不少标红,添加了这个配置属性后,各类讨厌的标红就去无踪了😏。github
导入以前,先在咱们工程中的app/下新建libs文件夹,而后继续在libs下新建armeabi-v7a和include两个文件夹 架构
咱们编写一个NDK的桥接类NDKBridge,并在其中定义咱们本身的native库:
NDKBridge.javaapp
public class NDKBridge {
static {
// 自定义的native库
System.loadLibrary("ndk_test_jni");
}
……
}
复制代码
定义一个简单的播放器类FFVideoPlayer,并在其中声明一个名为render的native方法:
FFVideoPlayer.javaide
public class FFVideoPlayer extends SurfaceView {
……
public void play(final String url) {
new Thread(new Runnable() {
@Override
public void run() {
render(url, FFVideoPlayer.this.getHolder().getSurface());
}
}).start();
}
// 播放器渲染的方法,须要在native层中实现
public native void render(String url, Surface surface);
}
复制代码
此时咱们尚未配置CMakeLists文件,也没有新建任何native代码,因此上面声明的native方法是会标红报错的post
配置CMakeLists文件,指定咱们的native代码入口,并指定编译成的native库,以及引用的哪些native代码。下面列出一些须要注意的点,详细内容能够到项目工程中查看gradle
# 添加库——本身编写的库
# 库名称:ndk_test_jni
# 库类型:SHARED,表示动态库,后缀为.so(若是是STATIC,则表示静态库,后缀为.a)
# 库源码文件:src/main/jni/ndk_test_jni.cpp
add_library(ndk_test_jni
SHARED
src/main/jni/ndk_test_jni.cpp)
……
# 引入头文件,不然没法在ndk_test_jni.cpp中导入FFmpeg编译出的源文件
include_directories(libs/include)
复制代码
暂时先别执行syc操做,由于都没有ndk_test_jni.cpp文件,确定会失败!ui
根据CMakeLists中的配置,咱们须要在工程的src/main/jni中新建一个ndk_test_jni.cpp文件,而后再执行syc操做。
到上面声明native方法的地方,此时应该仍是标红报错。用鼠标点击右边标红的地方,使错误处于选中状态,而后点击ALT+Enter快捷键,此时AS会弹出建立须要的native方法,点击确认后就会自动在咱们的ndk_test_jni.cpp中新建一个空的Java_cain_tencent_com_androidexercisedemo_ffmpeg_FFVideoPlayer_render方法,这就是咱们在java层声明的native方法的实现。而后就能够愉快地到ndk_test_jni.cpp中去尽情发挥,实现各个native方法了。
具体的代码这里就不贴出来了,具体的能够到项目查看,当中注释也写得很明朗了。这里须要注意的一点就是咱们须要将各个native方法包裹在extern "C" {}中
extern "C" {
#include <cstdio>
#include "lame/lame.h"
//封装格式处理
#include <libavformat/avformat.h>
#include <android/native_window_jni.h>
#include <libavfilter/avfilter.h>
#include <libavcodec/avcodec.h>
//封装格式处理
#include <libavformat/avformat.h>
//像素处理
#include <libswscale/swscale.h>
#include <unistd.h>
/** * 解码视频播,渲染播放 */
extern "C"
JNIEXPORT void JNICALL Java_cain_tencent_com_androidexercisedemo_ffmpeg_FFVideoPlayer_render(JNIEnv *env, jobject instance,jstring url_,jobject surface) {
……
}
}
复制代码
不然在编译时会报各类unresolved错误
这里须要播放在线视频,所以也须要记得申请联网权限