美文网首页
Android视音频基础知识

Android视音频基础知识

作者: 咸鱼Jay | 来源:发表于2022-09-25 11:47 被阅读0次

    学术概念

    采样和采样频率:

    ⼀秒钟内采样的次数称为采样频率。采样频率越⾼,越接近原始信号,但是也加⼤了运算处理的复杂度。根据Nyquist采样定理,要想重建原始信号,采样频率必须⼤于信号中最⾼频率的两倍。⼈能感受到的频率范围为20HZ--20kHZ, ⼀般⾳乐的采样频率为44.1kHZ, 更⾼的可以是48kHZ和96kHZ,不过⼀般⼈⽤⽿听感觉不出差别了。语⾳主要是以沟通为主,不需要像⾳乐那样清晰,⽤16k采样的语⾳就称为⾼清语⾳了。现在主流的语⾳采样频率为16kHz。

    采样位数

    数字信号是⽤0和1来表示的。采样位数就是采样值⽤多少位0和1来表示,也叫采样精度,⽤的位数越多就越接近真实声⾳。如⽤8位表示,采样值取值范围就是-128--127,如⽤16位表示,采样值取值范围就是-32768--32767。现在⼀般都⽤16位采样位数。

    声道:

    声道是指处理的声⾳是单声道还是⽴体声。Android⽀持双声道⽴体声和单声道。CHANNEL_IN_MONO单声道,CHANNEL_IN_STEREO⽴体声。单声道在声⾳处理过程中只有单数据流,⽽⽴体声则需要左、右声道的两个数据流。显然,⽴体声的效果要好,但相应的数据量要⽐单声道的数据量加倍。

    码率:

    就是⽐特率。⽐特率是指每秒传送的⽐特(bit)数,就是单位时间播放连续的媒体(如压缩后的音频或视频)的比特数量。比特率越高,带宽消耗得越多。

    ⾳频采集和播放:

    ⼀般⽤专⻔的芯⽚(通常叫codec芯⽚)采集⾳频,做AD转换,然后把数字信号通过I2S总线(主流⽤I2S总线,也可以⽤其他总线,⽐如PCM总线)送给CPU处理(也有的会把codec芯⽚与CPU芯⽚集成在⼀块芯⽚中)。当要播放时CPU会把⾳频数字信号通过I2S总线送给codec芯⽚,然后做DA转换得到模拟信号再播放出来。

    视音频完整解码播放流程分析

    <span id="视音频完整解码播放流程分析"></span>


    视音频完整解码播放流程分析

    视音频完整录制编码流程分析

    <span id="视音频完整录制编码流程分析"></span>


    视音频完整录制编码流程分析

    为什么要编码,如何编码(编码原理) ?

    视频是连续的图像序列,由连续的帧构成,一帧即为一幅图像。
    由于人眼的视觉暂留效应,当帧序列以一定的速率播放时,我们看到的就是动作连续的视频。
    这么多连续的图像数据如果不经过编码的数据量太大了。
    
    比如一个1920x1080分辨率,32位(ARGB_8888),每秒30帧的视频,一秒钟需要1920*1080*32*30,大小大概为237MB 数据。
    

    编码的目的

    编码的目的,就是为了压缩。各种视频编码方式,都是为了让视频变得体积更小,有利于存储和传输。编码的 核心思想就是去除冗余信息。

    为什么可以压缩

    去除冗余信息

    1. 空间冗余 == 相邻像素重复:
      空间冗余:图像内部相邻像素之间存在较强的相关性多造成的冗余。

    2. 时间冗余 == 帧之间差值:
      时间冗余:视频图像序列中的不同帧之间的相关性所造成的冗余

    3. 视觉冗余 == 人类不敏感的颜色:深红色和浅红色OK,但是:红色偏一点点橘红色,你还分得清楚吗?
      视觉冗余:是指人眼不能感知或不敏感的那部分图像信息

    4. 信息熵冗余 == 熵编码-哈夫曼算法
      信息熵冗余:也称编码冗余,人们用于表达某一信息所需要的比特数总比理论上表示该信息所需要的最少比特 数要大,它们之间的差距就是信息熵冗余,或称编码冗余。

    5. 知识冗余 == 人类(头 身体 腿),汽车,房子 不需要记录
      知识冗余:是指在有些图像中还包含与某些验证知识有关的信息。

    无损压缩(Winzip)

    • 压缩前解压缩后图像完全一致
    • 压缩比低

    有损压缩(H.264)

    • 压缩前解压缩后图像不一致
    • 压缩比高
    • 利用人的视觉系统的特性(人眼能见的动画频率和图像细节有限制)

    视频编码格式

    名称 推出机构 推出时间 目前使用领域
    HEVC(H.265) MPEG/ITU-T 2013 研发中
    H.264 MPEG/ITU-T 2003 各个领域
    MPEG4 MPEG 2001 不温不火
    MPEG2 MPEG 1994 数字电视
    VP9 Google 2013 研发中
    VP8 Google 2008 不普及
    VC-1 Microsoft Inc. 2006 微软平台
    ...... ...... ...... ......

    音频编码格式

    名称 推出机构 推出时间 目前使用领域
    AAC MPEG 1997 各个领域(新)
    AC-3 Dolby Inc. 1992 电影
    MP3 MPEG 1993 各个领域(旧)
    WMA Microsoft Inc. 1999 微软平台
    ...... ...... ...... ......

    封装格式

    名称 推出机构 流媒体 支持的视频编码 支持的音频编码 目前使用领域
    AVI Microsoft Inc. 不支持 几乎所有格式 几乎所有格式 BT下载影视
    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, IPTV,数字电视
    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 BT下载影视
    ......

    流媒体协议

    名称 推出机构 传输层协议 客户端 目前使用领域
    RTSP+RTP IETF TCP+UDP VLC, WMP IPTV
    RTMP Adobe Inc. TCP Flash 互联网直播
    RTMFP Adobe Inc. UDP Flash 互联网直播
    MMS Microsoft Inc. TCP/UDP WMP 互联网直播+点播
    HTTP-FLV WWW+IETF TCP Flash 互联网直播
    HLS(http live stream) APPLE TCP/UDP Flash 互联网直播+点播

    H264介绍

    一、H264 概述

    H.264,通常也被称之为H.264/AVC(或者H.264/MPEG-4 AVC或MPEG-4/H.264 AVC)

    1.H.264视频编解码的意义

    H.264的出现就是为了创建比以前的视频压缩标准更高效的压缩标准,使用更好高效的视频压缩算法来压缩视频的占用空间,提高存储和传输的效率,在获得有效的压缩效果的同时,使得压缩过程引起的失真最小。MPEG-4 AVC和H.264 是目前较为主流的编码标准。主要定义了两方面的内容:视频数据压缩形式的编码表示和用重建视频信息的语法来描述编码方法。目的是为了保证兼容的编码器能够成功的交互工作,同时也允许制造厂商自由的开发具有竞争力的创新产品。制造厂商只需要注意的事情就是能够获得和标准中采用的方法同样的结果。

    2.H.264编解码的理论依据

    提到H.264编解码,我们先简单说一下视频压缩算法。视频压缩算法是通过去除时间、空间的冗余来实现的。在一段时间内,相邻的图像的像素、亮度与色温的差别很小,我们没比要对每一个图像进行完成的编码,而是可以选取这段时间的第一张图(也就是第一帧)作为完整的编码,而后面一段时间的图像只需要记录与第一张图(第一帧)在像素、亮度、色温等方面的差别数据即可。通过去除不同类型的冗余,可以明显的压缩数据,代价就是一部分信息失真。

    H.264编解码在整个视频数据处理过程中,属于视频数据处理的编解码层,具体的可以查看本人总结的编解码流程图中的解码部分:视音频完整解码播放流程分析。编码部分将流程反过来进行理解即可视音频完整录制编码流程分析

    二、H.264相关概念

    1. H.264 的基本单位

    在H.264定义的结构中,一个视频图像编码后的数据叫做一帧。 一帧是由一个或多个片(slice)组成的,一个片是由一个或多个宏块(MB)组成的(宏块是H264编码的基本单位),一个宏块是由16x16的yuv数据组成的。

    2. 帧类型

    在H.264的协议中,定义了三类帧,分别是I帧、B帧和P帧。其中I帧就是之前我们所说的一个完整的图像帧,而B帧和P帧对应的就是之前说的不对全部图像做编码的帧。B帧和P帧的差别在于,P帧是参考之前的I帧生成的,B帧是参考前后的图像帧生成的。

    在视频画面播放过程中,若I帧丢失了,则后面的P帧也就随着解不出来,就会出现视频画面黑屏的现象;若P帧丢失了,则视频画面会出现花屏、马赛克等现象。

    I帧、B帧、P帧

    I帧:帧内编码帧,关键帧,I帧可以看作一个图像经过压缩之后的产物,可以单独解码出一个完整的图像; (压缩率最低)

    P帧:前向预测/参考编码帧,记录了本帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画 面叠加上本帧定义的差别,生成最终画面。 (压缩率比I帧高,比B帧低 属于 适中情况)

    B帧:双向预测/参考 编码帧,记录了本帧与前后帧的差别,解码需要参考前面一个I帧或者P帧,同时也需要 后面的P帧才能解码一张完整的图像。 (参考前后的预测得到的,压缩率是最高,但是耗时)

    I帧、B帧、P帧
    • I帧:自身可以通过视频解压算法解压成一张单独的完整的图片。

    • P帧:需要参考其前面的一个I帧或者B帧来生成一张完整的图片。

    • B帧:则要参考其前一个I或者P帧及其后面的一个P帧来生成一张完整的图片。

    • DTS:Decode Time Stamp(解码时间戳)。DTS主要是标识读入内存中的帧数据在什么时候开始送入解码器中进行解码。

    • PTS:Presentation Time Stamp(显示时间戳)。PTS主要用于度量解码后的视频帧什么时候被显示出来

    在没有B帧存在的情况下DTS的顺序和PTS的顺序应该是一样的。
    因为B帧打乱了解码和显示的顺序(要解码B帧需要先解码后面的P帧),所以一旦存在B帧,PTS和DTS就会不同。
    DTS主要用于视频的解码,在解码阶段使用。PTS主要用于视频的同步和输出.在显示的时候使用。

    dts与pts.jpg

    如上图:I帧的解码不依赖于任何的其它的帧.而p帧的解码则依赖于其前面的I帧或者P帧,B帧的解码则依赖于其前的最近的一个I帧或者P帧及其后的最近的一个P帧。

    3. GOP(画面组)

    GOP:两个I帧之间是一个图像序列,在一个图像序列中只有一个I帧


    GOP

    一个GOP(Group Of Picture)就是一组连续的画面GOP结构一般有两个数字,其中一个是GOP的长度(即两个I帧之间的B帧和P帧数),另一个数字为I帧和P帧之间的间隔距离(即B帧数)。在一个GOP内I帧解码不依赖任何的其它帧,P帧解码则依赖前面的I帧或P帧,B帧解码依赖前面的I帧或P帧及其后最近的一个P帧。

    注意:在码率不变的前提下,GOP值越大,P、B帧的数量会越多,平均每个I、P、B帧所占用的字节数就越多,也就更容易获取较好的图像质量;Reference越大,B帧的数量越多,同理也更容易获得较好的图像质量。但是通过提高GOP值来提高图像质量是有限度的。H264编码器在遇到场景切换的情况时,会自动强制插入一个I帧,此时实际的GOP值被缩短了。另一方面,在一个GOP中,P、B帧是由I帧预测得到的,当I帧的图像质量比较差时,会影响到一个GOP中后续P、B帧的图像质量,直到下一个GOP开始才有可能得以恢复,所以GOP值也不宜设置过大。同时,由于P、B帧的复杂度大于I帧,所以过多的P、B帧会影响编码效率,使编码效率降低。另外,过长的GOP还会影响Seek操作的响应速度,由于P、B帧是由前面的I或P帧预测得到的,所以Seek操作需要直接定位,解码某一个P或B帧时,需要先解码得到本GOP内的I帧及之前的N个预测帧才可以,GOP值越长,需要解码的预测帧就越多,seek响应的时间也越长。

    4. IDR 帧

    GOP中的I帧又分为普通I帧和IDR帧,IDR帧就是GOP的第一个I帧,这样区分视为了方便控制编码和解码的流程。 IDR帧一定是I帧,但是I帧不一定是IDR帧。

    IDR帧因为附带SPS、PPS等信息,解码器在收到 IDR 帧时,需要做的工作就是:把所有的 PPS 和 SPS 参数进行更新。

    可以看出来IDR帧的作用是让解码器立刻刷新相关数据信息,避免出现较大的解码错误问题。

    引入IDR帧机制是为了解码的重同步,当解码器解码到 IDR帧时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。这样,如果前一个序列出现错误,在这里可以获得重新同步的机会。IDR帧之后的帧永远不会使用IDR帧之前的数据来解码。

    三、H.264 压缩方式

    1. H.264 压缩算法

    H264 的核心压缩算法是帧内压缩和帧间压缩,帧内压缩是生成I帧的算法,帧间压缩是生成B帧和P帧的算法。
    帧内(Intraframe)压缩的原理是:当压缩一帧图像时,仅考虑本帧的数据而不考虑相邻帧之间的冗余信息,一般采用有损压缩算法,由于帧内压缩是编码一个完整的图像,所以可以独立的解码、显示。帧内压缩率一般不高。
    帧间(Interframe)压缩的原理是:相邻几帧的数据有很大的相关性,或者说前后两帧信息变化很小的特点。连续的视频其相邻帧之间具有冗余信息,根据这一特性,压缩相邻帧之间的冗余量就可以进一步提高压缩量,减小压缩比。

    而帧间压缩也称为时间压缩(Temporalcompression),它通过比较时间轴上不同帧之间的数据进行压缩。帧间压缩是无损的,它通过比较本帧与相邻帧之间的差异,仅记录本帧与其相邻帧的差值,这样可以大大减少数据量。

    2. H.264压缩方式说明

    H.264压缩视频数据时的具体方式如下:

    a). 分组,也就是将一系列变换不大的图像归为一个组,即一个GOP;

    b). 定义帧,将每组的图像帧归分为I帧、P帧和B帧三种类型;

    c). 预测帧, 以I帧做为基础帧,以I帧预测P帧,再由I帧和P帧预测B帧;

    d). 数据传输, 最后将I帧数据与预测的差值信息进行存储和传输。

    四、H.264 分层结构

    H.264的主要目标是为了有高的视频压缩比和良好的网络亲和性,为了达成这两个⽬标,H264将系统框架分为两个层面,分别是视频编码层面(VCL)和网络抽象层面(NAL)。

    1. VLC层(Video Coding Layer)

    VLC层:对核⼼算法引擎、块、宏块及⽚的语法级别的定义,负责有效表示视频数据的内容,最终输出编码完的数据SODB。
    通俗的讲:负责高效的视频内容表示, VCL数据即编码处理的输出,它表示被压缩编码后的视频数据序列。

    2. NAL层(Network Abstraction Layer)

    NAL层:负责将VCL产生的比特字符串适配到各种各样的网络和多元环境中,覆盖了所有片级以上的语法级别。
    通俗的讲:负责以网络所要求的恰当的方式对数据进行打包和传送,是传输层。不管在本地播放还是网络播放,都要通过这一层来传输。

    VCL就是被压缩编码后原始数据,在VCL数据封装到NAL单元中之后,才可以用于传输或存储。


    VCL和NAL的关系

    3. NALU (NAL Unit)

    H.264原始码流(裸流)是由一个接一个NALU组成,结构如下图,一个NALU = 一组对应于视频编码的NALU头部信息 + 一个原始字节序列负荷(RBSP,Raw Byte Sequence Payload)。

    NALU结构图

    一个原始的H.264 NALU 单元常由 [StartCode] [NALU Header] [NALU Payload] 三部分组成。

    3.1 Start Code

    Start Code 用于标示这是一个NALU 单元的开始,必须是”00 00 00 01” 或”00 00 01”。

    3.2. NAL Header

    NAL Header由三部分组成,forbidden_bit(1bit),nal_reference_bit(2bits)(优先级),nal_unit_type(5bits)(类型)。

    3.3 RBSP(Raw Byte Sequence Payload))

    下图是RBSP的序列的样例及相关类型参数的描述表:


    SPS是序列参数集,包含的是针对一连续编码视频序列的参数,如标识符 seq_parameter_set_id、帧数及 POC 的约束、参考帧数目、解码图像尺寸和帧场编码模式选择标识等等。

    PPS是图像参数集,对应的是一个序列中某一幅图像或者某几幅图像,其参数如标识符 pic_parameter_set_id、可选的 seq_parameter_set_id、熵编码模式选择标识、片组数目、初始量化参数和去方块滤波系数调整标识等等。

    参数集是一个独立的数据单位,不依赖于参数集之外的其他句法元素。一个参数集不对应某一个特定的图像或者序列,同一个序列参数集可以被一个或者多个图像参数集引用。同理,一个图像参数集也可以被一个或者多个图像引用。只有在编码器认为需要更新参数集的内容时,才会发出新的参数集。

    一帧图片经过 H.264 编码器之后,NAL单元就是装载着这些片(被编码为一个或多个片 slice), 每片包含整数个宏块(至少一个宏块,最多包含整个图像宏块)。


    NAL宏块

    在传输一组NAL数据时,如果数据是NALNALNALNALNALNALNALNAL这样数据,那么在解析的时候就无法解析,因为,没有分隔符。所以这里每个NAL之间添加起始码作为分隔符。

    一般H.264编码器的默认输出为:起始码+NALU(Nal单元)。起始码为:0x00000001或者0x000001。

    为什么需要起始码:0x00000001或者0x000001?
    答:因为每一个NALU都需要分隔,要分隔帧操作,就相对于写文章断句一样

    为什么 0x00000001或者0x000001,两种起始码?
    答:0x00000001 起始码代表:一个NALU里面有很多片。
    0x000001 起始码代表:一个NALU里面一个片可以搞定。
    反正你必须明白,遇到0x00000001或者0x000001,就是NALU的起始码来了

    从上面我们指定每个NALU是由(起始码+1个字节的NAL Header+ 若干整数字节的负荷数据RBSP)构成,这个头部信息是可以区分类型的,例如:I帧、P帧、B帧。通过下面的表可以查询到具体的类型。

    NAL单元类型码

    通过010Editor工具可以打开一个H264文件,如下图:


    010Editor工具打开H264文件

    查询0x00000001或者0x000001可以发现这些二进制串都是由起始码进行分割开的

    010Editor查询起始码信息

    先看第一组数据00 00 00 01 67,其中01前面就是起始码,后面的16进制67是1个字节的NAL Header,将这个0x67转2进制0110 0111,在取低5位0 0111,在转16进制0x07,查上面表可以看到是序列参数集,即SPS。

    为什么取低5位?
    一个字节有八个位,将这个八个位进行分组,如下图;


    第一组数据00 00 00 01 67-->长的起始码

    SPS 序列参数集(记录有多少I帧,多少B帧,多少P帧,帧是如何排列) == 7
    00 00 00 01 67,0x67 ---> 2进制0110 0111 ---> 取低五位0 0111 ---> 十六进制 0x07
    

    第二组数据00 00 00 01 68-->长的起始码

    PPS 图像参数集(图像宽高信息等) == 8
    00 00 00 01 68,0x68 ---> 2进制0110 1000 ---> 取低五位0 1000 ---> 十六进制 0x08
    

    第三组数据00 00 01 06-->短的起始码

    SEI辅助增强信息(可以记录坐标信息,人员信息, 后面解码的时候,可以通过代码获取此信息) https://blog.csdn.net/y601500359/article/details/80943990
    00 00 01 06 , 0x06 ---> 2进制0000 0110---> 取低五位0 0110 ---> 十六进制 0x06
    

    第四组数据00 00 00 01 65-->长的起始码

    IDR图像的编码条带,I帧完整画面出来
    00 00 00 01 65, 0x65 ---> 2进制0110 0101---> 取低五位0 0101 ---> 十六进制 0x05
    

    第五组数据00 00 01 41-->长的起始码

    普通的P帧
    00 00 00 01 41, 0x41 ---> 2进制0100 0001---> 取低五位0 0001 ---> 十六进制 0x01
    

    如果是00 00 01 61表示重要的P帧

    重要的P帧,因为2进制的第二组是11,代表这个帧很重要
    00 00 00 01 61, 0x61 ---> 2进制0110 0001---> 取低五位0 0001 ---> 十六进制 0x01
    

    第六组数据00 00 00 01 01-->长的起始码

    B帧
    00 00 00 01 01, 0x01 ---> 2进制0000 0001---> 取低五位0 0001 ---> 十六进制 0x01
    

    注意:真正开发中只分析:SPS序列参数集,PPS图像参数集,I帧

    五、H.264 局限性

    随着数字视频应用产业链的快速发展,视频应用向以下几个方向发展的趋势愈加明显:

    (1) 高清晰度(HigherDefinition):数字视频的应用格式从720P向1080P全面升级,而且现在4K的数字视频格式也已经成为常见。

    (2) 高帧率(Higherframe rate ):数字视频帧率从30fps向60fps、120fps甚至240fps的应用场景升级;

    (3) 高压缩率(HigherCompression rate ):传输带宽和存储空间一直是视频应用中最为关键的资源,因此,在有限的空间和管道中获得最佳的视频体验一直是用户的不懈追求。

    但是面对视频应用不断向高清晰度、高帧率、高压缩率方向发展的趋势,当前主流的视频压缩标准协议H.264的局限性不断凸显。主要体现在:
    (1) 宏块个数的爆发式增长,会导致用于编码宏块的预测模式、运动矢量、参考帧索引和量化级等宏块级参数信息所占用的码字过多,用于编码残差部分的码字明显减少。

    (2) 由于分辨率的大大增加,单个宏块所表示的图像内容的信息大大减少,这将导致相邻的4 x 4或8 x 8块变换后的低频系数相似程度也大大提高,导致出现大量的冗余。

    (3) 由于分辨率的大大增加,表示同一个运动的运动矢量的幅值将大大增加,H.264中采用一个运动矢量预测值,对运动矢量差编码使用的是哥伦布指数编码,该编码方式的特点是数值越小使用的比特数越少。因此,随着运动矢量幅值的大幅增加,H.264中用来对运动矢量进行预测以及编码的方法压缩率将逐渐降低。

    (4) H.264的一些关键算法例如采用CAVLC和CABAC两种基于上下文的熵编码方法、deblock滤波等都要求串行编码,并行度比较低。针对GPU/DSP/FPGA/ASIC等并行化程度非常高的CPU,H.264的这种串行化处理越来越成为制约运算性能的瓶颈。

    于是面向更高清晰度、更高帧率、更高压缩率视频应用的HEVC(H.265)协议标准应运而生。H.265在H.264标准2~4倍的复杂度基础上,将压缩效率提升一倍以上。

    (注意:实际使用过程中,不能忽视265专利费用这个重要的问题。专利问题参考:H.265成超级提款机 一场围绕专利授权的战争已经爆发)

    参考:
    H.264---(I、P、B帧)(I帧和IDR帧)(DTS和PTS、time_base)

    相关文章

      网友评论

          本文标题:Android视音频基础知识

          本文链接:https://www.haomeiwen.com/subject/ywkzortx.html