最近在开发一款APP,因为使用了FFmpeg库,所以需要将FFmpeg交叉编译以便应用于Android平台上。在开始编译之前,我个人认为有必要了解一下FFmpeg编译过程中的一些基础知识,毕竟按照我的教程只是依葫芦画瓢,知其然知其所以然,才可以更好地进阶Android开发。
1.JNI
JNI 全称 Java Native Interface,Java 本地化接口,可以通过 JNI 调用系统提供的 API。操作系统,无论是 Linux,Windows 还是 Mac OS,或者一些汇编语言写的底层硬件驱动都是 C/C++ 写的。Java和C/C++不同 ,它不会直接编译成平台机器码,而是编译成虚拟机可以运行的Java字节码的.class文件,通过JIT技术即时编译成本地机器码,所以有效率就比不上C/C++代码,JNI技术就解决了这一痛点。JNI 可以说是 C 语言和 Java 语言交流的适配器、中间件,即通过JNI,Java 和 其他语言之间可以相互调用,不止局限于 Java 调用其他语言,其他语言也可以主动调用 Java 。下面我们来看看JNI调用示意图:

从上图可以得知,JNI技术通过JVM调用到各个平台的API,虽然JNI可以调用C/C++ ,但是JNI调用还是比C/C++编写的原生应用还是要慢一点,不过对高性能计算来说,这点算不得什么,享受它的便利,也要承担它的弊端 。
Java 虚拟机实现了跨平台特性, 无法很好的实现与操作系统相关的本地操作,而 C 或 C++ 可以,同时代表着 C 或 C++ 不具备 Java 的跨平台能力。那么当我们在程序中使用 JNI 功能时,就必须关注程序的平台可移植性, JNI 标准要求本地代码至少能工作在任何Java 虚拟机环境。简而言之,跨平台的 Java 调用不了跨平台的 C/C++,使程序丧失了跨平台性,这就是 JNI 的副作用。而大多数不可避免的情况是:已存在用 C/C++ 写的程序/库或者 Java 语言不支持程序所要实现的特性,比如 ffmpeg 是由 C 编写的,则必须要通过 JNI 实现调用。