音视频相关知识总结

封装格式

我们经常看到有不同后缀表示的视频：avi，rmvb，mp4，flv，mkv 等等。这些格式代表的是封装格式。何为封装格式？就是把视频数据和音频数据打包成一个文件的规范。仅仅靠看文件的后缀，很难能看出具体使用了什么视音频编码标准。

我们可以通过视频的属性查看该视频文件采用的视音频技术。或者 MediaInfo 软件查看。

封装格式的主要作用是把视频码流和音频码流按照一定的格式存储在一个文件中。
主要的封装格式：

视频播放器原理

视音频技术主要包含以下几点：封装技术，视频压缩编码技术以及音频压缩编码技术。如果考虑到网络传输的话，还包括流媒体协议技术。

视频播放器播放一个互联网上的视频文件，需要经过以下几个步骤：
解协议，解封装，解码视音频，视音频同步。
如果播放本地文件则不需要解协议，为以下几个步骤：
解封装，解码视音频，视音频同步。

解协议的作用，就是将流媒体协议的数据，解析为标准的相应的封装格式数据。视音频在网络上传播的时候，常常采用各种流媒体协议，例如 HTTP，RTMP，HLS, 或是 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 数据。

视音频同步的作用，就是根据解封装模块处理过程中获取到的参数信息，同步解码出来的视频和音频数据，并将视频音频数据送至系统的显卡和声卡播放出来。

视频编码

视频编码的主要作用是将视频像素数据（RGB，YUV 等）压缩成为视频码流，从而降低视频的数据量。如果视频不经过压缩编码的话，体积通常是非常大的，一部电影可能就要上百 G 的空间。视频编码是视音频技术中最重要的技术之一。视频码流的数据量占了视音频总数据量的绝大部分。高效率的视频编码在同等的码率下，可以获得更高的视频质量。

主要的视频编码有：HEVC (H.265)，H.264，MPEG4，MPEG2，VP9，VP8 等。
目前的主流编码标准：H.264
H.264 仅仅是一个编码标准，而不是一个具体的编码器，H.264 只是给编码器的实现提供参照用的。

目前支持 H.265 的及其也越来越多。

音频编码

音频编码的主要作用是将音频采样数据（PCM 等）压缩成为音频码流，从而降低音频的数据量。音频编码也是互联网视音频技术中一个重要的技术。但是一般情况下音频的数据量要远小于视频的数据量，因而即使使用稍微落后的音频编码标准，而导致音频数据量有所增加，也不会对视音频的总数据量产生太大的影响。

主要的音频编码：AAC，MP3，WMA 等

Android 平台提供的媒体编解码器，容器和网络协议支持：
https://developer.android.com/guide/topics/media/media-formats

比如，Android 机把 AudioRecord 采集的到的 PCM 音频数据编码压缩为 AAC 格式的音频数据，然后解码为 PCM 通过 AudioTrack 来播放

视频转码 / 压缩

视频转码其实可以理解为，一个视频先解码，然后再按一定格式编码。
压缩视频其实就是在转码，重新编码，获取相对较小的，视频质量可接受的视频。

音视频压缩的基本原理：https://blog.csdn.net/leixiaohua1020/article/details/28114081

那视频的大小跟什么有关呢？

决定因素是码率（常用单位 kbps ），即 “每秒有多少数据”，码率越大视频越大，不管你是 1080p 还是 720p 还是什么其他尺寸，同样码率的 720p 视频和 1080p 视频文件大小是一样的，只是画质不一样。

而影响码率的因素有很多：

1、其他条件不变，画面尺寸（1080p、720p、480p...）越大码率越大；
2、其他条件不变，帧率（25 帧 / 秒、30 帧 / 秒 、60 帧 / 秒……）越高码率也越大；
3、还有一个是编码算法，优秀的算法能在画质损失较小的情况下降低码率从而减小视频文件的体积。

一个简单的计算视频大小的公式：

码率（kbps）x 视频时间（秒）÷8 = 视频文件大小（kb）

目前我们项目中视频压缩使用的库：https://github.com/ypresto/android-transcoder

Android MediaCodec：https://developer.android.com/reference/android/media/MediaCodec

MediaCodec 是 API 16 之后 Google 推出的用于音视频编解码的一套偏底层的 API，可以直接利用硬件加速进行视频的编解码。调用的时候需要先初始化 MediaCodec 作为视频的编码器，然后只需要不停传入原始的 YUV 数据进入编码器就可以直接输出编码好的 h264 流，整个 API 设计模型来看，就是同时包含了输入端和输出端的两条队列：

作为编码器，输入端队列存放的就是原始 YUV 数据，输出端队列输出的就是编码好的 h264 流，作为解码器则对应相反。

参考：https://me.csdn.net/leixiaohua1020