前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Android FFMPEG 开发】音视频基础 和 FFMPEG 编译 ( 音视频基础 | MPEG-4 标准 | Android 开发环境 | FFMPEG 交叉编译 | 安卓项目导入配置 )

【Android FFMPEG 开发】音视频基础 和 FFMPEG 编译 ( 音视频基础 | MPEG-4 标准 | Android 开发环境 | FFMPEG 交叉编译 | 安卓项目导入配置 )

作者头像
韩曙亮
发布2023-03-27 14:51:21
3.8K0
发布2023-03-27 14:51:21
举报
文章被收录于专栏:韩曙亮的移动开发专栏

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

文章目录

一. 音视频基础

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 下载 学习 地址 :

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


(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 中可以下载;

(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.导入库 :
代码语言:javascript
复制
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 下载 安装 :

编译失败大概率是因为版本错误, 确保使用以下版本进行编译 : ① 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 ) 添加的内容 :
代码语言:javascript
复制
user-session=ubuntu
greeter-show-manual-login=true
all-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 地址, ③ 外部电脑无法访问虚拟机;

虚拟机网络初始化 :

  • 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 连接 虚拟机 :
    • ( 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.conf 命令, 编辑 /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 版本的, 最新版本编译不过去;

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


4. FFMPEG 编译前的准备工作

(1) FFMPEG 源码下载


FFMPEG 源码下载 :

  • ( 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.环境变量设置总结 :
代码语言:javascript
复制
export NDK=root/FFMPEG/android-ndk-r14b
export PLATFORM=$NDK/platforms/android-21/arch-arm
export TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 
export CPU=armv7-a
export 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 ) 连接符 : “” 是连接符, 代表 下面的一行 与 本行 属于 一行数据, 同一行写不下 或者 处于格式美观需求 使用 连接符 将一行数据写成 若干行;
代码语言:javascript
复制
    --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 中执行即可, 注意要***①先执行环境变量设置的命令, ②再执行配置命令***;

①环境变量设置命令 :

代码语言:javascript
复制
export NDK=root/FFMPEG/android-ndk-r14b
export PLATFORM=$NDK/platforms/android-21/arch-arm
export TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 
export CPU=armv7-a
export PREFIX=./android/$CPU

②配置命令 :

代码语言:javascript
复制
./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 "字符串" , 就可以向命令行中打印字符串;
代码语言:javascript
复制
echo "FFMPEG 编译脚本开始"
  • 4.设置变量 : 变量名称=变量内容, 在之后就可以使用 变量名称 替代 变量内容, 类似于 宏定义; 这里将 环境变量 设置成 shell 脚本变量;
代码语言:javascript
复制
NDK=root/FFMPEG/android-ndk-r14b
PLATFORM=$NDK/platforms/android-21/arch-arm
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 
CPU=armv7-a
PREFIX=./android/$CPU
  • 5.配置设置 : 与命令行中的格式一样, 复制到脚本中即可;
代码语言:javascript
复制
./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 就是开启双线程编译;
代码语言:javascript
复制
make
  • 7.安装编译结果 :
代码语言:javascript
复制
make install
  • 8.最终脚本内容 :
代码语言:javascript
复制
#!/bin/bash
echo "FFMPEG 编译脚本开始"

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

echo "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 开始编译"
make
echo "FFMPEG 编译结束"

echo "FFMPEG 安装"
make install

echo "FFMPEG 编译脚本执行完毕"

6. 正式编译

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


正式开始编译 :

  • 1.设置环境变量 : 将下面的环境变量复制到命令行执行, 可以整体复制, 也可以逐条复制;
代码语言:javascript
复制
export NDK=/root/FFMPEG/android-ndk-r14b
export PLATFORM=$NDK/platforms/android-21/arch-arm
export TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 
export CPU=armv7-a
export PREFIX=./android/$CPU
  • 2.配置编译选项 : 直接复制到命令行, 然后点回车 即可设置成功, 该步骤主要是生成 Makefile 文件;
代码语言:javascript
复制
./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 ;
代码语言:javascript
复制
make

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

  • 4.安装 : 执行 make install 命令, 将编译出来的 头文件 和 动态库 复制到 指定的目录中, 即 ffmpeg-3.4/android/armv-7
代码语言:javascript
复制
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 中创建并编辑脚本;
代码语言:javascript
复制
#!/bin/bash
echo "FFMPEG 编译脚本开始"

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

echo "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 开始编译"
make
echo "FFMPEG 编译结束"

echo "FFMPEG 安装"
make install

echo "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” 修饰; 此时头文件 无法 进行提示, 编译也会报错;
代码语言:javascript
复制
/*
 * 此处在 C++ 文件中引用一个 C 文件库
 * 需要使用 extern "C" 来说明, 表明使用和编译其中的代码都按照 C 语言的规范进行
 */
extern "C"
{
 #include <libavcodec/avcodec.h>
}

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

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

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

代码语言:javascript
复制
#添加头文件的路径
#添加了头文件之后, 在 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 中进行一系列的配置才能使用报错; 直接调用动态库的方法会

代码语言:javascript
复制
#添加动态库 (导入步骤 ①)
add_library(    avcodec     #动态名称
	            SHARED      #库类型, 即 动态库
	            IMPORTED )  #导入方式

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

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

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

代码语言:javascript
复制
#设置 avcodec 动态库路径属性 (导入步骤 ②)
set_target_properties(  avcodec                         #动态库名称
                        PROPERTIES                      #设置属性
                        IMPORTED_LOCATION               #属性类型
                        ${CMAKE_CURRENT_SOURCE_DIR}/libs/armeabi-v7a/libavcodec.so) #动态库的相对路径
  • 7.链接动态库 : 在自动生成的 native-lib 链接配置中添加 avcodec 库的链接, 之后便可以在 代码中调用 avcodec 中的函数了;
代码语言:javascript
复制
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 中;
代码语言:javascript
复制
android {
    ... ...
    defaultConfig {
        ... ...
        externalNativeBuild {
            ... ...
            ndk{
                abiFilters "armeabi-v7a"
            }
        }
    }
    ... ...
}
  • 9.gradle 中 设置动态库路径 : 在 app/build.gradle 中设置 动态库路径 ; 使用 sourceSets 任务设置, 设置的路径是 android -> defaultConfig -> sourceSets; 这个路径是相对路径, 即 app/buid.gradle 的同级目录, 即 app/libs;

注意 : 一定要使用 单引号, 凡是涉及到文件的设置一律使用单引号设置; 双引号会报错;

代码语言:javascript
复制
android {
    ... ...
    defaultConfig {
        ... ...
        sourceSets{
            main{
                jniLibs.srcDirs=['libs']
            }
        }
    }
   ... ...
}
  • 10.build.gradle 配置文件示例 :
代码语言:javascript
复制
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 整体配置 :
代码语言:javascript
复制
# 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 中 配置该文件 : 设置 该 文件的 ①编译 配置, 并***②查找 日志库***, 之后***③进行库的链接操作***;
代码语言:javascript
复制
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 层中的 本地方法 定义 :
代码语言:javascript
复制
    /**
     * 本地方法需要在 'native-lib' 本地库中实现,
     * 这个本地库必须打包在本应用中.
     */
    public native String stringFromJNI();
  • 4.Native 层中 的方法实现 :
代码语言:javascript
复制
JNICALL
Java_han_ffmpeg_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello From C++";
    return env->NewStringUTF(hello.c_str());
}
  • 5.加载动态库 : 在文件的开头, 使用静态代码块加载动态库;
代码语言:javascript
复制
    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }
  • 6.使用 本地 方法 : 在界面中显示 从 本地 传来的 字符串;
代码语言:javascript
复制
        // 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.导入头文件 :
代码语言:javascript
复制
/*
 * 此处在 C++ 文件中引用一个 C 文件库
 * 需要使用 extern "C" 来说明, 表明使用和编译其中的代码都按照 C 语言的规范进行
 */
extern "C"
{
#include <libavcodec/avcodec.h>
}
  • 2.获取 编译 配置方法 :libavcodec/avcodec.h 中定义的 avcodec_configuration 方法, 返回一个字符串;
代码语言:javascript
复制
/**
 * Return the libavcodec build-time configuration.
 */
const char *avcodec_configuration(void);
  • 3.调用头文件中的函数 :
代码语言:javascript
复制
    //将编译时的配置信息返回给 Java 层, 并在界面中显示出来
    std::string hello = avcodec_configuration();
  • 4.执行项目 : 打印出的配置 正好是我们在 编译配置 选项中设置的 各种配置;

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-04-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一. 音视频基础
    • 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) 测试工程
      • (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 源码编译配置简介
      • (2) configure 配置详解
      • (3) 编写 FFMPEG 编译的自动化 shell 脚本
    • 6. 正式编译
      • (1) 使用命令行进行编译
      • (2) 使用编译脚本进行编译
  • 四. Android Studio 中项目导入 FFMPEG 及 配置
    • 1. Android 项目创建
      • (1) 创建 工程
    • 2. Android 项目 配置 ( 重点 )
      • (1) 项目配置
    • 3. Android 项目 代码分析
      • (1) JNI 使用流程 简介
      • (2) 打印 FFMPEG 编译时的配置
相关产品与服务
云直播
云直播(Cloud Streaming Services,CSS)为您提供极速、稳定、专业的云端直播处理服务,根据业务的不同直播场景需求,云直播提供了标准直播、快直播、云导播台三种服务,分别针对大规模实时观看、超低延时直播、便捷云端导播的场景,配合腾讯云视立方·直播 SDK,为您提供一站式的音视频直播解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档