其实老早就想写一些关于音视频学习的文章了,但由于各方面的原因迟迟都没有开始。一个方面是因为笔者写文章都是成系统的,音视频需要大家有一定的 c/c++ 基础;还有一个方面是因为之前经验不足,这一块涉及到的细节也比较多。我自己学习时看过大量的文章和资料,这里推荐 雷霄骅的专栏 ,虽然文章的更新永远停在了那一刻,但其无私分享的精神值得我们每一个开发者学习。音视频这系列文章我们打算从基础开始学,然后结合移动端 NDK 来开发。因此如果你已经是音视频开发的老司机,那么本文可能不太适合你,其次如果之前没了解过 NDK 开发,学习起来也可能会有些难度。
目前市面上我们所熟悉的音视频开发大致有:视频播放器、短视频、视音频直播 等等,他们之间有很多的共性像音视频编解码、视音频同步等,因此我们首先来看下这些共性内容。假设我们现在要播放一个本地视频,需要经过哪些步骤呢?大家不妨自己先思考一下,当然这里不是说集成 ijkplayer 或者 ExoPlayer 等开源库,目前只给一个 SurfaceView 和一个视频文件,在此基础上实现一个视频播放。我们先来看一个简单的流程图:
上面这张图我们务必得要记在心里,想必理解这么一张图对于大家来说应该 soEasy 。很多东西都是一通百通的,之前就讲过怎么解析一张图片,我们再涣散一下思维,假如去解析加载一个 dex/class 文件呢?基于上面这个图,我们再来看一些具体的细节:
解封装
将输入的封装格式的数据(文件),分离成为音频流压缩编码数据和视频流压缩编码数据。封装格式种类很多,具体可以参考下面这张表,它的作用就是将已经压缩编码的视频数据和音频数据按照一定的格式放到一起。例如,FLV 格式的数据,经过解封装操作后,输出 H.264 编码的视频码流和 AAC 编码的音频码流。
名称 | 推出机构 | 支持的视频编码 | 支持的音频编码 |
---|---|---|---|
AVI | Microsoft Inc. | 几乎所有格式 | 几乎所有格式 |
MP4 | MPEG | MPEG-2, MPEG-4, H.264, H.263等 | AAC, MPEG-1 Layers I, II, III, AC-3等 |
TS | MPEG | MPEG-1, MPEG-2, MPEG-4, H.264 | MPEG-1 Layers I, II, III, AAC, |
FLV | Adobe Inc. | Sorenson, VP6, H.264 | MP3, ADPCM, Linear PCM, AAC等 |
MKV | CoreCodec Inc. | 几乎所有格式 | 几乎所有格式 |
RMVB | Real Networks Inc. | RealVideo 8, 9, 10 | AAC, Cook Codec, RealAudio Lossless |
视音频解码
将视频/音频压缩编码数据,解码成为非压缩的视频/音频原始数据。音频的压缩编码标准包含 AAC,MP3,AC-3 等等,视频的压缩编码标准则包含 H.264,MPEG2,VC-1 等等。解码是整个系统中最重要也是最复杂的一个环节。通过解码,压缩编码的视频数据输出成为非压缩的颜色数据,例如 YUV420P,RGB 等等;压缩编码的音频数据输出成为非压缩的音频抽样数据,例如 PCM 数据。
视频编码
视频编码的主要作用是将视频像素数据(RGB,YUV等)压缩成为视频码流,从而降低视频的数据量。如果视频不经过压缩编码的话,体积通常是非常大的,一部电影可能就要上百G的空间。视频编码是视音频技术中最重要的技术之一。视频码流的数据量占了视音频总数据量的绝大部分。高效率的视频编码在同等的码率下,可以获得更高的视频质量。主要的编码方式有 HEVC(H.265),H.264,MPEG4,MPEG2,VP9,VP8,VC-1 等等。
音频编码
音频编码的主要作用是将音频采样数据(PCM等)压缩成为音频码流,从而降低音频的数据量。音频编码也是互联网视音频技术中一个重要的技术。但是一般情况下音频的数据量要远小于视频的数据量,因而即使使用稍微落后的音频编码标准,而导致音频数据量有所增加,也不会对视音频的总数据量产生太大的影响。高效率的音频编码在同等的码率下,可以获得更高的音质。主要的编码方式有 AAC,AC-3,MP3,WMA 等等。
FFmpeg
整个音视频技术学习的核心就在协议和编解码,其中最复杂重要的部分当属编解码了,如果没有基础的话,我们可以买一些书看一下,实体书或电子书都行。如果真的只给大家一个文件和一个 SurfaceView ,第一步解封装估计就得难倒一大部分人。因此如果是初学习音视频技术,还是建议大家基于一些第三方的开源库来实现功能,等时机成熟了再去了解底层的源码和算法。我选的是一个常用的同时也是大家比较熟悉的开源库 FFmpeg。所以后面我们基于 FFmpeg + NDK 来开发音视频,等有了一定的经验我们再去阅读源码学习算法。
准备工作
首先我们得去编译 FFmpeg 的 so 库文件,而编译 so 库又涉及到 shell 脚本和 cmake 语法知识,所以我们又需要一个 linux 环境。我当初在学习这些基础知识时,买的是半年的云主机服务,如果大家本来就是用的 linux 系统或 mac 系统,那么就没必要再去购买云主机了。考虑到 Android 底层本身也是基于 linux 内核,趁着买了云主机的这个机会,我把 linux 内核的基础也学习了一遍。所以未来几个月的文章和视频,基本都是一些关于 shell 脚本,cmake 语法,linux 内核,音视频编解码,音视频通话,视频直播 等知识。