本篇博客代码及资源下载 : https://download.csdn.net/download/han1202012/10382762

  • 一. 音视频基础
    • 1. 音频基础
      • (1) 声音要素
      • (2) 心理声学模型
    • 2. 音频信号处理
      • (1) 音频信号量化过程
      • (2) PCM 音频参数 简介
    • 3. 音频压缩
      • (1) 有损压缩
      • (2) 频域遮蔽效应
      • (3) 时域遮蔽效应
    • 4. 音频编解码
      • (1) 音频编解码器
    • 5. AAC 编解码器
      • (1) AAC 编解码器 简介
      • (2) AAC 规格
      • (3) AAC 格式
      • (4) AAC 编解码库
  • 二. 视频基础
    • 1. MPEG-4 标准
      • (1) MPEG-4 标准 简介
      • (2) 封装格式 简介
      • (3) 编码格式 简介
    • 2. 封装格式 和 编码格式简介
      • (1) 封装 和 编码 格式 简介
    • 3. YUV 和 RGB 像素格式 简介
      • (1) 像素格式简介
      • (2) RGB 图像 在内存中的 存储方式
      • (3) YUV 像素格式
    • 4. 视频参数简介
      • (1) MP4 格式封装简介
      • (2) H264 | AVC 视频编码标准
    • 5. 编码帧相关概念
      • (1) 帧类型简介
      • (2) 帧类型 与 GOF ( Group Of Frame ) 组帧
      • (3) 帧 相关 参数
      • (4) 视频编码器 简介
  • 二. Android Studio 环境安装配置
    • 1. Android Studio 安装
      • (1) Android Studio 的各种地址
      • (2) SDK NDK 安装
      • (3) 模拟器安装
    • 2. Android Studio 相关工具介绍
      • (1) SDK 简介
      • (2) NDK 简介
      • (3) 关于 Android 版本的说明
    • 3. 测试 Android 开发环境 ( 测试 包含 C/C++ 的 Android 工程 )
      • (1) 测试工程
  • 三. FFMPEG 交叉编译
    • 1. NDK 简介
      • (1) NDK 安装
      • (2) ndk-build 构建脚本 ( FFMPEG不使用该脚本 使用 CMake )
      • (3) JNI 简介
    • 2. ABI ( Application Binary Interface ) 应用程序二进制接口 简介
      • (1) ABI 简介
      • (2) NEON 简介
    • 3. 交叉编译环境安装
      • (1) Ubuntu 虚拟机 下载
      • (2) Ubuntu 虚拟机 安装
      • (3) 创建 root 用户 并使用 root 用户登录 图形界面
      • (4) 虚拟机网络设置
      • (4) 配置 Ubuntu 的软件环境
    • 4. FFMPEG 编译前的准备工作
      • (1) FFMPEG 源码下载
      • (3) FFMPEG 源码编译步骤
      • (4) FFMPEG 源码编译配置简介
    • 5. 编译详细过程
      • (1) 环境变量设置
      • (2) configure 配置详解
      • (3) 编写 FFMPEG 编译的自动化 shell 脚本
    • 6. 正式编译
      • (1) 使用命令行进行编译
      • (2) 使用编译脚本进行编译
  • 四. Android Studio 中项目导入 FFMPEG 及 配置
    • 1. Android 项目创建
      • (1) 创建 工程
    • 2. Android 项目 配置 ( 重点 )
      • (1) 项目配置
    • 3. Android 项目 代码分析
      • (1) JNI 使用流程 简介
      • (2) 打印 FFMPEG 编译时的配置






一. 音视频基础




1. 音频基础


(1) 声音要素


声音要素 :

  • 1.音调 : 声音的频率, 即每秒钟震动的次数; 下面举个栗子:
    • ( 1 ) 人声对比 : 声音频率由大到小排列 : 小孩声音频率 > 女人声音频率 > 男人声音频率;
    • ( 2 ) 音乐领域 : 声音频率由小到大排列 : do (1) < re (2) < mi (3) < fa (4) < so (5) < la (6) < si (7);
  • 2.音量 : 声音震动的幅度决定, 震动幅度大 音量大, 震动幅度小, 音量小;
  • 3.音色 : 音色即声音的材质, 与谐波有关, 如 钢琴的 C1 音符 与 小提琴的 C1 音符频率是一样的, 都是 261 Hz, 但是明显声音不同, 这就是由于其谐波不同导致的;
    • ( 1 ) 声音波形越接近正弦波, 声音越好听, 波形越乱, 越嘈杂;
  • 4.声音要素分析 :
    • ( 1 ) 甲 和 乙 的震动频率是一样的, 音调相同; 丙 的音调 要高于 甲 和 乙;
    • ( 2 ) 乙 和 丙 的震动幅度是一样的, 其 音量 相同, 乙的音量要大于 甲;
    • ( 3 ) 丁的声音没有任何规律, 是噪音, 音质差;


(2) 心理声学模型


心理声学模型 介绍 :

  • 1.人的听觉范围 : 人能听到 20 Hz ~ 20000Hz 之间的声音;
    • ( 1 ) 次声波 : 低于 20Hz 的声波 是 次声波;
    • ( 2 ) 超声波 : 高于 20000 Hz 的声波 是 超声波;
  • 2.人的发音范围 : 人能发出 85 Hz ~ 1100 Hz 的声音;
  • 3.其它动物的发音听觉范围 : 难怪自然灾害动物都比较警觉;
    • ( 1 ) 狗 : 听觉 15 Hz ~ 50000 Hz, 发音 452 Hz ~ 1800 Hz;
    • ( 2 ) 猫 : 听觉 60 Hz ~ 65000 Hz, 发音 760 Hz ~ 1500 Hz;
    • ( 3 ) 蝙蝠 : 听觉 1000 Hz ~ 120000 Hz, 发音 10000 Hz ~ 120000 Hz;
    • ( 4 ) 海豚 : 听觉 150 Hz ~ 150000 Hz, 发音 7000 Hz ~ 120000 Hz;




2. 音频信号处理


(1) 音频信号量化过程


音频信号量化过程 :

  • 1.模拟数据 : 自然界中的连续的模拟数据;
  • 2.采样 : 在模拟数据中设置 若干 个采样时间点, 每个采样点 从模拟数据中 取该采样点 时间 对应的数据值大小;
    • ( 1 ) 采样率 : 每秒钟的采样个数, 44100 Hz 采样率 就是每秒钟有 44100 个采样点;
    • ( 2 ) 常用采样率 : 16KHz, 32KHz, 44.1KHz, 48K Hz;
  • 3.量化 : 每个采样点的值 根据震动幅度的大小, 将震动幅度 分成若干个级别, 如 0 ~ 256, 0~ 65535 等;
    • ( 1 ) 采样位数 : 采样位数 为 8 位, 就是讲震动幅度分成 256 个级别, 采样位数为 16 位, 就是将震动幅度分为 65536 个级别;
  • 4.编码 : 将采样值 的大小 根据 震动幅度, 编码成 8位 或 16 位 的数字, 将这些数字按照一定顺序排列起来;
    • ( 1 ) 采样值 : 采样值 是 无符号数, 没有负数, 0 是最小值;
    • ( 2 ) 声道数量 : 如 单声道, 立体声, 5.1 环绕声;
    • ( 3 ) 码率( 传输速度 ) : 采样率 * 采样位数 * 声道数 , 其结果是 1 秒钟的 位数, 单位是 bps ( bit per second 比特每秒 ) ;
  • 5.数字信号 : 将编码 转为 0 1 组成的 二进制数字信号, 在物理硬件上传输;


(2) PCM 音频参数 简介


PCM 音频参数简介 :

  • 1.采样率 : 44100 Hz ( CD 采样率 ), 48000 Hz ( DVD 采样率 );
    • ( 1 ) 采样率单位 : 44100 Hz 是 1 秒钟 采集 44100 个声音大小样本;
    • ( 2 ) 采样率质量 : 采样率 值 越大, 越真实, 质量越高;
  • 2.通道 : 左声道 右声道. 如果是双声道 那么 每个样本需要采集 2 个声音样本;
    • ( 1 ) 单声道 : 如果采样率 为 44100 Hz, 单声道, 那么这个音频 1秒钟采集 44100 个样本;
    • ( 2 ) 立体声 : 如果采样率 为 44100 Hz, 立体声, 就是分左右声道, 那么 1 秒钟采集 88200 个 样本;
  • 3.样本大小 : 每个采样声音样本的大小, 样本格式大小越大, 声音质量越好;
    • ( 1 ) 16 位 : 每个样本 2 字节, AV_SAMPLE_FMT_S16 格式;
    • ( 2 ) 32 位 : 每个样本 4 字节, AV_SAMPLE_FMT_FLTP 格式, 一般声卡最高支持到 24 位, 无法播放 32 位的声音;
    • ( 3 ) 重采样 : 如果声音样本大小是 32位的, 声卡是播不出 32 位声音的, 需要将其 重采样 为 16 位, 在传给声卡播放;
    • ( 4 ) 查看本电脑的播放设置 : 插图
  • 4.样本类型 : PCM 数据有两种存放方式, ① 一种是普通格式, 又叫交错格式, ② 另外一种是平面格式;
    • ( 1 ) 普通格式 ( 交错格式 ) : AV_SAMPLE_FMT_S16 格式, 每个样本 2 字节, b1 b2 分别是第 1 和 第 2 字节, 那么该格式存放格式就是 两个 字节 交替存放, 如 b1 b2 b1 b2 b1 b2 b1 b2
    • ( 2 ) 平面格式 : AV_SAMPLE_FMT_S16P 格式, 每个样本 2 字节, b1 b2 分别是第 1 和 第 2 字节, 那么该格式存放格式是 第 1 字节存放在一起在前半部分, 第 2 字节 存放在一起, 在后半部分, 如 b1 b1 b1 b1 b1 b1 b2 b2 b2 b2 b2 b2;




3. 音频压缩


(1) 有损压缩


有损压缩 :

  • 1.压缩方法 : 将采集到的 冗余信息 删除;
  • 2.冗余信息简介 : 冗余信息 包括 ① 听不到的音频信息 ② 被遮蔽的音频信号;
    • ( 1 ) 听不到的信息 : 人耳 听觉范围 外的 音频信号 如 ① 超声波 ② 次声波;
    • ( 2 ) 被遮蔽的音频信号 : 这些被遮蔽的信号分为 ① 频域掩蔽 和 ②时域掩蔽;


(2) 频域遮蔽效应


频域遮蔽效应 :

  • 1.频率最小可闻域 : 每个 频率都有一个声音强度的阈值, 小于这个阈值就听不到这个频率的声音 了, 每个频率的阈值都不一样;
  • 2.高音量掩蔽提升阈值 : 如果 有一个能量很大的声音出现, 该声音前后的频率的阈值会提高, 即 每个 频率在每个时间段的 最小可闻阈值 不一样;
  • 3.删除冗余信息 : 每个时间段的每个频率 最小可闻阈值 之下的声音 人耳是听不到的, 可以删除;
    • ( 1 ) 横轴说明 : 下图中的横轴是 频率值, 在 频率 最右侧, 即 频率高于 10^4 之后, 不管发出多高的音量, 人耳也听不到, 即超声波音量在高也听不到, 这些听不到的声音可以删除;



(3) 时域遮蔽效应


时域遮蔽效应 : 当 强音信号 和 弱音信号 ① 同时发音 或 ② 发音时间接近的时候, 会出现遮蔽效应;

  • 1.同时掩蔽 : 强音 和 弱音 信号同时发音时, 弱音信号会被掩蔽;
  • 2.前掩蔽 : 人耳 在 停到 强音 信号 之前的 一段时间, 发出的弱音信号 会被掩蔽, 这段时间非常短, 大概在 几十毫秒左右;
  • 3.后掩蔽 : 人耳 听到 强音信号消失后, 才能听到 弱音信号, 这段时间的弱音信号被掩蔽, 大概 一百 毫秒左右;





4. 音频编解码


(1) 音频编解码器


音频编解码器 : 混个脸熟就行, 详细的编解码过程之后再看;

  • 1.OPUS : 最新的编解码器, 新能最好; 但是 RTMP 目前 支持 AAC Speex, 不支持 OPUS 编解码器;
  • 2.AAC : 直播中使用较多, 音质要求比较高. 延迟也高; 其目的是为了替代上一代的 Mp3 编解码;
  • 3.Vorbis : Ogg Vorbis, 类似于 MP3.
  • 4.Speex : 除了音频编解码之外, 提供 回音消除, 降噪 等高级功能;
  • 5.iLBC :
  • 6.AMR :
  • 7.G.711 : 固话使用就是 该 音频 编解码器;
  • 8.性能对比 : OPUS > AAC > Virbis; 下面的两张图说明 OPUS 无论是 音频质量 还是 音频延迟, 在任何码率下 其性能都是最好的;
  • 9.码率 与 延迟 新能 分析图 : 横轴是码率 ( Bitrate 单位 kbps ) , 纵轴是 延迟 ( Delay 单位是 ms );
  • 10.码率 与 声音质量性能分析图 : 横轴是码率 ( Bitrate 单位 kbps ) , 纵轴是 声音质量;




5. AAC 编解码器


(1) AAC 编解码器 简介


AAC 简介 :

  • 1.MP3 格式 : MP3 格式 是基于上一代 MPEG-2 标准进行开发的, 该方式压缩是有损压缩, 无法 100% 还原;
  • 2.AAC 压缩 : 基于 MPEG-4 标准, 使用 SBR 和 PS 技术, 使压缩率增高, 同时保证音质好;
  • 3.应用范围广 : 目前 ① 90% 的直播使用的是 AAC 编码, ② RTMP 支持 AAC 编码; ③ AAC 能保证 音频 的高保真;
  • 4.AAC 规格 : ① AAC LC, ② AAC HE v1, ③ AAC HE v2;


(2) AAC 规格


AAC 规格 :

  • 1.AAC LC 规格 : 单纯的 AAC 编解码技术;
    • ( 1 ) 低复杂度 ( Low Complexity ) : 码流 是 128Kbps.
  • 2.AAC HE V1 规格 : 在 AAC 编解码技术的基础上 , 增加了 SBR 技术;
    • ( 1 ) SBR 技术 : Spectral Band Replication 分频复用技术, 将音频的频带分成 低频 和 高频 分别进行编码, 降低 低频 信号的采样率, 提高高频信号采样率; 码流 64Kbps;
  • 3.AAC HE V2 规格 : 在 AAC 编码技术基础上 增加了 SBR 技术, 又增加了 PS 技术;
    • ( 1 ) PS 技术 : Parametric Stereo 参数立体声 技术, 双声道 一个声道 完整保存, 另一个声道保存差异数据; 码流 32Kbps ;


(3) AAC 格式


AAC 格式 :

  • 1.ADIF ( Audio Data Interchange Format ) 格式 : 将音频信息 ( 采样率, 采样位数 等 ) 存放在文件头处, 文件只能从开头播放, 这种格式常用于在磁盘中保存 音频数据 ;
  • 2.ADTS ( Audio Data Transport Format ) 格式 : 音频信息 存放在每一帧 数据的开始位置, 可以再音频流的任意位置解码, 这种格式用于实时音频流传输解码;
    • ( 1 ) 弊端 : 该中格式 每帧 数据都要有一个 同步字, 其大小要比 ADIF 格式的要大很多;


(4) AAC 编解码库


AAC 编解码库 :

  • 1.Libfdk_AAC 编码库 : 性能最好, 推荐使用这个;
  • 2.ffmpeg AAC 编码库 :
  • 3.libfaac 编码库 :
  • 4.libvo_aacenc 编码库 : 已经淘汰;






二. 视频基础




1. MPEG-4 标准


(1) MPEG-4 标准 简介


MPEG-4 标准概述 :

  • 1.概念 : MPEG-4 是用于 ①音频 ②视频 信息 的 压缩编码 的 标准;
  • 2.用到的 MPEG-4 文档内容 : 在 MPEG-4 文档的 Part 14 定义了 文件格式 相关内容, MPEG-4 文档的 part 15 定义了 AVC 文件格式;
  • 3.压缩算法 : H264 压缩算法, AVC 压缩算法 ;

媒体文件播放流程 : 封装 -> 解码 -> 重采样 -> 像素格式转换;

  • 1.封装 : 从 文件 中将 音频 或 视频 读取出来 ;
  • 2.解码 : 将读取出来的内容解压出来;
  • 3.重采样 : 将视频转换成显卡支持的格式, 音频转换为声卡所支持的格式;
  • 4.像素格式转换 : 视频需要做像素格式转换;


(2) 封装格式 简介


常用封装格式简介 :

  • 1.AVI 格式 : 该格式的可以存放任意压缩格式的媒体数据, 甚至可以存放没有压缩过的数据;
  • 2.FLV 格式 : FLV 是一个流媒体格式, 直播 经常会用到;
  • 3.TS 格式 : TS 也是一种流媒体格式, 一般网络电视使用的是这种格式;
  • 4.ASF 格式 : 微软支持的流媒体格式, 适合做点播;
  • 5.MP4 格式 : MPEG-4 中定义的封装格式;


(3) 编码格式 简介


常用的视频编码格式简介 : 视频都是有损压缩格式;

  • 1.H264 格式 : 在文档的 Part10 介绍, 效率很高的一种编码格式;
  • 2.WMV 格式 :
  • 3.XviD 格式 : 在文档的 Part2 介绍,
  • 4.MJPEG 格式 : 这种格式每一帧画面都是独立的, 压缩率很低, 一般摄像机拍摄的原始视频是这种格式的;
  • 5.上述格式对比总结 : H264 WMV XviD 三种格式的算法都是根据前后帧的关系进行压缩, 压缩的效率要远远高于 MJPEG 格式, 同样质量大小的视频, MJPEG 的大小是 其它三种压缩格式的好几倍;

常用的音频编码格式简介 : 音频格式可以分为 有损压缩 和 无损压缩;

  • 1.AAC 格式 : 有损压缩格式;
  • 2.MP3 格式 : 有损压缩格式, 早期的音频格式;
  • 3.APE 格式 : 无损压缩, 与原始声音一样;
  • 4.FLAC 格式 : 无损压缩;




2. 封装格式 和 编码格式简介


(1) 封装 和 编码 格式 简介


封装模型 :

  • 1.封装模型简介 : 按照次序排列 : 封装格式头 -> 视频编码帧 -> 音频编码帧 -> 视频编码帧 -> 音频编码帧 … ( 重复视频音频编码帧 )
  • 2.封装格式头 : 主要封装 box 音视频 相关 信息, ①视频压缩编码格式, 视频关键帧索引, ②音频压缩编码格式 等内容;
  • 3.封装视频音频次序 : 视频编码帧 和 音频编码帧 帧率不是完全一致的, 只要音频帧帧率大于等于视频帧即可;
  • 4.视频编码帧 : 以 H264 编码规则举例 :
    • ( 1 ) NAL 层 : 网络提取层数据, 包含了网络提取层头部信息, 用于网络传输, 头部信息中包含了该帧的相关信息, 包括是是否是关键帧, B 帧, P 帧 等信息 ;
    • ( 2 ) VCL 层 : 视频编码层;
    • ( 3 ) SPS : 表示序列参数设置, 如关键帧信息;
    • ( 4 ) PPS : 图像参数, 如 图像宽高 等; 如果没有封装头, 视频也能根据 SPS 和 PPS 进行解码播放; 解码的时候会先解析 SPS 和 PPS 参数;
    • ( 5 ) 解码为 YUV : 视频编码帧 最终 解码为 YUV 格式, Y 表示灰度( 如果只解析 Y 就是黑白视频图像 ) , UV 表示色彩;
    • ( 6 ) YUV 转换为 RGB : YUV 格式的视频 需要 转为 RGB 来进行显示, 解压出来的数据非常大 1 秒钟几百 M 的数据, 这个过程开销很大 1 分钟 几个 G , 注意优化;
    • ( 7 ) 软解码 : 使用 CPU 实现, 耗电量大, 兼容性强, 性能强(1秒100帧以上) ,
    • ( 8 ) 硬解码 : 协处理器 实现, 解码逻辑直固化在硬件上, 但是性能固定限制 (每秒固定帧如60帧), 兼容性差;
  • 5.音频编码帧 :
    • ( 1 ) 压缩格式 : AAC 有损压缩格式, APE, FLAC 无损压缩格式;
    • ( 2 ) 原始格式 : PCM 原始格式, 音频大小即使是原始的格式 但是比起视频来说数据量也很小;
    • ( 3 ) 解码为 PCM FLT 格式 : AAC 解码为 FLT 格式, 方便浮点运算, float 4 字节 32 位, 无损格式解码为 PCM 格式;
    • ( 4 ) 重采样 : 将 PCM 或 FLT 格式转为声卡支持的采样位数, 一般声卡支持 16 位, 好的支持 24 位的;




3. YUV 和 RGB 像素格式 简介


(1) 像素格式简介


像素 格式 简介 :

  • 1.视频压缩格式 : H264 是压缩格式, 这是解码前的格式, 这些格式都需要①先解压, 然后②转为像素格式播放;
  • 2.RGB 格式 : RGBA, BGRA, RGB32, ARGB32, 其中 R 代表红色, G 代表绿色, B 代表蓝色, A 代表透明度,
  • 3.YUV 格式 : Y 代表灰度, UV 代表色彩, H264 的算法是基于 YUV 格式的, YUV 要比 RGB 要小, 一个像素 RGB 需要 3 字节 ( 24 Bit), YUV 的话需要 12 Bit ( 位 ), FFMPEG 有转换接口, 推荐使用 显卡 GPU Shader 进行转换 ( GPU 处理像素转换效率很高 ), 节省 CPU 资源;
    • ( 1 ) YUV -> R 转换公式 : R = Y + 1.4075 * ( V - 128 );
    • ( 2 ) YUV -> G 转换公式 : G = Y - 0.3455 * ( U - 128 ) - 0.7169 * ( V - 128 );
    • ( 3 ) YUV -> B 转换公式 : B = Y + 1.779 * ( U -128 );


(2) RGB 图像 在内存中的 存储方式


RGB 在内存中的存储方式 :

  • 1.存放次序 : RGB 在 内存中是按照从低位到高位 BGR 进行存放的, 是倒着存放的, 如 0 字节存放 B, 1 字节存放 G, 2 字节存放 R ;
  • 2.对齐操作干扰读取序列 : 有时候为了提高运算效率, 会让像素值是 4 的倍数, 方便对齐, 如果此时宽度是 3 个像素, 就会在 每行补一个 RGB 都是 0 值的像素, 这时候 第四个像素值 的索引就是 4 (第一行 0, 1, 2, 3, 将 3 索引补成了 0);
  • 3.最佳操作 : 尽量使用 4 的倍数的像素值, 整块内存进行操作, 运算一次即可拷贝整块内存, 如果出现上述情况, 就需要逐行读取, 可能要拷贝几百到几千次, 根据行数决定;


(3) YUV 像素格式


YUV 像素格式简介 :

  • 1.Y 意义 : Y 代表亮度, 是灰度值, 单纯的使用 Y 就是黑白电视机;
  • 2.U V 意义 : U 和 V 代表色度值, U V 与 Y 结合可以转换为 RGB 颜色值;
  • 3.YUV 4:4:4 采样 : 每个像素都有一个 YUV 对应, 一个像素大小也是 3 字节, 与 RGB 一样;
  • 4.YUV 4:2:2 采样 : 0 Y 对应 0 UV, 1 Y 对应前一个 0UV, 第二个 Y 使用前一个 UV, 两个灰度 公用一个色度, 每两个像素就节省 2 个字节;
  • 5.YUV 4:2:0 采样(最常用的) : 四个 灰度 公用一个 UV 色度值, 四个 灰度 是 上下左右 2 x 2 挨着的色度值. 每四个像素点节省 3 个 UV 值, 即 4 个像素点 使用 6 字节 ( 4 Y 1U 1V ) , 平均每个像素点占用 1字节;
  • 6.YUV 4:2:0 P 平面存储方式 : 平面形式存放, 现将 Y 全部存放, 后面再存放 U , 最后存放 V 数据;




4. 视频参数简介


(1) MP4 格式封装简介


MP4 格式分析 : 列举一些头部封装信息;

  • 1.MP4 格式文档 : MPEG-4 标准的 Part14 文档, 主要讲解 MP4 文件的格式;
    • ( 1 ) 文档下载地址 : , 解压, 其中的 ISO_IEC_14496-14_2003-11-15.pdf 就是这部分文档 ;
  • 2.ftyp 字段 : file type ( 文件类型 ), 表示这个文件属于那种类型;
  • 3.moov 字段 : metadata container ( 元数据容器 ), 表示存放媒体信息的位置;
  • 4.mvhd 字段 : movie header ( 媒体信息头 ), 存放文件的总信息, 如 视频长度, 创建时间 等信息;
  • 5.trak 字段 : track of stream container ( 媒体流容器 ), 该容器存放 视频流 或 音频流;
  • 6.mdhd 字段 : media header ( 媒体头部信息 ), 定义时间转换相关信息,
    • ( 1 ) TimeScale 时间 : 该值可以转换成真实的时间;
    • ( 2 ) 帧同步作用 : 每帧视频都有显示时间, 根据这个时间进行时间同步运算;


(2) H264 | AVC 视频编码标准


H264 编码标准层级 :

  • 1.视频编码层 ( VCL ) : 该层主要负责视频的编码 解码 等操作 ;
  • 2.网络抽象层 ( NAL ) : 该层主要进行数据的格式化, 并提供封装的头信息;

NAL 单元 :

  • 1.概念 : 每个数据帧就是一个 NAL 单元;
  • 2.帧分隔符 : 每帧前一般使用 00 00 00 01 或者 00 00 01 作为分隔符;
  • 3.首帧数据 : 通常 编码器 编码 生成的 第一帧数据是 PPS 和 SPS 数据, 接着就是 I 帧;




5. 编码帧相关概念


(1) 帧类型简介


帧类型简介 :

  • 1.I 帧 : 关键帧, 使用的压缩技术是 帧内压缩技术;
  • 2.P 帧 : 向前依赖, P 帧压缩时 参考 前一帧数据, 使用的压缩技术 是 帧间压缩技术;
  • 3.B 帧 : 前后依赖, B 帧压缩时 参考前一帧 同时 也 参考 后一帧 数据, 使用的压缩技术 也是 帧间压缩技术;
    • ( 1 ) 不适用于实时性较高的情况;


(2) 帧类型 与 GOF ( Group Of Frame ) 组帧


帧类型 与 GOF :

  • 1.I 帧 : I 类型 帧 是关键帧, 关键帧是一帧的 完整数据, 可以独立解码出来;
    • ( 1 ) 可独立播放的帧组 : 从数据中任意抽出连续帧 不一定能够播放, 必须是 关键帧 及 关键帧以后的帧 才能播放出来; 关键帧之前的数据如果没有前面的关键帧是解码不出来的;
    • ( 2 ) 低帧率应用 : 在实时性要求不是很高的监控环境中, 1秒钟一帧, 只要将关键帧解码显示出来即可;
    • ( 3 ) 关键帧丢失 : 如果关键帧丢失, 那么依赖于该关键帧的后面的 B 帧 和 P 帧 就会根据上一个关键帧来解码, 可能会出现错误;
    • ( 4 ) 设置关键帧的依赖帧数量 : 可设置 一个数量 如 30 帧, 依赖于一个 关键帧, 如果其依赖的关键帧丢失, 那么这 30 帧都出现错误;
  • 2.参考帧 : 除了关键帧意外, 其它类型的帧 信息都不全, 需要参考其余的帧进行解码;
    • ( 1 ) P 帧 参考帧 : P 帧 的 参照帧 是 前一帧 ;
    • ( 2 ) B 帧 参考帧 : B 帧的 参考帧 是 前一帧 和 后一帧 两帧 数据;
  • 2.B 帧 : B 帧解码 是 相对于 前一帧 和 后一帧 的变化 进行解码, 如果后一帧没有解码出来, 该 B 帧就无法解码出来,
  • 3.P 帧 : P 帧 解码是相对于前一帧的变化进行解码, P 帧的参考帧 是 前一帧, 按照 前后 次序解码 即可;
  • 5.解码顺序 和 播放顺序 : 由于 B 帧 是依赖于前一帧 和 后一帧进行解码, 势必无法进行顺序的解码, 解码的帧序号是跳跃进行的;
    • ( 1 ) 帧解码 播放 次序举例 : ① I 帧 ② B 帧 ③ B 帧 ④ P 帧 ⑤ B 帧 ⑥ B 帧 ⑦ P 帧 ⑧ B 帧 ⑨ P 帧
    • ( 2 ) 解码分析 : 如果 遇到 ② B 帧, 需要 前一帧 和 后一帧 解码, 如果 后一帧 还是 ③B 帧, 那么就先要将 后面的 ③B 帧先解出来, 然后返回来 解码 ② B 帧;


与 GOF 相关的 视频 故障 问题分析 :

  • 1.花屏 : GOF 中的 P 帧 或 I 帧 丢失, 会导致解码图像出现错误;
  • 2.卡顿 : 为了 防止花屏产生, 如果发现 P 或 I 帧丢失, 那么 整个 GOF 内的帧都不显示, 直到下一个 I 帧到来后显示, 这样就造成了 卡顿;


(3) 帧 相关 参数


帧 相关 参数 :

  • 1.SPS ( Sequence Parameter Set ) 序列集参数 : 存放内容 ① 帧数 ② 参考帧数目 ③ 解码图像尺寸 ④ 帧场编码模式选择标识 ;
  • 2.PPS ( Picture Parameter Set ) 图像参数集 : 存放内容 : ① 片组数目 ② 初始量化参数 ③ 去方块滤波系数调整标识 ④ 熵编码模式选择标识 ;


(4) 视频编码器 简介


视频编码器简介 :

  • 1.x264 :
  • 2.x265 :
  • 3.openH264 :






二. Android Studio 环境安装配置




1. Android Studio 安装


(1) Android Studio 的各种地址


Android Studio 下载 学习 地址 :

  • 1.下载页面 : https://developer.android.google.cn/studio/index.html
    • ( 1 ) 直接下载链接 : 点击下载 Android Studio 3.1.1 ;
  • 2. 开发者官网地址 : https://developer.android.google.cn/develop/index.html
  • 3.网站可直接访问 : 这是 Google 最新搭建了一个 Android 文档网站的镜像, 这个网站目前可以直接访问, 可以不使用代理 VPN 等手段;
  • 4. 官方的安装说明 : https://developer.android.google.cn/studio/install.html, 先设置 JAVA, JAVA_HOME 环境变量, 再安装 Android Studio ;
  • 5. Android Studio 工具主页 : https://developer.android.google.cn/studio/index.html
  • 6.Android Studio 功能介绍 : https://developer.android.google.cn/studio/features.html
  • 7. Android Studio 用户指南 : https://developer.android.google.cn/studio/intro/index.html
  • 8. Android Studio 预览版 : https://developer.android.google.cn/studio/preview/index.html, 黄色图标版本的, 出现各种错误需要排除, 作死的可以考虑下;

具体安装过程就不介绍了, 与普通软件安装过程差不多; 狂点 下一步 即可完成安装 ;



(2) SDK NDK 安装


安装 SDK NDK 等开发环境 :

  • 1.打开 SDK Manager : 安装 SDK, NDK, CMake 三种工具都在 SDK Manager 中进行安装, 点击 图标, 即可打开 SDK Manger;
  • 2.下载 SDK : 在 SDK Manager 中 的 SDK Platform 板块中, 下载任意一个 SDK 即可, 尽量下载高版本的 SDK, 推荐下载 25 以上版本的;
  • 3.下载 NDK 和 CMake : 在 SDK Tools 板块中, 选择 CMake 和 NDK 两个进行下载;


(3) 模拟器安装


Android 模拟器安装 :

  • 1.Android Studio 自带模拟器 :
    • ( 1 ) 进入 AVD Manager 界面 : 点击 按钮 打开 AVD Manager ( Android Virtual Device Manager ) 界面;
    • ( 2 ) 创建虚拟机 : 点击 Create Virtual Device 按钮, 开始创建 虚拟机;
    • ( 3 ) 选择屏幕尺寸 : 选择 屏幕尺寸, 以及屏幕参数;
    • ( 4 ) 选择 Android 系统版本 :
    • ( 5 ) 设置 Android 虚拟机的 参数 :
    • ( 6 ) 创建成功 :
    • ( 7 ) 打开虚拟机 :
  • 2.第三方模拟器 雷电安卓模拟器 : http://www.ldmnq.com/, 该模拟器是基于 VirtualBox 制作的;
  • 3.第三方模拟器 逍遥安卓模拟器 : http://www.xyaz.cn/, 该模拟器是基于 VirtualBox 制作的;
  • 4.GenyMotion 模拟器 : https://www.genymotion.com/, 可配置各种参数, 性能比较好;




2. Android Studio 相关工具介绍


(1) SDK 简介


SDK 目录分析 :

  • 1.platform-tools 目录 : 平台相关的工具, 主要是在操作系统 ( Windows Linux Mac ) 中独立使用的工具, 如 adb sqlite3 fastboot 等工具;
  • 2.tools 目录 : Android 开发环境中使用的工具, 如 性能监控工具, 调试工具. 一般都是在 Android Studio 中打开使用, 很少单独使用;
  • 3.platform 目录 : 存放下载的各个版本的 SDK ;
  • 4.ndk-bundle 目录 : 交叉编译工具, 用于编译 C/C++ 代码;
  • 5.build-tools 目录 : 编译工具, 存放下载的各个版本的 编译工具 ;


(2) NDK 简介


NDK 简介 :

  • 1.platforms 目录 : NDK 各个 Android 版本依赖的库, 每个对应 Android 版本都有 各种 CPU 架构对应的库 如 arm, mips, x86 等;
    • ( 1 ) platforms 目录内容 :
    • ( 2 ) 单个 Android 版本中对应的不同 CPU 架构库的目录 :
    • ( 3 ) 每种 CPU 对应的库不同 : 不同的 CPU 使用的 库 的类型是不一样的, 需要分别进行管理, 在不同的 CPU 架构上执行不同额 库;
  • 2.toolchains 目录 : 交叉编译工具链;

    • ( 1 ) 交叉编译 : 在 x86 平台上, 编译出 在 ARM 平台上运行的 库;
    • ( 2 ) 交叉编译的执行者 : windows-x86_64 代表交叉编译的执行者是 Windows 系统 x86 64位的 CPU, 每个交叉编译工具下都是 prebuilt 目录, 在每个 prebuilt 目录下都是 windows-x86_64 目录;
    • ( 3 ) 编译的库在哪个平台执行 : 在 arm 平台执行需要使用 aarch64-linux-android-4.9 工具, 在 mips 平台执行需要使用 mips64el-linux-android-4.9 工具, 不同的工具对应不同的平台;


(3) 关于 Android 版本的说明


Android 版本采用 : 下图是从 Android Studio 中截取的一张图;

- 1.蓝牙支持 : 如果你做的软件需要 BLE 蓝牙支持, 那么必须使用 4.3 以上的版本;
- 2.音频软件 : 如果开发的 APP 需要高性能音频, 则必须使用 4.4 以上的;





3. 测试 Android 开发环境 ( 测试 包含 C/C++ 的 Android 工程 )


(1) 测试工程


包含 C/C ++ 的 Android 工程 创建 与 运行 :

  • 1.创建工程 : Android Studio 必须要创建一个工程, 才能进入开发界面;
    • ( 1 ) 选择 C++ 11 支持 : 在创建工程界面, 需要勾选 Include C++ 11 选项;
    • ( 2 ) 选择 最小 版本 : 这里选择 4.0.3 版本, 基本是 100% 支持所有现有设备;
    • ( 3 ) 生成一个 Activity 首界面 :
    • ( 4 ) 设置 Activity 启动界面 : 设置 Activity 界面的 名称 和 界面 对应的 布局文件名称;
    • ( 5 ) 定制 C ++ 支持 : 在 定制 C ++ 支持 ( Customize C++ Support ) 界面, 选择 C ++ 11 标准;
    • ( 6 ) 等待应用配置编译 : 等待应用的 配置 编译, 这个过程比较长, 之后会自动进入开发界面;
  • 2.打开虚拟机 : 在 AVD Manager 中, 点击运行即可打开虚拟机;
  • 3.运行项目 : 点击 运行 按钮, 选择 要运行 APP 的设备, 即 刚才启动的虚拟机;

  • 4.运行成功 :






三. FFMPEG 交叉编译


编译失败大概率是因为版本错误, 确保使用以下版本进行编译 : ① Ubuntu 版本 : Ubuntu 16.04.4 64位 ② NDK 版本 : android-ndk-r14b ③ FFMPEG 版本 : ffmpeg-3.4 ;


1. NDK 简介


(1) NDK 安装


交叉编译环境安装 :

  • 1.NDK 简介 : Android 中 NDK 允许 开发者在 Android 中可以使用 C/C++ 进行开发, 调用 C/C++ 库;
  • 2.Native 层代码性能很高 : Java 语言的执行效率较低, Native 层的 C 语言代码效率很高, 做高效率的物理运算需要使用 C/C++ 代码实现;
  • 3.NDK 下载 : 在 Android Studio 中可以在 SDK Manager 中可以下载;
    • ( 1 ) 下载网站 : https://developer.android.google.cn/ndk/index.html


(2) ndk-build 构建脚本 ( FFMPEG不使用该脚本 使用 CMake )


>

构建脚本 ndk-build 作用 :

  • 1.启动构建 : ndk-build 是一个脚本文件, 用于启动 构建脚本;
  • 2.自动构建 : ndk-build 可以自动查找探测 开发环境 和 项目目录, 找到相应的内容, 进行自动构建;
  • 3.编译完成 : 自动构建完成后, 会自动生成一个 二进制文件;
  • 4.复制库 : ndk-build 会将生成的二进制文件复制到对应的目录进行使用;
  • 5.已过时 : 这是上一个版本的 构建工具, 需要配置 Android.mk 和 Application.mk 文件进行交叉编译;
  • 6.当前交叉编译方案 : Android Studio 3.0 以上都使用 CMake 进行交叉编译;


(3) JNI 简介


Java 原生接口 ( Java Native Interface ) JNI 简介 :

  • 1.作用 : Java 与 C/C++ 进行交互的接口;
  • 2.定义原生接口 : 先在 Java 定义 native 方法, 如 private native void hello(String str);
  • 3.导入库 :
static{    System.loadLibrary("native-lib");}
  • 4.动态链接库 ( .so 后缀 ) : 特点是 只把 函数的地址写进入, 运行时才动态加载这个库;
  • 5.静态链接库 ( .a 后缀 ) : 特点是 函数 在编译的时候, 直接把源码 复制到 本工程中;
    • ( 1 ) 缺点 : 使用静态库编译, 编译的时间比较长;
    • ( 2 ) 优点 : 只导出一个库, 可以隐藏自己调用的库;




2. ABI ( Application Binary Interface ) 应用程序二进制接口 简介


(1) ABI 简介


ABI ( Application Binary Interface ) 应用程序二进制接口 简介 :

  • 1.CPU 指令集 : 程序执行 最终 是转换成 CPU 的指令集来执行, 不同的 CPU 的指令集格式是不同的;
  • 2.ABI ( Application Binary Interface ) 概念 : ABI 中规定了 机器码 运行的时候 如何 与 系统 进行交互;
  • 3.ABI 包含的内容 :
    • ( 1 ) 机器码对应的 CPU 指令集 ;
    • ( 2 ) 内存存储 和 读取 的 字节次序 ;
    • ( 3 ) 可执行的二进制文件 ( 程序 或 共享库 ) 的格式;
    • ( 4 ) 对齐方式 ;
    • ( 5 ) 堆栈使用的约定, 函数调用的约定;




(2) NEON 简介


NEON 简介 :

  • 1.概念 : NEON ( ARM架构处理器扩展结构 ) , 是适用于ARM Cortex-A系列处理器的一种128位SIMD(Single Instruction, Multiple Data,单指令、多数据)扩展结构, 提供 标量/矢量 指令 和 寄存器;
  • 2.关于 NEON 的编译设置 :
    • ( 1 )




3. 交叉编译环境安装


(1) Ubuntu 虚拟机 下载


Ubuntu 下载 安装 :

  • 1.官网下载地址 : https://www.ubuntu.com/download/desktop
  • 2.官网下载选项 : https://www.ubuntu.com/download/alternative-downloads, 可选择要下载的版本;
  • 3.下载版本 : Ubuntu 16.04.4 LTS, 下载 64位 桌面版, ubuntu-16.04.4-desktop-amd64.iso ;

编译失败大概率是因为版本错误, 确保使用以下版本进行编译 : ① Ubuntu 版本 : Ubuntu 16.04.4 64位 ② NDK 版本 : android-ndk-r14b ③ FFMPEG 版本 : ffmpeg-3.4 ;



(2) Ubuntu 虚拟机 安装


Ubuntu 虚拟机安装 :

  • 1.虚拟机工具 : VMware 12 或 14 版本, 这里我使用的是 VMware Workstation 12 PRO 版本, 找个地方下载 安装激活, 推荐购买正版软件 ;
  • 2.创建虚拟机 : 安装好虚拟机后, 点击主页的 创建虚拟机, 选择典型安装;

  • 3.选择安装文件 : 选择 安装光盘映像文件, 从目录中选择下载的 文件 ubuntu-16.04.4-desktop-amd64.iso ;
  • 4.设置用户名密码 : 设置用户名 和 密码, 这个密码一定要记住, 之后登陆要使用;
  • 5.设置安装位置 : 设置 虚拟机 在电脑硬盘的位置 ;
  • 6.设置空间大小 : 至少 40 G 以上的空间;
  • 7.自定义硬件 : 选择 自定义硬件 按钮, 然后设置硬件, ① 内存分配 2 G, ② 主要是分配 处理器, 一般是有几个处理器就分配几个; ③ 虚拟机 网络 设置为 桥接网络 ;


  • 8.启动虚拟机 : 设置好以后, 启动虚拟机, 会自动安装 系统;
  • 9.登录操作系统 : 安装完后登录操作系统, 需要之前设置的 密码 ;
  • 10.打开终端 :


(3) 创建 root 用户 并使用 root 用户登录 图形界面


设置 root 用户 :

  • 1.解锁 root 用户 密码 : 使用 sudo passwd -u root 命令解锁 root 用户密码, 期间要输入当前用户的密码;
  • 2.设置 root 用户密码 : 使用 sudo passwd root 命令设置 root 用户密码, 期间要 输入 两次 root 用户密码;
  • 3.设置 root 用户界面登录 : 编辑 /usr/share/lightdm/lightdm.conf.d/50-unity-greeter.conf 文件, 在文件最后添加 如下内容;
    - ( 1 ) 编辑文件命令 : gedit /usr/share/lightdm/lightdm.conf.d/50-unity-greeter.conf ;
    - ( 2 ) 添加的内容 :
user-session=ubuntugreeter-show-manual-login=trueall-guest=false


- 4.重启系统 : 重启系统后可以看到, 用户名可以自己输入, 输入 root 用户名 和 密码 即可以 root 用户登录用户界面;

- 5.出现错误 : 此时会出现 /root/.profile 相关错误提示;

- 6.解决错误 : 使用 gedit /root/.profile 命令 编辑 .profile 配置文件, 在 最后一行最前面加上 “tty -s &&” 内容, 重启系统, 该问题消失;



(4) 虚拟机网络设置


VMware 三种网络设置 : ① 是否能访问外网 ② 是否有独立IP ③ 外部电脑是否可访问虚拟机

  • 1.桥接模式 ( Bridge ) : ① 访问外网, ② 虚拟机有 独立 IP 地址, ③ 外部电脑可以访问虚拟机;
  • 2.网络地址转换模式 ( NAT ) : ① 访问外网, ② 没有独立 IP 地址, ③ 外部电脑无法访问虚拟机; ④ 主机与虚拟机构成局域网可互相访问;
  • 3.主机模式 ( Host-only ) : ① 不能访问外网, ② 没有独立 IP 地址, ③ 外部电脑无法访问虚拟机;


虚拟机网络初始化 :

  • 桥接网络 不可用 处理方案 ( 参考 ) : https://jingyan.baidu.com/article/17bd8e521775fb85ab2bb8e0.html;
  • 1.步骤 1 : 删除设备管理器 网络适配器 中的两个虚拟机网卡;
  • 2.步骤 2 : 进入虚拟机网络编辑器, 点击 还原默认设置, 即可将网卡恢复到初始状态;


(4) 配置 Ubuntu 的软件环境


设置 Ubuntu :

  • 1.更新数据源 : 使用 apt-get update 命令, 更新数据源, 刷新软件库列表;
  • 2.安装 openssh-server : 使用 ssh 连接时的加密通信工具, 用于Xshell 或 SecureCRT 命令行连接使用; 使用 apt-get install openssh-server 命令安装;
  • 3.查看虚拟机 IP 地址 : 使用 ifconfig 命令查看 虚拟机 局域网 IP 地址;
  • 4.使用 SecureCRT 连接 虚拟机 :
    • ( 1 ) 下载 SecureCRT : https://download.csdn.net/download/han1202012/9993841
    • ( 2 ) 不能使用 root 用户 登录 : Ubuntu 16.04 不能使用 root 用户远程连接, 只能使用非 root 用户登录;
    • ( 3 ) 创建连接 :
    • ( 4 ) 设置用户密码 : 不能使用 root 用户;


    • ( 5 ) 连接成功 :
  • 5.安装 VIM : 该编辑工具用于在 命令行 编辑 文件使用;
  • 6.samba 共享工具安装 : 使用 apt-get install samba 命令安装, 该工具的作用是 将 windows 目录 与 Linux 共享 ;

    • ( 1 ) Ubuntu 中安装 samba : 使用 apt-get install samba 命令;
    • ( 2 ) 配置 samba : 使用 gedit /etc/samba/smb.con**f 命令, 编辑 /etc/samba/smb.conf** 文件, 在文件末尾添加如下配置;
      [root]
      comment=root
      path=/root
      browseable=yes
      readonly=no

    • ( 3 ) 设置 samba 用户 : 使用 smbpasswd -a root 命令 设置 root 用户权限, 期间需要输入两次访问密码;

    • ( 4 ) Windows 访问共享文件 : 进入 运行 界面, 访问 \虚拟机IP地址, IP地址使用 ifconfig 命令查看, 输入在 Linux 中设置的 samba 用户名 和 密码 即可访问共享文件;

      设置了 samba 用户权限就不会有拒绝访问的提示了;

    • ( 5 ) 查看共享目录 :

  • 7.NDK 工具安装 : 注意 要下载 Linux 64 位版本的 NDK 工具, 注意要下载 android-ndk-r14b 版本的, 最新版本编译不过去;

    • ( 1 ) 下载页面 : https://developer.android.google.cn/ndk/downloads/index.html
    • ( 2 ) 下载地址 : https://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip
    • ( 3 ) 放置位置 : 将 NDK 下载后放在 /root/FFMPEG 目录下;

编译失败大概率是因为版本错误, 确保使用以下版本进行编译 : ① Ubuntu 版本 : Ubuntu 16.04.4 64位 ② NDK 版本 : android-ndk-r14b ③ FFMPEG 版本 : ffmpeg-3.4 ;





4. FFMPEG 编译前的准备工作


(1) FFMPEG 源码下载


FFMPEG 源码下载 :

  • 1.FFMPEG 下载主页面 : http://ffmpeg.org/download.html

    • ( 1 ) 各个版本的源码列表界面 : http://ffmpeg.org/releases/
    • ( 2 ) 推荐下载 3.4 版本 : http://ffmpeg.org/releases/ffmpeg-3.4.tar.bz2, 之后的源码编译配置运行都以该版本为基础;
    • ( 3 ) 在 Ubuntu 中下载命令 : 在 Ubuntu 中可以使用 wget http://ffmpeg.org/releases/ffmpeg-3.4.tar.bz2 命令下载;
  • 2.Git 下载最新源码 : 使用 git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg 命令可以使用 Git 下载最新的版本;
  • 3.放置位置 : 将 FFMPEG 源码下载后放在 /root/FFMPEG 目录下;


(3) FFMPEG 源码编译步骤


FFMPEG 源码编译流程 :

  • 1.编译准备 : ① 源码解压 ② NDK 环境 ③ make 工具安装

    • ( 1 ) 解码源码 : 使用 tar -xvf ffmpeg-3.4.tar.bz2 命令, 解压源码到 FFMPEG 目录下 ;
    • ( 2 ) 文件准备 : 检查确保 ndk 和 ffmpeg 源码都已解压到 /root/FFMPEG 目录下;

    • ( 3 ) 安装 make 工具 : 一般 Ubuntu 都自带 make 工具, 如果没有使用 apt-get install make 命令安装;

  • 2.配置编译参数 : 使用 ./configure 命令 进行编译配置;
  • 3.编译 : 使用 make 命令编译, 使用多线程编译 make -j线程数, 如 make -j8, 我的电脑是 四核八线程的, 这里设置 j8 是使用 8 个线程编译;
  • 4.安装 : make install 命令 安装 编译好的程序, 将编译好的 库 和 头文件 复制到 指定的 目录中;

编译失败大概率是因为版本错误, 确保使用以下版本进行编译 : ① Ubuntu 版本 : Ubuntu 16.04.4 64位 ② NDK 版本 : android-ndk-r14b ③ FFMPEG 版本 : ffmpeg-3.4 ;



(4) FFMPEG 源码编译配置简介


configure 配置参数 :

  • 1.输出目录 : –prefix 参数设置输出路径;
  • 2.开启指定模块 : –enable 开启指定的模块, 如 硬解码 neon 等模块;
  • 3.禁止模块 : –disable 禁止某些模块, 如 禁止 ffmpeg 工具;
  • 4.交叉编译参数 : 给 gcc 指定交叉编译参数, 编译其它平台的库;




5. 编译详细过程


(1) 环境变量设置


如果熟悉可以不看本节的讲解内容, 直接在命令行设置环境变量, 设置内容在第 6 点中.

设置环境变量 : 这些设置可以设置到一个 shell 脚本中, 也可以使用

  • 1.设置 NDK 路径环境变量 : export NDK=/root/FFMPEG/android-ndk-r14b ;
  • 2.设置 PLATFORM 平台依赖库环境变量 : export PLATFORM=$NDK/platforms/android-21/arch-arm, 编译 基于 android 21 版本, 那么也需要来与 NDK 中的 21 版本下的 so 库 和 头文件 ;
    • ( 1 ) 依赖于 NDK 环境变量 : $NDK 与 /root/FFMPEG//root/FFMPEG/android-ndk-r14b 是等价的;
  • 3.设置 TOOLCHAIN 工具链常量 : export TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64, 配置交叉编译工具环境变量;
    • ( 1 ) 使用者 : 其中的 linux-x86_64 目录名称说明了 使用者是 Linux 操作系统 x86 CPU 架构, 64 位的系统;
    • ( 2 ) 使用位置 : 其中的 arm-linux-androideabi 目录名称说明了 编译出来是在 arm CPU 架构, linux 内核, androideabi 架构 上 运行的;
    • ( 3 ) 全路径 : /root/FFMPEG/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64, 这里前面使用 NDK 环境变量代替 /root/FFMPEG/android-ndk-r14b 路径;
    • ( 4 ) 包含的内容 : 其中包含了 用到的 所有的 交叉编译工具; 下面是部分截图;
  • 4.设置 CPU 架构常量 : export CPU=armv7-a, 主要是指定一个 CPU 架构 环境变量;
  • 5.设置输出目录 : export PREFIX=./android/$CPU , 指定编译完成的可执行文件输出到什么位置, 这个目录是 /root/FFMPEG/ffmpeg-3.4/android/armv7-a;
    • ( 1 ) 编译时所在的目录 : 如果使用 该环境变量 作为 输出目录, 那么必须在 /root/FFMPEG/ffmpeg-3.4/ 目录下进行编译;
  • 6.环境变量设置总结 :
export NDK=root/FFMPEG/android-ndk-r14bexport PLATFORM=$NDK/platforms/android-21/arch-armexport TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 export CPU=armv7-aexport PREFIX=./android/$CPU


(2) configure 配置详解


configure 编译配置分析 :

  • 1.设置输出路径 : –prefix=$PREFIX, 设置编译出的可执行文件输出到该目录中;
  • 2.指定编译完成后要运行的系统 : –target-os=android, 编译完成后在 android 系统中运行;
  • 3.指定交叉编译工具链名称前缀 : –cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- ,
    • ( 1 ) 默认的编译器 : 一般 C/C ++ 工程的默认编译器 是 gcc 或 g++;
    • ( 2 ) 交叉编译编译器 : 交叉编译的编译器在 NDK 目录中, 路径为 /root/FFMPEG/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc, 这里的 /root/FFMPEG/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi- 就是编译器的前缀, $TOOLCHAIN/bin/arm-linux-androideabi- 等价于 /root/FFMPEG/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi- ;
  • 4.指定 CPU 架构 : –arch=arm , arm 架构体系;
  • 5.指定 CPU 指令集 : –cpu=armv7-a , armv-7 指令集;
  • 6.指定系统依赖库位置 : –sysroot=$PLATFORM, 即 NDK 下 指定的 Android 版本号的 库 和 头文件;
  • 7.指定 gcc 参数 : –extra-cflags=”-I$PLATFORM/usr/include -fPIC -DANDROID -mfpu=neon -mfloat-abi=softfp “ , 指定 gcc 编译参数;
    • ( 1 ) 指定编译的头文件地址 : -I$PLATFORM/usr/include ;
    • ( 2 ) 编译动态链接库的参数 : -fPIC -DANDROID ;
    • ( 3 ) 指定使用的协处理器 : -mfpu=neon;
    • ( 4 ) 指定 软浮点 运算 : -mfloat-abi=softfp ;
  • 8.指定编译器 : –cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc;
  • 9.指定符号查看工具 : –nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm ;
  • 10.编译成动态库 : –enable-shared , 编译生成的库就是动态链接库;
  • 11.开启 CPU 运行时探测 : –enable-runtime-cpudetect;
  • 12.指定公共许可 : –enable-gpl , 开源相关的, 有些库 必须开源才能使用;
  • 13.指定编译时压缩库大小 : –enable-small, 后果是性能上有损失;
  • 14.指定本次编译为交叉编译 : –enable-cross-compile;
  • 15.开启指令优化 : –enable-asm ;
  • 16.支持 neon 协处理器 : –enable-neon;
  • 17.打开 jni : –enable-jni , 通过 jni 调用 java 调用 硬解码;
  • 18.指定编码 : –enable-decoder=h264_mediacodec ;
  • 19.指定硬件编码 : –enable-hwaccel=h264_mediacodec ;
  • 20.减少的编译模块 : 关闭这些模块, 可以更快的编译, 减少不必要的错误, android 中用不到这些模块;
    • ( 1 ) 连接符 : “\” 是连接符, 代表 下面的一行 与 本行 属于 一行数据, 同一行写不下 或者 处于格式美观需求 使用 连接符 将一行数据写成 若干行;
    --disable-debug \    --disable-static \    --disable-doc \    --disable-ffmpeg \    --disable-ffplay \    --disable-ffprobe \    --disable-ffserver \    --disable-postproc \    --disable-avdevice \    --disable-symver \    --disable-stripping 
  • 21.configure 完整配置命令行 : 复制该命令, 直接在 Linux 中执行即可, 注意要①先执行环境变量设置的命令, ②再执行配置命令;

①环境变量设置命令 :

export NDK=root/FFMPEG/android-ndk-r14bexport PLATFORM=$NDK/platforms/android-21/arch-armexport TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 export CPU=armv7-aexport PREFIX=./android/$CPU

②配置命令 :

./configure \    --prefix=$PREFIX \    --target-os=android \    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \    --arch=arm \    --cpu=armv7-a  \    --sysroot=$PLATFORM \    --extra-cflags="-I$PLATFORM/usr/include -fPIC -DANDROID -mfpu=neon -mfloat-abi=softfp " \    --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \    --nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm \    --enable-shared \    --enable-runtime-cpudetect \    --enable-gpl \    --enable-small \    --enable-cross-compile \    --enable-asm \    --enable-neon \    --enable-jni \    --enable-mediacodec \    --enable-decoder=h264_mediacodec \    --enable-hwaccel=h264_mediacodec \    --disable-debug \    --disable-static \    --disable-doc \    --disable-ffmpeg \    --disable-ffplay \    --disable-ffprobe \    --disable-ffserver \    --disable-postproc \    --disable-avdevice \    --disable-symver \    --disable-stripping 


(3) 编写 FFMPEG 编译的自动化 shell 脚本


这里只是简单介绍下 FFMPEG 的编译脚本如何编写, 编译也可以只使用上面的命令行进行编译;
编写编译脚本进行FFMPEG 的编译只是编译方式的一种;

FFMPEG 编译 shell 脚本 :

  • 1.创建脚本文件 : 一定要在 Linux 中创建脚本文件, 在 Ubuntu 中使用 gedit 进行创建编辑, 或者 使用 命令行 中的 vim vi 编辑器进行创建编辑 shell 脚本文件;
  • 2.设置执行方式 : #!/bin/bash , 表示该脚本默认使用 bash 执行;
  • 3.打印字符串到命令行 : echo “字符串” , 就可以向命令行中打印字符串;
echo "FFMPEG 编译脚本开始"
  • 4.设置变量 : 变量名称=变量内容, 在之后就可以使用 变量名称 替代 变量内容, 类似于 宏定义; 这里将 环境变量 设置成 shell 脚本变量;
NDK=root/FFMPEG/android-ndk-r14bPLATFORM=$NDK/platforms/android-21/arch-armTOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 CPU=armv7-aPREFIX=./android/$CPU
  • 5.配置设置 : 与命令行中的格式一样, 复制到脚本中即可;
./configure \    --prefix=$PREFIX \    --target-os=android \    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \    --arch=arm \    --cpu=armv7-a  \    --sysroot=$PLATFORM \    --extra-cflags="-I$PLATFORM/usr/include -fPIC -DANDROID -mfpu=neon -mfloat-abi=softfp " \    --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \    --nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm \    --enable-shared \    --enable-runtime-cpudetect \    --enable-gpl \    --enable-small \    --enable-cross-compile \    --enable-asm \    --enable-neon \    --enable-jni \    --enable-mediacodec \    --enable-decoder=h264_mediacodec \    --enable-hwaccel=h264_mediacodec \    --disable-debug \    --disable-static \    --disable-doc \    --disable-ffmpeg \    --disable-ffplay \    --disable-ffprobe \    --disable-ffserver \    --disable-postproc \    --disable-avdevice \    --disable-symver \    --disable-stripping 
  • 6.开始编译 : 使用 make 开始编译, 开启多线程编译使用 make -j2 就是开启双线程编译;
make
  • 7.安装编译结果 :
make install
  • 8.最终脚本内容 :
#!/bin/bashecho "FFMPEG 编译脚本开始"NDK=/root/FFMPEG/android-ndk-r14bPLATFORM=$NDK/platforms/android-21/arch-armTOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 CPU=armv7-aPREFIX=./android/$CPUecho "FFMPEG 编译选项配置"./configure \    --prefix=$PREFIX \    --target-os=android \    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \    --arch=arm \    --cpu=armv7-a  \    --sysroot=$PLATFORM \    --extra-cflags="-I$PLATFORM/usr/include -fPIC -DANDROID -mfpu=neon -mfloat-abi=softfp " \    --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \    --nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm \    --enable-shared \    --enable-runtime-cpudetect \    --enable-gpl \    --enable-small \    --enable-cross-compile \    --enable-asm \    --enable-neon \    --enable-jni \    --enable-mediacodec \    --enable-decoder=h264_mediacodec \    --enable-hwaccel=h264_mediacodec \    --disable-debug \    --disable-static \    --disable-doc \    --disable-ffmpeg \    --disable-ffplay \    --disable-ffprobe \    --disable-ffserver \    --disable-postproc \    --disable-avdevice \    --disable-symver \    --disable-stripping echo "FFMPEG 开始编译"makeecho "FFMPEG 编译结束"echo "FFMPEG 安装"make installecho "FFMPEG 编译脚本执行完毕"






6. 正式编译


(1) 使用命令行进行编译


正式开始编译 :

  • 1.设置环境变量 : 将下面的环境变量复制到命令行执行, 可以整体复制, 也可以逐条复制;
export NDK=/root/FFMPEG/android-ndk-r14bexport PLATFORM=$NDK/platforms/android-21/arch-armexport TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 export CPU=armv7-aexport PREFIX=./android/$CPU

  • 2.配置编译选项 : 直接复制到命令行, 然后点回车 即可设置成功, 该步骤主要是生成 Makefile 文件;
./configure \    --prefix=$PREFIX \    --target-os=android \    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \    --arch=arm \    --cpu=armv7-a  \    --sysroot=$PLATFORM \    --extra-cflags="-I$PLATFORM/usr/include -fPIC -DANDROID -mfpu=neon -mfloat-abi=softfp " \    --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \    --nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm \    --enable-shared \    --enable-runtime-cpudetect \    --enable-gpl \    --enable-small \    --enable-cross-compile \    --enable-asm \    --enable-neon \    --enable-jni \    --enable-mediacodec \    --enable-decoder=h264_mediacodec \    --enable-hwaccel=h264_mediacodec \    --disable-debug \    --disable-static \    --disable-doc \    --disable-ffmpeg \    --disable-ffplay \    --disable-ffprobe \    --disable-ffserver \    --disable-postproc \    --disable-avdevice \    --disable-symver \    --disable-stripping 

①开始编译后的命令行内容 :

②编译成功标志 :

  • 3.开始编译 : 执行 make 命令, 开始编译, 单线程编译会进行几分钟, 没有报错的话应该能编译成功, 编译失败大概率是因为版本错误, 确保使用以下版本进行编译 : ① Ubuntu 版本 : Ubuntu 16.04.4 64位 ② NDK 版本 : android-ndk-r14b ③ FFMPEG 版本 : ffmpeg-3.4 ;
make

执行完没报错就是执行成功 .

  • 4.安装 : 执行 make install 命令, 将编译出来的 头文件 和 动态库 复制到 指定的目录中, 即 ffmpeg-3.4/android/armv-7
make install

  • 5.编译结果 : 安装完成后的 头文件 和 库 , 在 –prefix=$PREFIX 配置选项中配置的结果输出路径是 ffmpeg-3.4/android/armv7-a;

编译失败大概率是因为版本错误, 确保使用以下版本进行编译 : ① Ubuntu 版本 : Ubuntu 16.04.4 64位 ② NDK 版本 : android-ndk-r14b ③ FFMPEG 版本 : ffmpeg-3.4 ;



(2) 使用编译脚本进行编译


执行 FFMPEG 编译脚本 :

  • 1.脚本内容 : 在 Ubuntu 中创建一个shell 脚本, 注意 一定要在 Ubuntu 中创建, 在 Windows 中创建的脚本无法执行; * Windows 与 Linux 中的换行符不一样 .* 必须在 Ubuntu 中创建并编辑脚本;

#!/bin/bashecho "FFMPEG 编译脚本开始"NDK=/root/FFMPEG/android-ndk-r14bPLATFORM=$NDK/platforms/android-21/arch-armTOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 CPU=armv7-aPREFIX=./android/$CPUecho "FFMPEG 编译选项配置"./configure \    --prefix=$PREFIX \    --target-os=android \    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \    --arch=arm \    --cpu=armv7-a  \    --sysroot=$PLATFORM \    --extra-cflags="-I$PLATFORM/usr/include -fPIC -DANDROID -mfpu=neon -mfloat-abi=softfp " \    --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \    --nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm \    --enable-shared \    --enable-runtime-cpudetect \    --enable-gpl \    --enable-small \    --enable-cross-compile \    --enable-asm \    --enable-neon \    --enable-jni \    --enable-mediacodec \    --enable-decoder=h264_mediacodec \    --enable-hwaccel=h264_mediacodec \    --disable-debug \    --disable-static \    --disable-doc \    --disable-ffmpeg \    --disable-ffplay \    --disable-ffprobe \    --disable-ffserver \    --disable-postproc \    --disable-avdevice \    --disable-symver \    --disable-stripping echo "FFMPEG 开始编译"makeecho "FFMPEG 编译结束"echo "FFMPEG 安装"make installecho "FFMPEG 编译脚本执行完毕"
  • 2.脚本使用前提 : ① root 用户 执行脚本, ② NDK 与 FFMPEG 源码都放在 /root/FFMPEG/ 目录下, ③ 版本号都一致.
  • 3.在强调一遍版本号 : 编译失败大概率是因为版本错误, 确保使用以下版本进行编译 : ① Ubuntu 版本 : Ubuntu 16.04.4 64位 ② NDK 版本 : android-ndk-r14b ③ FFMPEG 版本 : ffmpeg-3.4 ;
  • 4.修改 shell 脚本权限 : chmod 777 ffmpeg_android.sh ;
  • 5.执行脚本 : ./ffmpeg_android.sh 开始执行该 shell 脚本;


  • 6.查看执行结果 :







四. Android Studio 中项目导入 FFMPEG 及 配置




1. Android 项目创建


(1) 创建 工程


FFMPEG Android 工程创建 :

  • 1.创建项目 : ① 名称 FFMPEG_ANDROID, ② 域名 ffmpeg.han, ③ 包名 han.ffmpeg, ④ 最重要一点 引入 C ++ 11 支持;
  • 2.设置项目最低版本 : 选择 4.0 最低版本, 兼容 100% 机型; 不用修改 直接点下一步;
  • 3.选择一个默认的空界面 : 不用修改 直接点下一步;
  • 4.设置首界面的布局文件 : 不用修改 直接点下一步;
  • 5.设置 C ++ 标准版本 : 这里选择 C++ 11 版本;




2. Android 项目 配置 ( 重点 )


(1) 项目配置


项目配置 :

  • 1.拷贝 FFMPEG 头文件 到项目中 : 将 在 Ubuntu 编译出的 ffmpeg-3.4\android\armv7-a 目录下 的 include 目录拷贝到 Android 项目的 app 目录下, 与 src 目录, CMaleList.txt 是同一级文件;


  • 2.在 native 代码中引入头文件 : 程序自动生成的是 cpp 文件, 这是 C++代码, FFMPEG 是 C 语言的库, 因此这里我们导入头文件的时候需要使用 extern “C” 修饰; 此时头文件 无法 进行提示, 编译也会报错;
/* * 此处在 C++ 文件中引用一个 C 文件库 * 需要使用 extern "C" 来说明, 表明使用和编译其中的代码都按照 C 语言的规范进行 */extern "C"{ #include }

C语言 与 C++ 函数在库中存放的内容是不一致的, 如果要使用 C 语言规范, 需要特别标识出来;
如果只导入了头文件, 编译不会报错, 但是调用方法的时候还是会报错的, 如果调用其中的方法, 还要配置动态库;(再次强调一遍)


  • 3.CMakeList.txt 中配置头文件路径 : 使用 include_directories( 头文件相对路径 ) 进行配置, 配置了头文件路径后, 在 native 层的 C/C++ 代码中就可以导入其中的头文件;

    添加了头文件路径后, 才能导入头文件, 此时导入头文件不报错;
    如果只导入了头文件, 编译不会报错, 但是调用方法的时候还是会报错的, 如果调用其中的方法, 还要配置动态库;
    头文件代码提示 : * ① 执行该配置, 然后 ② Build (菜单) -> Rebuild Project 重新编译后, 头文件代码才可以提示, Ctrl + 鼠标左键 操作即可跳转到头文件代码中;


#添加头文件的路径#添加了头文件之后, 在 native-lib 目录下使用就不会报错了, 并可以使用 ctrl + 左键 直接跳转到该头文件中#添加的路径是相对路径, include 就是与 该 CMakeList.txt 同级的 include 目录include_directories(include)

  • 4.拷贝动态库到项目中 : 将在 Ubuntu 16.04 中 编译后的动态库拷贝到项目中的 libs 目录下;
    • ( 1 ) 拷贝来源 : 在 Ubuntu 16.04 中编译的输出结果在 ffmpeg-3.4/android/armv7-a/lib/ 目录下, 其中有 6 个动态库, 拷贝这 6 个动态库;
    • ( 2 ) 拷贝目的地 : 需要在 项目根目录/app/libs 目录下创建一个 Android 的 abi 指令集名称目录, 即 armeabi-v7a, 将 6 个动态库拷贝到 FFMPEG_ANDROID/app/libs/armeabi-v7a/ 目录中 ;

现在还是无法直接调用动态库 : 此时只是将动态库复制到了项目中, 还无法调用, 需要在 CMakeList.txt 中进行一系列的配置才能使用报错;
直接调用动态库的方法会


  • 5.添加动态库 : 使用 下面的 CMake 配置 添加动态库; avcodec 是动态库名称, SHARED 是动态库的类型, IMPORTED 是指直接导入动态库, 更详细的用法参考 https://cmake.org/cmake/help/v3.0/command/add_library.html ;
#添加动态库 (导入步骤 ①)add_library(    avcodec     #动态名称                SHARED      #库类型, 即 动态库                IMPORTED )  #导入方式

配置动态库需要三个步骤 : ① 添加动态库, ② 配置动态库路径, ③ 链接动态库 ;


  • 6.配置动态库路径 : 使用下面的代码 设置 动态库路径;

${CMAKE_CURRENT_SOURCE_DIR} 变量使用 : 配置的路径必须获取 CMakeList.txt 的当前位置, 即 使用该变量获取 , 再以该当前位置为标准, 扩展到其它相对路径, 不能使用 libs/armeabi-v7a/libavcodec.so 路径进行配置, 否则会报错;

#设置 avcodec 动态库路径属性 (导入步骤 ②)set_target_properties(  avcodec                         #动态库名称                        PROPERTIES                      #设置属性                        IMPORTED_LOCATION               #属性类型                        ${CMAKE_CURRENT_SOURCE_DIR}/libs/armeabi-v7a/libavcodec.so) #动态库的相对路径


  • 7.链接动态库 : 在自动生成的 native-lib 链接配置中添加 avcodec 库的链接, 之后便可以在 代码中调用 avcodec 中的函数了;
target_link_libraries( # Specifies the target library.                       native-lib                       avcodec  #(导入步骤 ③)                       # Links the target library to the log library                       # included in the NDK.                       ${log-lib} )


  • 8.指定编译指令集 :在 app/build.gradle 中 设定只编译 armeabi-v7a 一个指令集, 设定的位置是 android -> defaultConfig -> externalNativeBuild -> ndk 中;
android {    ... ...    defaultConfig {        ... ...        externalNativeBuild {            ... ...            ndk{                abiFilters "armeabi-v7a"            }        }    }    ... ...}


  • 9.gradle 中 设置动态库路径 : 在 app/build.gradle 中设置 动态库路径 ; 使用 sourceSets 任务设置, 设置的路径是 android -> defaultConfig -> sourceSets; 这个路径是相对路径, 即 app/buid.gradle 的同级目录, 即 app/libs;
    注意 : 一定要使用 单引号, 凡是涉及到文件的设置一律使用单引号设置;
    双引号会报错;
android {    ... ...    defaultConfig {        ... ...        sourceSets{            main{                jniLibs.srcDirs=['libs']            }        }    }   ... ...}

  • 10.build.gradle 配置文件示例 :
apply plugin: 'com.android.application'android {    compileSdkVersion 27    defaultConfig {        applicationId "han.ffmpeg"        minSdkVersion 14        targetSdkVersion 21        versionCode 1        versionName "1.0"        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"        externalNativeBuild {            //C ++ 标准版本            cmake {                cppFlags "-std=c++11"            }            //设置编译的过滤器, 这里我们只编译 armeabi-v7a 指令集的库            ndk{                abiFilters "armeabi-v7a"            }        }        sourceSets{            main{                jniLibs.srcDirs=['libs']            }        }    }    buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }    }    externalNativeBuild {        cmake {            path "CMakeLists.txt"        }    }}dependencies {    implementation fileTree(dir: 'libs', include: ['*.jar'])    implementation 'com.android.support:appcompat-v7:27.1.1'    implementation 'com.android.support.constraint:constraint-layout:1.1.0'    testImplementation 'junit:junit:4.12'    androidTestImplementation 'com.android.support.test:runner:1.0.2'    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'}


  • 11.CMakeList.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.4.1)# 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.#添加头文件的路径#添加了头文件之后, 在 native-lib 目录下使用就不会报错了, 并可以使用 ctrl + 左键 直接跳转到该头文件中#添加的路径是相对路径, include 就是与 该 CMakeList.txt 同级的 include 目录include_directories(include)#添加动态库 (导入步骤 ①)add_library(    avcodec     #动态名称                SHARED      #库类型, 即 动态库                IMPORTED )  #导入方式#设置 avcodec 动态库路径属性 (导入步骤 ②)set_target_properties(  avcodec                         #动态库名称                        PROPERTIES                      #设置属性                        IMPORTED_LOCATION               #属性类型                        ${CMAKE_CURRENT_SOURCE_DIR}/libs/armeabi-v7a/libavcodec.so) #动态库的相对路径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 )# 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 )# 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                       avcodec  #(导入步骤 ③)                       # Links the target library to the log library                       # included in the NDK.                       ${log-lib} )




3. Android 项目 代码分析


(1) JNI 使用流程 简介


JNI 使用流程 :

  • 1.创建 Native 层源文件 : 创建一个 C/C ++ 文件 native-lib.cpp, 该文件作为与 Java 层互动的接口文件;
  • 2.CMakeList.txt 中 配置该文件 : 设置 该 文件的 ①编译 配置, 并②查找 日志库, 之后③进行库的链接操作;
add_library( # 设置库的名称             native-lib             # 编译库的类型是 动态库             SHARED             # C/C++ 源文件的相对路径             src/main/cpp/native-lib.cpp )find_library( # 设置要查找的库的名称              log-lib              # 指定想要 CMake 去定位的 NDK 库的名称              log )target_link_libraries( # Specifies the target library.                       native-lib                       # Links the target library to the log library                       # included in the NDK.                       ${log-lib} )
  • 3.Java 层中的 本地方法 定义 :
    /**     * 本地方法需要在 'native-lib' 本地库中实现,     * 这个本地库必须打包在本应用中.     */    public native String stringFromJNI();
  • 4.Native 层中 的方法实现 :
JNICALLJava_han_ffmpeg_MainActivity_stringFromJNI(        JNIEnv *env,        jobject /* this */) {    std::string hello = "Hello From C++";    return env->NewStringUTF(hello.c_str());}
  • 5.加载动态库 : 在文件的开头, 使用静态代码块加载动态库;
    // Used to load the 'native-lib' library on application startup.    static {        System.loadLibrary("native-lib");    }
  • 6.使用 本地 方法 : 在界面中显示 从 本地 传来的 字符串;
        // Example of a call to a native method        TextView tv = (TextView) findViewById(R.id.sample_text);        tv.setText(stringFromJNI());


(2) 打印 FFMPEG 编译时的配置


打印 FFMPEG 编译配置 : 之前的步骤 ① Linux 平台编译 ② CMake 配置 ③ Gradle 配置 执行完后, 在执行下面的操作;

  • 1.导入头文件 :
/* * 此处在 C++ 文件中引用一个 C 文件库 * 需要使用 extern "C" 来说明, 表明使用和编译其中的代码都按照 C 语言的规范进行 */extern "C"{#include }
  • 2.获取 编译 配置方法 :libavcodec/avcodec.h 中定义的 avcodec_configuration 方法, 返回一个字符串;
/** * Return the libavcodec build-time configuration. */const char *avcodec_configuration(void);
  • 3.调用头文件中的函数 :
    //将编译时的配置信息返回给 Java 层, 并在界面中显示出来    std::string hello = avcodec_configuration();
  • 4.执行项目 : 打印出的配置 正好是我们在 编译配置 选项中设置的 各种配置;


本篇博客代码及资源下载 : https://download.csdn.net/download/han1202012/10382762

更多相关文章

  1. Android调用so文件(C代码库)方法详解
  2. Android(安卓)Studio 文件提前结束
  3. Android自动化编译设置AndroidManifest.xml中package值(包名)
  4. [转]android 系统权限大全的简介与内容
  5. Eclipse将android 类编译为jar类库
  6. Android中如何编译运行系统自带桌面Launcher2源码
  7. AndroidStudio使用NDK编译C/C++代码使用原生库
  8. Android中巧用Java反射机制
  9. Android应用框架之数据库框架Room简介

随机推荐

  1. Android模拟位置实现
  2. seekbar属性设置
  3. android通知栏快捷设置开发,即添加快捷磁
  4. Android中Gradle配置打包运行不同版本
  5. android 录制系统内置声音 android remot
  6. Android(安卓)使用SharePreferences保存L
  7. Android的context 和 getApplicationCont
  8. android判断scrollview滚动到底和滚动到
  9. Android Studio如何发布APK
  10. Android(安卓)Studio编译报错:Password ve