Android NDK开发之旅 目录
音视频基础知识
视频播放器原理
一个最简单的视频播放器的过程(不包括视频加密等等过程):
这是一个视频播放的最基本的原理流程图,从这个图可以很整体得看到视频处理的一些主要步骤:
-
解协议
解协议的作用,就是将流媒体协议的数据,解析为标准的相应的封装格式数据。视音频在网络上传播的时候,常常采用各种流媒体协议,例如HTTP,RTMP,或是MMS等等。这些协议在传输视音频数据的同时,也会传输一些信令数据。这些信令数据包括对播放的控制(播放,暂停,停止),或者对网络状态的描述等。解协议的过程中会去除掉信令数据而只保留视音频数据。例如,采用RTMP协议传输的数据,经过解协议操作后,输出FLV格式的数据。
-
解封装
解封装的作用,就是将输入的封装格式的数据,分离成为音频流压缩编码数据和视频流压缩编码数据。封装格式种类很多,例如MP4,MKV,RMVB,TS,FLV,AVI等等,它的作用就是将已经压缩编码的视频数据和音频数据按照一定的格式放到一起。例如,FLV格式的数据,经过解封装操作后,输出H.264编码的视频码流和AAC编码的音频码流。
-
解码
解码的作用,就是将视频/音频压缩编码数据,解码成为非压缩的视频/音频原始数据。音频的压缩编码标准包含AAC,MP3,AC-3等等,视频的压缩编码标准则包含H.264,MPEG2,VC-1等等。解码是整个系统中最重要也是最复杂的一个环节。通过解码,压缩编码的视频数据输出成为非压缩的颜色数据,例如YUV420P,RGB等等;压缩编码的音频 数据输出成为非压缩的音频抽样数据,例如PCM数据。
-
视音频同步
视音频同步的作用,就是根据解封装模块处理过程中获取到的参数信息,同步解码出来的视频和音频数据,并将视频音频数据送至系统的显卡和声卡播放出来。
注意:我们利用FFmpeg进行编程的时候几乎就是基于这个流程图来进行。比如说,编程的时候我们会拿到解码器,解码读取数据,绘制到屏幕上面的时候可能还需要把YUV数据转换为RGB等等。
我们常见的封装视频的格式有:flv(音视频分开)、mp4、avi等等。后面我们会详细说明。
为什么视频需要经过封装处理呢?
因为摄像头采集到的画面、以及麦克风采集到的音频数据是经过压缩的处理,不然视频文件就会很大。
也就是说:
录像、录音,实质是一个压缩采集的图像或者声音的过程。这个过程就是视频编码压缩的过程。
播放视频、音频文件实质上就是解压缩的过程,这个过程又称为解码。
视频的封装格式介绍
封装格式的作用是:视频码流和音频码流按照一定的格式存储在一个文件中。
封装格式分析工具:Elecard Format Analyzer
为什么要音视频分开存储呢?因为音视频的编码格式各种各样,同时编码必然会造成混乱。
常见的视频封装格式有:
以两个格式为例子,介绍一下原理:
MPEG2-TS格式是由一个一个数据大小固定的TS-Packet组成,因此可以支持快进。
FLY格式由FLV HEADER以及一个一个大小不固定的Tag组成。因为FLV格式直接能够用flash(浏览器)播放,因此常用于视频直播邻域。我们在做RTMP推流的时候,一开始就需要发送头信息。因为数据单元大小不固定,因此原生的视频播放器不支持FLV视频的快进(有些播放器进行了处理可以快进)。
视频编解码常见格式介绍
视频的压缩算法很多,因此编码格式就会有很多种,下面介绍一些常见的编解码格式:
常见视频编解码格式:
-
常见的视频编码格式有:H.264、MPEG2、VP8等(谷歌收购的WebRTC视频通话就是用VP8)。
以H264为例,H264是由大小不固定的NALU构成。(NALU实质是一种数据结构)。H264里面有很多子压缩算法,原理比较复杂,包括了熵编码,环路滤波,帧内检测,帧间检测等知识。H264编码原理比较复杂,因此H264的压缩效率是几百到几千倍。
-
视频解码得到的像素数据RGB、YUV。
YUV,分为三个分量,Y:表示明亮度(Luminance或Luma),也就是灰度值;而 U 和 V :表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。
YUV码流的存储格式其实与其采样的方式密切相关,主流的采样方式有三种,YUV4:4:4,YUV4:2:2,YUV4:2:0
YUV格式采样方式4:2由来:
在最近十年中,视频工程师发现人眼对色度的敏感程度要低于对亮度的敏感程度。在生理学中,有一条规律,那就是人类视网膜上的视网膜杆细胞要多于视网膜锥细胞,说得通俗一些,视网膜杆细胞的作用就是识别亮度,而视网膜锥细胞的作用就是识别色度。所以,你的眼睛对于亮和暗的分辨要比对颜色的分辨精细一些。正是因为这个,在我们的视频存储中,没有必要存储全部颜色信号。既然眼睛看不见,那为什么要浪费存储空间(或者说是金钱)来存储它们呢?
音视频编解码格式:
-
常见的音频编码格式有:AAC、MP3。
- 音频解码得到的是音频采样数据,然后喇叭才能播放。常见格式是PCM,实质是一个一个的采样值。单位时间内震动的数据,包括振幅和频率。常用采样率44100,人耳朵能够擦觉到的最高采样率。
音频采样数据PCM:保存了音频中每个采样点的值,音频采样数据体积很大,一般需要进过压缩,我们平常说的“无损”实质上是没有损失的压缩的意思。
在做视频直播的时候:音频常用AAC来进行编码,用FAAC库来处理;视频用H264编码。
相关播放(编辑)工具
YUV:YUV Player
PCM:Adobe Audition
查看视频信息:MediaInfo
视频编码数据:Elecard Format Analyzer
视频编码分析工具:Elecard Stream Eye
FFmpeg介绍
FFmpeg是开源的C/C++音视频处理的类库,这个库十分优秀,以至于很多大公司都在用。主流的视频播放器几乎都使用了FFmpeg。
FFmpeg的八个函数库的基本介绍
如下图所示:
Visual Studio下FFmpeg的项目配置
前言
为了方便编写和调试,编写过程一般在Windows(VS)、Linux(Gcc)平台中进行。编写调试无误后再再放在Android编译器上调试。为了方便,我这里就在vs下进行项目配置。
1.下载头文件、lib文件和dll文件。
先进入ffmpeg的官网:点击打开链接,不要直接点击页面上最大的那个“download”,而是点击左侧标签中的Download,再点击“Get the packages”中的windows图标,此时在图标下面会出现“Windows Builds”字样,点击进入之后会看到有三种包可以下载,分别是Static,Shared,Dev,我们在这里使用的是后两种,其中Shared中有dll文件,Dev中有头文件和lib文件。
选择对应的系统,这里我们先介绍Windows版本的,点击下面的Windows Builds,跳转到下面的界面:
下面并解压的资源如下:
2.将下载好的include文件、lib文件和dll文件复制到工程目录中。
将上一步下载好的包解压,取Shared中的dll文件直接复制到工程目录下(dll文件在bin文件夹中),取Dev中的include文件夹和lib文件夹直接复制到工程目录下。
3.在编译器中进行配置(我这里使用的是VS2013,Win64)。
这一步共需要配置三个部分:
⑴配置属性->C/C++->常规->附加包含目录:设置为include或include路径。
⑵配置属性->链接器->常规->附加库目录:设置为lib或lib路径
⑶配置属性->链接器->输入->附加依赖项:加入下面这几个lib
avcodec.lib
avdevice.lib
avfilter.lib
avformat.lib
avutil.lib
postproc.lib
swresample.lib
swscale.lib
4.经过以上三步后ffmpeg的配置就已经完成了。我们可以使用一段代码来测试是否配置成功。测试代码如下:
#include
#include
#include
using namespace std;
//C/C++混编,指示编译器按照C语言进行编译
extern "C" {
#include "libavcodec\avcodec.h"
}
void main() {
//输出FFmpeg的配置信息,检查是否配置好
cout << avcodec_configuration() << endl;
system("pause");
}
如果输入如下结果则说明配置成功。
5.至此,我们已经成功配置ffmpeg。