文件格式:RMVB、AVI、WMV、MP4、FLV 等,可以理解为音、视频流的容器。
编码标准:Mpeg-4国际标准;H.264(也称为AVC)是一种视频压缩标准,它是MPEG-4 Part 10的一部分,也是一种广泛使用的视频编码格式。H.265(也称为HEVC)是H.264的后继者,它可以提供更高的压缩比和更好的视频质量。其他的音频和视频编码格式,如AAC、WMA、FLAC等。
当我们将视频流、音频流写入到一个封装容器(如FLV)中之前,需要先弄清楚这个容器的标准是否支持我们当前的视频流、音频流数据。如果将 H.265 的视频数据存储到 FLV 容器中,其他播放器不一定能够很好地播放这个视频,因为H.265视频压缩数据并不在 FLV 参考标准协议中,不在标准中,通常兼容性就不好。
音视频编解码
- 针对的是音频 PCM 裸数据、视频的 YUV 和 RGB 的图像数据。
- 音频是连续的采样序列,而视频则是连续的图像序列,这些序列是有前后关系
视频的编码压缩通常会涉及到I、B、P帧的概念
I 帧:关键帧,存储完整的图像帧,不依赖其他帧进行解码,常位于视频开头和场景发生变化的地方。
P帧:预测帧,有前面的I帧、P帧进行预测得到的。P帧只存储与前面的I帧或P帧之间的差异信息,所以也只能通过前面的帧进行解码,拥有更高的压缩比。
B帧:双向预测帧,由前后I、P帧数据进行预测得到的,所以解码需要先解前后两个参考帧。
正确的解码顺序为:1423756每个帧的解码都依赖于前面已经解码的帧,因此解码器需要按照正确的顺序对帧进行解码。一旦一个帧被解码,它就不再需要参与后续帧的解码了,因为后续帧只需要参考前面已经解码的帧就可以进行预测和解码。这样可以避免重复解码和浪费计算资源,提高解码效率。
一般情况下,B帧占的空间最小,所以适当地增加 B 帧可以减少视频流占用的带宽或者存储空间。但在实时直播场景下,参考标准中推荐的做法通常是不带 B 帧。
可变码率和恒定码率
- 视频编码时,当碰到运动的场景,图像组中通常也会包含更多的图像运动参考信息,所以压缩难度也提升了很多,压缩后的视频码率也就变得比常规图像更高一些,这个码率的波动通常时高时低,具有可变性,我们一般称之为可变码率(VBR)。
- 直播时,一个传输信号通道中会携带多条流,为了确保多条流在同一个信号通道中互不干扰,一般会要求编码时采用恒定码率的方式(CBR)。但是如果采用 CBR 的话,画质往往会有一些损耗,这也就是为什么画面突然变得模糊。
封装容器格式:MP4
- 由许多个 Box 与 FullBox 组成
- Box 由 Header 和 Data 两部分组成
- Header 包含了整个 Box 的长度的大小(Size)和类型(Type)
当 Size 等于 0 时,代表这个 Box 是文件中的最后一个 Box;当 Size 等于 1 时说明 Box 长度需要更多的 bits 位来描述,在后面会定义一个 64bits 位的 largesize 用来描述 Box 的长度;当 Type 为 uuid 时,说明这个 Box 中的数据是用户自定义扩展类型;
- Data 为 Box 的实际数据,可以是纯数据,也可以是更多的子 Box;
当一个 Box 中 Data 是一系列的子 Box 时,这个 Box 又可以称为 Container Box。
- FullBox 在 Box 结构的基础上,在 Header 中增加 8bit 位 version 标志和 24bit 位的 flags 标志
moov box 与 mdat box
- 音频与视频数据的索引信息,就是存在 moov box
- 音频和视频的索引信息在 moov 中分别存储在不同的 trak 里面
- trak 里面会保存对应的数据采样相关的索引信息
基于moov box的特性,当我们基于网络请求播放 MP4 点播文件时,如果 moov box 存储在 mdat box 后面的话,播放器需要先读取到 MP4 文件的 moov 以后,才能够开始播放 MP4 文件,而这个读取的动作,有些播放器是选择先下载全部 MP4 文件,有些则是需要先解析一下 mdat,跳过 mdat 以后再读取 moov,所以 为了节省播放器操作,兼容性更好,通常我们需要将 moov 移到 MP4 文件的头部,节省播放 MP4 文件开始时间段的开销。
需要注意的是,一般需要先写入 mdat 中的音视频数据,这样我们就知道数据采样存储的位置和大小,然后才能写入到 moov 中,所以是 先写入 mdat 后写入 moov 这样一个顺序。解决办法是生成文件之后做一个后处理,也就是将 moov 移动到 mdat 前面。
音视频流的两种存储方式:
如果是顺序读取音视频数据的话,当然就是音视频数据交错存储比较好,这样会给内存、硬盘或者网络节省很多开销。如果音视频分开,单独存放在各自的区域的话,为了更好地做音视频同步,通常会读取一段视频帧数据,再读取一段音频采样数据,这样势必会不断跳跃式地读取硬盘中的数据,或者不断地发起网络请求,如果是 http 请求的话,我们会看到大量的 http range 请求,给网络开销与服务器并发造成很大的压力。
网友评论