Android 基于ffmpeg开发简易播放器 - 基础知识

5,914 阅读22分钟

音视频基础知识

视频文件格式

对于视频来说,常见的文件格式则有:.mov、.avi、.mpg、.vob、.mkv、.rm、.rmvb 等等。文件格式通常表现为文件在操作系统上存储时的后缀名,它通常会被操作系统用来与相应的打开程序关联。之所以会有不同格式的视频,是因为采用了不同的封装方式来实现视频的。

视频封装格式

视频封装格式相当于一种储存视频信息的容器,它里面包含了封装视频文件所需要的视频信息、音频信息和相关的配置信息(比如:视频和音频的关联信息、如何解码等等)。一种视频封装格式的直接反映就是对应着相应的视频文件格式。

一些文件封装格式:

  • AVI 格式,对应的文件格式为 .avi。这种视频格式的优点是图像质量好,无损 AVI 可以保存 alpha 通道。缺点是体积过于庞大,并且压缩标准不统一,存在较多的高低版本兼容问题。
  • DV-AVI 格式,对应的文件格式为 .avi。常见的数码摄像机就是使用这种格式记录视频数据的。它可以通过电脑的 IEEE 1394 端口传输视频数据到电脑,也可以将电脑中编辑好的的视频数据回录到数码摄像机中。
  • WMV 格式,对应的文件格式是 .wmv、.asf,是微软推出的一种采用独立编码方式并且可以直接在网上实时观看视频节目的文件压缩格式。在同等视频质量下,WMV 格式的文件可以边下载边播放,因此很适合在网上播放和传输。
  • MPEG 格式,对应的文件格式有 .mpg、.mpeg、.mpe、.dat、.vob、.asf、.3gp、.mp4 等等。MPEG 格式目前有三个压缩标准,分别是 MPEG-1、MPEG-2、和 MPEG-4。MPEG-4 是现在用的比较多的视频封装格式,它为了播放流式媒体的高质量视频而专门设计的,以求使用最少的数据获得最佳的图像质量。
  • Matroska 格式,对应的文件格式是 .mkv,Matroska 是一种新的视频封装格式,它可将多种不同编码的视频及 16 条以上不同格式的音频和不同语言的字幕流封装到一个 Matroska Media 文件当中。
  • Real Video 格式,对应的文件格式是 .rm、.rmvb。用户可以使用 RealPlayer 根据不同的网络传输速率制定出不同的压缩比率,从而实现在低速率的网络上进行影像数据实时传送和播放。
  • QuickTime File Format 格式,对应的文件格式是 .mov。这种封装格式具有较高的压缩比率和较完美的视频清晰度等特点,并可以保存 alpha 通道。
  • Flash Video 格式,对应的文件格式是 .flv,是由 Adobe Flash 延伸出来的一种网络视频封装格式。这种格式被很多视频网站所采用。

在程序设计中,我们需要将视频文件以指定的格式独取出来。

视频编解码方式

视频编解码的过程是指对数字视频进行压缩或解压缩的一个过程。

在做视频编解码时,需要考虑以下这些因素的平衡:视频的质量、用来表示视频所需要的数据量(通常称之为码率)、编码算法和解码算法的复杂度、针对数据丢失和错误的鲁棒性(Robustness)、编辑的方便性、随机访问、编码算法设计的完美性、端到端的延时以及其它一些因素。

常见的视频编码方式有:

  • H.26X 系列,由国际电传视讯联盟远程通信标准化组织(ITU-T)主导,包括 H.261、H.262、H.263、H.264、H.265。

    • 1.H.261,主要用于老的视频会议和视频电话系统。是第一个使用的数字视频压缩标准。实质上说,之后的所有的标准视频编解码器都是基于它设计的。
    • H.262,等同于 MPEG-2 第二部分,使用在 DVD、SVCD 和大多数数字视频广播系统和有线分布系统中。
    • H.263,主要用于视频会议、视频电话和网络视频相关产品。在对逐行扫描的视频源进行压缩的方面,H.263 比它之前的视频编码标准在性能上有了较大的提升。尤其是在低码率端,它可以在保证一定质量的前提下大大的节约码率。
    • H.264,等同于 MPEG-4 第十部分,也被称为高级视频编码(Advanced Video Coding,简称 AVC),是一种视频压缩标准,一种被广泛使用的高精度视频的录制、压缩和发布格式。该标准引入了一系列新的能够大大提高压缩性能的技术,并能够同时在高码率端和低码率端大大超越以前的诸标准。
    • H.265,被称为高效率视频编码(High Efficiency Video Coding,简称 HEVC)是一种视频压缩标准,是 H.264 的继任者。HEVC 被认为不仅提升图像质量,同时也能达到 H.264 两倍的压缩率(等同于同样画面质量下比特率减少了 50%),可支持 4K 分辨率甚至到超高画质电视,最高分辨率可达到 8192×4320(8K 分辨率),这是目前发展的趋势。
  • MPEG 系列,由国际标准组织机构(ISO)下属的运动图象专家组(MPEG)开发。

    • MPEG-1 第二部分,主要使用在 VCD 上,有些在线视频也使用这种格式。该编解码器的质量大致上和原有的 VHS 录像带相当。
    • MPEG-2 第二部分,等同于 H.262,使用在 DVD、SVCD 和大多数数字视频广播系统和有线分布系统中。
    • MPEG-4 第二部分,可以使用在网络传输、广播和媒体存储上。比起 MPEG-2 第二部分和第一版的 H.263,它的压缩性能有所提高。
    • MPEG-4 第十部分,等同于 H.264,是这两个编码组织合作诞生的标准。
  • 其他,AMV、AVS、Bink、CineForm 等等,这里就不做多的介绍了。

可以把「视频封装格式」看做是一个装着视频、音频、「视频编解码方式」等信息的容器。一种「视频封装格式」可以支持多种「视频编解码方式」,比如:QuickTime File Format(.MOV) 支持几乎所有的「视频编解码方式」,MPEG(.MP4) 也支持相当广的「视频编解码方式」。当我们看到一个视频文件名为 test.mov 时,我们可以知道它的「视频文件格式」是 .mov,也可以知道它的视频封装格式是 QuickTime File Format,但是无法知道它的「视频编解码方式」。那比较专业的说法可能是以 A/B 这种方式,A 是「视频编解码方式」,B 是「视频封装格式」。比如:一个 H.264/MOV 的视频文件,它的封装方式就是 QuickTime File Format,编码方式是 H.264。

视频解码后需要转换成显卡支持的格式才能够显示。像素格式的转换。

音频编解码方式

在视频中经常使用的音频编码方式有:

  • AAC。
  • MP3,是当曾经非常流行的一种数字音频编码和有损压缩格式,它被设计来大幅降低音频数据量。
  • WMA,包括有损和无损压缩格式。

音频需要转换成声卡支持的格式才能够播放。重采样。

封装格式和编码格式

像素格式

像素格式就是图像的具体像素用什么表示,主要有两种,RGB和YUV。摄像头采集的像素格式和显示器显示的像素格式都为RGB格式,但是很多的压缩和解码算法都是基于YUV格式的,所以需要进行RGB和YUV格式的转换。可以直接使用显卡的Shader语言来转换。

PCM音频参数

采样率:44100 (CD,1s内采集了44100次,越大越接近真实情况) 通道:左右声道 样本大小:AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_FLTP(浮点格式,效率更高)。 AV_SAMPLE_FMT_FLTP无法直接播放,需要进行重采样转换成AV_SAMPLE_FMT_S16格式之后才能播放。

样本类型planar

MP4格式分析

blog.csdn.net/shelldon/article/details/54144409

关于 H.264

H.264 是现在广泛采用的一种编码方式。

解释几个概念:

  • 图像。H.264 中,「图像」是个集合的概念,帧、顶场、底场都可以称为图像。一帧通常就是一幅完整的图像。当采集视频信号时,如果采用逐行扫描,则每次扫描得到的信号就是一副图像,也就是一帧。当采集视频信号时,如果采用隔行扫描(奇、偶数行),则扫描下来的一帧图像就被分为了两个部分,这每一部分就称为「场」,根据次序分为:「顶场」和「底场」。「帧」和「场」的概念又带来了不同的编码方式:帧编码、场编码。逐行扫描适合于运动图像,所以对于运动图像采用帧编码更好;隔行扫描适合于非运动图像,所以对于非运动图像采用场编码更好。

  • 片(Slice),每一帧图像可以分为多个片。
  • 网络提取层单元(NALU, Network Abstraction Layer Unit),NALU 是用来将编码的数据进行打包的,一个分片(Slice)可以编码到一个 NALU 单元。不过一个 NALU 单元中除了容纳分片(Slice)编码的码流外,还可以容纳其他数据,比如序列参数集 SPS。对于客户端其主要任务则是接收数据包,从数据包中解析出 NALU 单元,然后进行解码播放。
  • 宏块(Macroblock),分片是由宏块组成。

颜色模型

最经典的颜色模型应该就是 RGB 模型了。

在 RGB 模型中每种颜色需要 3 个数字,分别表示 R、G、B,比如 (255, 0, 0) 表示红色,通常一个数字占用 1 字节,那么表示一种颜色需要 24 bits。那么有没有更高效的颜色模型能够用更少的 bit 来表示颜色呢?

现在我们假设我们定义一个「亮度(Luminance)」的概念来表示颜色的亮度,那它就可以用含 R、G、B 的表达式表示为:

Y = kr*R + kg*G + kb*B

Y 即「亮度」,kr、kg、kb 即 R、G、B 的权重值。

这时,我们可以定义一个「色度(Chrominance)」的概念来表示颜色的差异:

Cr = R – Y
Cg = G – Y
Cb = B – Y

Cr、Cg、Cb 分别表示在 R、G、B 上的色度分量。上述模型就是 YCbCr 颜色模型基本原理。

YCbCr 是属于 YUV 家族的一员,是在计算机系统中应用最为广泛的颜色模型。在 YUV 中 Y 表示的是「亮度」,也就是灰阶值,U 和 V 则是表示「色度」。YUV 的关键是在于它的亮度信号 Y 和色度信号 U、V 是分离的。那就是说即使只有 Y 信号分量而没有 U、V 分量,我们仍然可以表示出图像,只不过图像是黑白灰度图像。在YCbCr 中 Y 是指亮度分量,Cb 指蓝色色度分量,而 Cr 指红色色度分量。

YCbCr 与 RGB 相互转换的公式:

Y = 0.299R + 0.587G + 0.114B
Cb = 0.564(B - Y)
Cr = 0.713(R - Y)
R = Y + 1.402Cr
G = Y - 0.344Cb - 0.714Cr
B = Y + 1.772Cb

但是我们会发现,这里 YCbCr 也仍然用了 3 个数字来表示颜色啊,有节省 bit 吗?为了回答这个问题,我们来结合视频中的图像和图像中的像素表示来说明。

图片是由类似下面的像素组成:

一副图片就是一个像素阵列:
上图中,每个像素的 3 个分量的信息是完整的,YCbCr 4:4:4。
上图中,对于每个像素点都保留「亮度」值,但是省略每行中偶素位像素点的「色度」值,从而节省了 bit。
上图中,做了更多的省略,但是对图片质量的影响却不会太大。

码流格式

对于一个解码器来说,它的工作对象就是从一个特定结构的数据流中去获取有效的 bit 流,而这个数据流则是结构化后分为数据包传输的,其大致结构如下:
我们可以看到,在 NAL 包之间存在着一些间隔标记。

NAL 包的第一个字节是定义包类型的头文件,NAL 包有这样一些类型:
NAL 的类型说明了当前这个 NAL 包的数据结构和数据含义,它可能是片(Slice),参数集或者填充数据等等。

如上图所示,NAL 包将其负载数据存储在 RBSP(Raw Byte Sequence Payload) 中,RBSP 是一系列的 SODB(String Of Data Bits)。

H.264 的码流结构:

一张图片可以包含一个或多个分片(Slice),而每一个分片(Slice)又会被分为了若干宏块(Macroblock)。对于分片(Slice)来说,有如下这些类型:
如我们所见,每个分片也包含着头和数据两部分,分片头中包含着分片类型、分片中的宏块类型、分片帧的数量以及对应的帧的设置和参数等信息,而分片数据中则是宏块,这里就是我们要找的存储像素数据的地方。

宏块是视频信息的主要承载者,因为它包含着每一个像素的亮度和色度信息。视频解码最主要的工作则是提供高效的方式从码流中获得宏块中的像素阵列。

从上图中,可以看到,宏块中包含了宏块类型、预测类型、Coded Block Pattern、Quantization Parameter、像素的亮度和色度数据集等等信息。

GOP

一组可以独立解码并播放的数据:

分为I帧,B帧,P帧。

  • I帧:关键帧。可以独立解码并播放。
  • B帧:相对前一帧的变化,需要参考前一帧进行解码。
  • P帧:相对前一帧和后一帧的变化,需要参考前一帧和后一帧进行解码。

所以解码顺序与显示顺序不一致。需要缓冲一定的帧数才能够正确显示。

PTS & DTS

视频的播放过程可以简单理解为一帧一帧的画面按照时间顺序呈现出来的过程。但是在实际应用中,并不是每一帧都是完整的画面,因为如果每一帧画面都是完整的图片,那么一个视频的体积就会很大,这样对于网络传输或者视频数据存储来说成本太高,所以通常会对视频流中的一部分画面进行压缩(编码)处理。由于压缩处理的方式不同,视频中的画面帧就分为了不同的类别,其中包括:I 帧、P 帧、B 帧。

I、P、B 帧

I 帧、P 帧、B 帧的区别在于:

  • I 帧(Intra coded frames):I 帧图像采用帧内编码方式,即只利用了单帧图像内的空间相关性,而没有利用时间相关性。I 帧使用帧内压缩,不使用运动补偿,由于 I 帧不依赖其它帧,所以是随机存取的入点,同时是解码的基准帧。I 帧主要用于接收机的初始化和信道的获取,以及节目的切换和插入,I 帧图像的压缩倍数相对较低。I 帧图像是周期性出现在图像序列中的,出现频率可由编码器选择。
  • P 帧(Predicted frames):P 帧和 B 帧图像采用帧间编码方式,即同时利用了空间和时间上的相关性。P 帧图像只采用前向时间预测,可以提高压缩效率和图像质量。P 帧图像中可以包含帧内编码的部分,即 P 帧中的每一个宏块可以是前向预测,也可以是帧内编码。
  • B 帧(Bi-directional predicted frames):B 帧图像采用双向时间预测,可以大大提高压缩倍数。值得注意的是,由于 B 帧图像采用了未来帧作为参考,因此 MPEG-2 编码码流中图像帧的传输顺序和显示顺序是不同的。

也就是说,一个 I 帧可以不依赖其他帧就解码出一幅完整的图像,而 P 帧、B 帧不行。P 帧需要依赖视频流中排在它前面的帧才能解码出图像。B 帧则需要依赖视频流中排在它前面或后面的帧才能解码出图像。

这就带来一个问题:在视频流中,先到来的 B 帧无法立即解码,需要等待它依赖的后面的 I、P 帧先解码完成,这样一来播放时间与解码时间不一致了,顺序打乱了,那这些帧该如何播放呢?这时就需要了解另外两个概念:DTS 和 PTS。

DTS、PTS 的概念

  • DTS(Decoding Time Stamp):即解码时间戳,这个时间戳的意义在于告诉播放器该在什么时候解码这一帧的数据。
  • PTS(Presentation Time Stamp):即显示时间戳,这个时间戳用来告诉播放器该在什么时候显示这一帧的数据。

需要注意的是:虽然 DTS、PTS 是用于指导播放端的行为,但它们是在编码的时候由编码器生成的。

当视频流中没有 B 帧时,通常 DTS 和 PTS 的顺序是一致的。但如果有 B 帧时,就回到了我们前面说的问题:解码顺序和播放顺序不一致了。

比如一个视频中,帧的显示顺序是:I B B P,现在我们需要在解码 B 帧时知道 P 帧中信息,因此这几帧在视频流中的顺序可能是:I P B B,这时候就体现出每帧都有 DTS 和 PTS 的作用了。DTS 告诉我们该按什么顺序解码这几帧图像,PTS 告诉我们该按什么顺序显示这几帧图像。顺序大概如下:

   PTS: 1 4 2 3
   DTS: 1 2 3 4
Stream: I P B B

音频的播放,也有 DTS、PTS 的概念,但是音频没有类似视频中 B 帧,不需要双向预测,所以音频帧的 DTS、PTS 顺序是一致的。

音频视频混合在一起播放,就呈现了我们常常看到的广义的视频。在音视频一起播放的时候,我们通常需要面临一个问题:怎么去同步它们,以免出现画不对声的情况。

要实现音视频同步,通常需要选择一个参考时钟,参考时钟上的时间是线性递增的,编码音视频流时依据参考时钟上的时间给每帧数据打上时间戳。在播放时,读取数据帧上的时间戳,同时参考当前参考时钟上的时间来安排播放。这里的说的时间戳就是我们前面说的 PTS。实践中,我们可以选择:同步视频到音频、同步音频到视频、同步音频和视频到外部时钟。

帧内预测和帧间预测

宏块的数据结构中包含了「预测类型」这个字段,这里就接着说说「帧内预测」和「帧间预测」这两种在视频编码中常用到的压缩方法,也可以称为「帧内压缩」和「帧间压缩」。

帧内压缩类似于图片压缩,跟这一帧的前面(或后面)一帧(或几帧)无关,由当前帧中,已编码的部分来推测当前待编码的这一部分数据是什么。帧间压缩是由这一帧的前(或后)一帧(或几帧)来推测当前待压缩的这一部分数据是什么。

上节中,我们说过图片可以划分为宏块。一般来说,运动多细节多的部分,划分成小块来编码,无变化的大片的部分,划分成大块来编码。其大致效果如下:

帧内预测

对于帧内压缩,我们可以看下图示例:

我们可以通过第 1、2、3、4、5 块的编码来推测和计算第 6 块的编码,因此就不需要对第 6 块进行编码了,从而压缩了第 6 块,节省了空间。

帧内预测在 H.264 编码标准里有以下几种预测方法:

帧间预测

对于帧间压缩,可以看下面连续的两帧:

可以看到前后两帧的差异其实是很小的,这时候用帧间压缩就很有意义。

做帧间压缩常用的方式就是块匹配(Block Matching),就是找找看前面已经编码的几帧里面,和我当前这个块最类似的一个块,这样我就不用编码当前块的内容了,只需要编码当前块和我找到的那个块的差异(称为残差)即可。找最像的块的过程叫运动搜索(Motion Search),又叫运动估计(Motion Estimation)。用残差和原来的块就能推算出当前块的过程叫运动补偿(Motion Compensation)。

视频业务

视频相关的业务方式通常有:本地视频文件播放、网络视频点播、网络视频直播等等几种。对于网络视频点播、网络视频直播,整个过程大致如下图所示:

而本地视频文件播放就更简单了,是在上面的过程中省略掉解协议的过程。

流媒体协议

随着互联网基础设施越来越完善,网络视频点播和直播业务也越来越多,这其中少不了流媒体协议的支持。常见的流媒体协议有:

  • RTP,实时传输协议,Real-time Transport Protocol,是一种网络传输协议,运行在 UDP 协议之上,RTP协议详细说明了在互联网上传递音频和视频的标准数据包格式。RTP协议常用于流媒体系统(配合 RTSP 协议)。
  • RTCP,实时传输控制协议,Real-time Transport Control Protocol,是实时传输协议(RTP)的一个姐妹协议。RTCP为RTP媒体流提供信道外(out-of-band)控制。RTCP 本身并不传输数据,但和 RTP 一起协作将多媒体数据打包和发送。RTCP 定期在流多媒体会话参加者之间传输控制数据。RTCP 的主要功能是为 RTP 所提供的服务质量(Quality of Service)提供反馈。
  • RTSP,实时流传输协议,Real Time Streaming Protocol,该协议定义了一对多应用程序如何有效地通过 IP 网络传送多媒体数据。RTSP 在体系结构上位于 RTP 和 RTCP 之上,它使用 TCP 或 UDP 完成数据传输。使用 RTSP 时,客户机和服务器都可以发出请求,即 RTSP 可以是双向的。
  • RTMP,实时消息传输协议,Real Time Messaging Protocol,是 Adobe Systems 公司为 Flash 播放器和服务器之间音频、视频和数据传输开发的开放协议。协议基于 TCP,是一个协议族,包括 RTMP 基本协议及 RTMPT/RTMPS/RTMPE 等多种变种。RTMP 是一种设计用来进行实时数据通信的网络协议,主要用来在 Flash/AIR 平台和支持RTMP协议的流媒体/交互服务器之间进行音视频和数据通信。
  • RTMFP,是 Adobe 公司开发的一套新的通信协议,全称 Real Time Media Flow Protocol,协议基于 UDP,支持 C/S 模式和 P2P 模式,即该协议可以让使用 Adobe Flash Player 的终端用户之间进行直接通信。
  • HTTP,超文本传输协议,HyperText Transfer Protocol,运行在 TCP 之上,这个协议是大家非常熟悉的,它也可以用到视频业务中来。
  • HLS,是苹果公司实现的基于 HTTP 的流媒体传输协议,全称 HTTP Live Streaming,可支持流媒体的直播和点播,主要应用在 iOS 系统,为 iOS 设备(如 iPhone、iPad)提供音视频直播和点播方案。对于 HLS 点播,基本上就是常见的分段 HTTP 点播,不同在于,它的分段非常小。要实现HLS点播,重点在于对媒体文件分段。对于 HLS 直播,相对于常见的流媒体直播协议,例如 RTMP 协议、RTSP 协议等,HLS 最大的不同在于直播客户端获取到的并不是一个完整的数据流,而是连续的、短时长的媒体文件(MPEG-TS 格式),客户端不断的下载并播放这些小文件。由于数据通过 HTTP 协议传输,所以完全不用考虑防火墙或者代理的问题,而且分段文件的时长很短,客户端可以很快的选择和切换码率,以适应不同带宽条件下的播放。不过 HLS 的这种技术特点,决定了它的延迟一般总是会高于普通的流媒体直播协议。

业务方案

网络视频点播

网络视频点播业务采用 HTTP 有两方面优势:

  • HTTP 是基于 TCP 协议的应用层协议,媒体传输过程中不会出现丢包等现象,从而保证了视频的质量。
  • HTTP 是绝大部分的 Web 服务器支持的协议,因而流媒体服务机构不必投资购买额外的流媒体服务器,从而节约了开支。

网络视频点播服务采用的封装格式有多种:MP4,FLV,F4V 等,它们之间的区别不是很大。

视频编码标准和音频编码标准是 H.264 和 AAC,这两种标准分别是当今实际应用中编码效率最高的视频标准和音频标准。

视频播放器方面则都使用了 Flash 播放器。

网络视频直播

网络视频直播服务采用 RTMP 作为直播协议的好处是可以直接被 Flash 播放器支持,而 Flash 播放器在 PC 时代有着极高的普及率,并且与浏览器结合的很好。因此这种流媒体直播平台基本上可以实现了「无插件直播」,极大降低了用户使用成本。

封装格式、视频编码、音频编码、播放器方面几乎全部采用了 FLV、H.264、AAC、Flash。FLV、RTMP、Flash 都是 Adobe 公司的产品,天生有着良好的结合性。