专栏首页猫哥的专栏【Android 音视频开发打怪升级:音视频硬解码篇】一、音视频基础知识

【Android 音视频开发打怪升级:音视频硬解码篇】一、音视频基础知识

一、视频是什么?
动画书

不知道大家小时候是否玩过一种动画小人书,连续翻动的时候,小人书的画面就会变成一个动画,类似现在的gif格式图片。

动画书:来源网络

本来是一本静态的小人书,通过翻动以后,就会变成一个有趣的小动画,如果画面够多,翻动速度够快的话,这其实就是一个小视频。

而视频的原理正是如此,由于人类眼睛的特殊结构,画面快速切换时,画面会有残留,感觉起来就是连贯的动作。所以,视频就是由一系列图片构成的

视频帧

帧,是视频的一个基本概念,表示一张画面,如上面的翻页动画书中的一页,就是一帧。一个视频就是由许许多多帧组成的。

帧率

帧率,即单位时间内帧的数量,单位为:帧/秒 或fps(frames per second)。如动画书中,一秒内包含多少张图片,图片越多,画面越顺滑,过渡越自然。

帧率的一般以下几个典型值:

24/25 fps:1秒 24/25 帧,一般的电影帧率。

30/60 fps:1秒 30/60 帧,游戏的帧率,30帧可以接受,60帧会感觉更加流畅逼真。

85 fps以上人眼基本无法察觉出来了,所以更高的帧率在视频里没有太大意义。

色彩空间

这里我们只讲常用到的两种色彩空间。

  • RGB

RGB的颜色模式应该是我们最熟悉的一种,在现在的电子设备中应用广泛。通过R G B三种基础色,可以混合出所有的颜色。

  • YUV

这里着重讲一下YUV,这种色彩空间并不是我们熟悉的。这是一种亮度与色度分离的色彩格式。

早期的电视都是黑白的,即只有亮度值,即Y。有了彩色电视以后,加入了UV两种色度,形成现在的YUV,也叫YCbCr。

Y:亮度,就是灰度值。除了表示亮度信号外,还含有较多的绿色通道量。

U:蓝色通道与亮度的差值。

V:红色通道与亮度的差值。

采用YUV有什么优势呢?

人眼对亮度敏感,对色度不敏感,因此减少部分UV的数据量,人眼却无法感知出来,这样可以通过压缩UV的分辨率,在不影响观感的前提下,减小视频的体积。

RGB和YUV的换算
Y = 0.299R + 0.587G + 0.114B 
U = -0.147R - 0.289G + 0.436B
V = 0.615R - 0.515G - 0.100B
——————————————————
R = Y + 1.14V
G = Y - 0.39U - 0.58V
B = Y + 2.03U

二、音频是什么?

音频数据的承载方式最常用的是脉冲编码调制,即PCM

在自然界中,声音是连续不断的,是一种模拟信号,那怎样才能把声音保存下来呢?那就是把声音数字化,即转换为数字信号。

我们知道声音是一种波,有自己的振幅和频率,那么要保存声音,就要保存声音在各个时间点上的振幅。

而数字信号并不能连续保存所有时间点的振幅,事实上,并不需要保存连续的信号,就可以还原到人耳可接受的声音。

根据奈奎斯特采样定理:为了不失真地恢复模拟信号,采样频率应该不小于模拟信号频谱中最高频率的2倍。

根据以上分析,PCM的采集步骤分为以下步骤:

模拟信号->采样->量化->编码->数字信号

音频采样

采样率和采样位数

采样率,即采样的频率。

上面提到,采样率要大于原声波频率的2倍,人耳能听到的最高频率为20kHz,所以为了满足人耳的听觉要求,采样率至少为40kHz,通常为44.1kHz,更高的通常为48kHz。

采样位数,涉及到上面提到的振幅量化。波形振幅在模拟信号上也是连续的样本值,而在数字信号中,信号一般是不连续的,所以模拟信号量化以后,只能取一个近似的整数值,为了记录这些振幅值,采样器会采用一个固定的位数来记录这些振幅值,通常有8位、16位、32位。

位数

最小值

最大值

8

0

255

16

-32768

32767

32

-2147483648

2147483647

位数越多,记录的值越准确,还原度越高。

最后就是编码了。由于数字信号是由0,1组成的,因此,需要将幅度值转换为一系列0和1进行存储,也就是编码,最后得到的数据就是数字信号:一串0和1组成的数据。

整个过程如下:

声道数

声道数,是指支持能不同发声(注意是不同声音)的音响的个数。

单声道:1个声道 双声道:2个声道 立体声道:默认为2个声道 立体声道(4声道):4个声道

码率

码率,是指一个数据流中每秒钟能通过的信息量,单位bps(bit per second)

码率 = 采样率 * 采样位数 * 声道数

三、为什么要编码

这里的编码和上面音频中提到的编码不是同个概念,而是指压缩编码

我们知道,在计算机的世界中,一切都是0和1组成的,音频和视频数据也不例外。由于音视频的数据量庞大,如果按照裸流数据存储的话,那将需要耗费非常大的存储空间,也不利于传送。而音视频中,其实包含了大量0和1的重复数据,因此可以通过一定的算法来压缩这些0和1的数据。

特别在视频中,由于画面是逐渐过渡的,因此整个视频中,包含了大量画面/像素的重复,这正好提供了非常大的压缩空间。

因此,编码可以大大减小音视频数据的大小,让音视频更容易存储和传送。

四、视频编码

视频编码格式

视频编码格式有很多,比如H26x系列和MPEG系列的编码,这些编码格式都是为了适应时代发展而出现的。

其中,H26x(1/2/3/4/5)系列由ITU(International Telecommunication Union)国际电传视讯联盟主导

MPEG(1/2/3/4)系列由MPEG(Moving Picture Experts Group, ISO旗下的组织)主导。

当然,他们也有联合制定的编码标准,那就是现在主流的编码格式H264,当然还有下一代更先进的压缩编码标准H265。

H264编码简介

H264是目前最主流的视频编码标准,所以我们后续的文章中主要以该编码格式为基准。

H264由ITU和MPEG共同定制,属于MPEG-4第十部分内容。

由于H264编码算法十分复杂,不是一时半刻能够讲清楚的,也不在本人目前的能力范围内,所以这里只简单介绍在日常开发中需要了解到的概念。实际上,视频的编码和解码部分通常由框架(如Android硬解/FFmpeg)完成,一般的开发者并不会接触到。

  • 视频帧

我们已经知道,视频是由一帧一帧画面构成的,但是在视频的数据中,并不是真正按照一帧一帧原始数据保存下来的(如果这样,压缩编码就没有意义了)。

H264会根据一段时间内,画面的变化情况,选取一帧画面作为完整编码,下一帧只记录与上一帧完整数据的差别,是一个动态压缩的过程。

在H264中,三种类型的帧数据分别为

I帧:帧内编码帧。就是一个完整帧。

P帧:前向预测编码帧。是一个非完整帧,通过参考前面的I帧或P帧生成。

B帧:双向预测内插编码帧。参考前后图像帧编码生成。B帧依赖其前最近的一个I帧或P帧及其后最近的一个P帧。

  • 图像组:GOP和关键帧:IDR

全称:Group of picture。指一组变化不大的视频帧。

GOP的第一帧成为关键帧:IDR

IDR都是I帧,可以防止一帧解码出错,导致后面所有帧解码出错的问题。当解码器在解码到IDR的时候,会将之前的参考帧清空,重新开始一个新的序列,这样,即便前面一帧解码出现重大错误,也不会蔓延到后面的数据中。

注:关键帧都是I帧,但是I帧不一定是关键帧

  • DTS与PTS

DTS全称:Decoding Time Stamp。标示读入内存中数据流在什么时候开始送入解码器中进行解码。也就是解码顺序的时间戳。

PTS全称:Presentation Time Stamp。用于标示解码后的视频帧什么时候被显示出来。

在没有B帧的情况下,DTS和PTS的输出顺序是一样的,一旦存在B帧,PTS和DTS则会不同。

  • 帧的色彩空间

前面我们介绍了RGB和YUV两种图像色彩空间。H264采用的是YUV。

YUV存储方式分为两大类:planar 和 packed。

planar:先存储所有Y,紧接着存储所有U,最后是V; packed:每个像素点的 Y、U、V 连续交叉存储。

planar如下:

YUV Planar

packed如下:

YUV Packed

不过pakced存储方式已经非常少用,大部分视频都是采用planar存储方式。

上面说过,由于人眼对色度敏感度低,所以可以通过省略一些色度信息,即亮度共用一些色度信息,进而节省存储空间。因此,planar又区分了以下几种格式: YUV444、 YUV422、YUV420。

YUV 4:4:4采样,每一个Y对应一组UV分量。

YUV 4:2:2采样,每两个Y共用一组UV分量。

YUV 4:2:0采样,每四个Y共用一组UV分量。

其中,最常用的就是YUV420

  • YUV420格式存储方式

YUV420属于planar存储方式,但是又分两种类型:

YUV420P:三平面存储。数据组成为YYYYYYYYUUVV(如I420)或YYYYYYYYVVUU(如YV12)。

YUV420SP:两平面存储。分为两种类型YYYYYYYYUVUV(如NV12)或YYYYYYYYVUVU(如NV21)

关于H264的编码算法和数据结构,涉及的知识和篇幅很多(如网络抽象层NAL、SPS、PPS),本文不再深入细说,网上也有比较多的教程讲解,有兴趣可以自行深入学习。

入门理解H264编码

五、音频编码

音频编码格式

原始的PCM音频数据也是非常大的数据量,因此也需要对其进行压缩编码。

和视频编码一样,音频也有许多的编码格式,如:WAV、MP3、WMA、APE、FLAC等等,音乐发烧友应该对这些格式非常熟悉,特别是后两种无损压缩格式。

但是,我们今天的主角不是他们,而是另外一个叫AAC的压缩格式。

AAC是新一代的音频有损压缩技术,一种高压缩比的音频压缩算法。在MP4视频中的音频数据,大多数时候都是采用AAC压缩格式。

AAC编码简介

AAC格式主要分为两种:ADIF、ADTS。

ADIF:Audio Data Interchange Format。 音频数据交换格式。这种格式的特征是可以确定的找到这个音频数据的开始,不需进行在音频数据流中间开始的解码,即它的解码必须在明确定义的开始处进行。这种格式常用在磁盘文件中。

ADTS:Audio Data Transport Stream。 音频数据传输流。这种格式的特征是它是一个有同步字的比特流,解码可以在这个流中任何位置开始。它的特征类似于mp3数据流格式。

ADTS可以在任意帧解码,它每一帧都有头信息。ADIF只有一个统一的头,所以必须得到所有的数据后解码。且这两种的header的格式也是不同的,目前一般编码后的都是ADTS格式的音频流。

ADIF数据格式:

header

raw_data

ADTS 一帧 数据格式(中间部分,左右省略号为前后数据帧):

ADTS

AAC内部结构也不再赘述,可以参考AAC 文件解析及解码流程

六、音视频容器

细心的读者可能已经发现,前面我们介绍的各种音视频的编码格式,没有一种是我们平时使用到的视频格式,比如:mp4、rmvb、avi、mkv、mov...

没错,这些我们熟悉的视频格式,其实是包裹了音视频编码数据的容器,用来把以特定编码标准编码的视频流和音频流混在一起,成为一个文件。

例如:mp4支持H264、H265等视频编码和AAC、MP3等音频编码。

mp4是目前最流行的视频格式,在移动端,一般将视频封装为mp4格式。

七、硬解码和软解码

硬解和软解的区别

我们在一些播放器中会看到,有硬解码和软解码两种播放形式给我们选择,但是我们大部分时候并不能感觉出他们的区别,对于普通用户来说,只要能播放就行了。

那么他们内部究竟有什么区别呢?

在手机或者PC上,都会有CPU、GPU或者解码器等硬件。通常,我们的计算都是在CPU上进行的,也就是我们软件的执行芯片,而GPU主要负责画面的显示(是一种硬件加速)。

所谓软解码,就是指利用CPU的计算能力来解码,通常如果CPU的能力不是很强的时候,一则解码速度会比较慢,二则手机可能出现发热现象。但是,由于使用统一的算法,兼容性会很好。

硬解码,指的是利用手机上专门的解码芯片来加速解码。通常硬解码的解码速度会快很多,但是由于硬解码由各个厂家实现,质量参差不齐,非常容易出现兼容性问题。

Android平台的硬解码

终于来到有关Android的部分了,作为本文的结尾,也算是为下一篇文章开一个头。

MediaCodec 是Android 4.1(api 16)版本引入的编解码接口,是所有想在Android上开发音视频的开发人员绕不开的坑。

由于Android碎片化严重,虽然经过多年的发展,Android硬解已经有了很大改观,但实际上各个厂家实现不同, 还是会有一些意想不到的坑。

相对于FFmpeg,Android原生硬解码还是相对容易入门一些,所以接下来,我将会从MediaCodec入手,讲解如何实现视频的编解码,以及引入OpenGL实现对视频的编辑,最后才引入FFmpeg来实现软解,算是一个比较常规的音视频开发入门流程吧。

参考文章

音视频开发基础知识

YUV颜色编码解析

YUV数据格式

音频基础知识

AAC 文件解析及解码流程

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【Android 音视频开发打怪升级:音视频硬解码篇】二、音视频硬解码流程:封装基础解码框架

    MediaCodec 是Android 4.1(api 16)版本引入的编解码接口,同时支持音视频的编码和解码。

    开发的猫
  • [Glide4源码解析系列] — 3.Glide数据解码与转码

    继上一篇文章[Glide4源码解析系列]--2.Glide数据模型转换与数据抓取之后,已经过去几个月的时间,期间由于学习其他东西和项目的原因(其实是懒癌发作~)...

    开发的猫
  • 【Android 音视频开发打怪升级:FFmpeg音视频编解码篇】七、Android FFmpeg 视频编码

    本文是音视频系列文章的最后一篇了,也是拖了最久的一篇(懒癌发作-_-!!),终于下定决心,把坑填完。

    开发的猫
  • 一张图概括淘宝直播背后的前端技术 | 赠送多媒体前端手册

    2020年,直播带货火爆全网。想一探淘宝直播背后的前端技术?本文将带你进入淘宝直播前端技术的世界。

    glumes
  • 零基础入门:实时音视频技术基础知识全面盘点

    随着移动网络速度越来越快、质量越来越来,实时音视频技术已经在各种应用场景下全面开花,语音通话、视频通话、视频会议、远程白板、远程监控等等。

    JackJiang
  • Linux: Debian 9 Stretch可能将不支持Secure Boot

    Debian 团队宣布 Debian 9 Stretch 在发布时将不太可能会支持 Secure Boot。Debian 9 的代码在今年 2 月冻结,之后开发...

    Debian社区
  • 常见编码问题UnicodeEncodeError

    python 里面的编码和解码也就是 unicode 和 str 这两种形式的相互转化。编码是 unicode -> str,相反的,解码就是 str -> u...

    意气相许的许
  • Python入门之字符编码

    一、字节编码的基础知识 一、计算机基础知识 #1 我们的程序都是运行在特定的操作系统内,例如window,linux,mac等等 #2 运行应用程序,需要要操作...

    Jetpropelledsnake21
  • 工程实践,淘宝直播高画质低延时技术探索

    目前5G新基建正在迈入起航阶段,5G相比目前广泛使用的4G,它具有更高的速率,更大的容量,同时延迟更低,可靠性更高。在5G时代,视频得益于网络带宽的提升,未来将...

    CV君
  • Python2中的中文字符编解码浅析

    自动化测试过程中,输入文本、读取文件、解析网络请求、字符串断言、正则匹配这些步骤都是必不可少的。而Python是测试过程中最为常用的语言之一,很多测试团队的自动...

    腾讯移动品质中心TMQ

扫码关注云+社区

领取腾讯云代金券