音视频及H264/H256编码相关原理

一、音视频封装格式原理:

          我们播放的视频文件一般都是用一种封装格式封装起来的,封装格式的作用是什么呢?一般视频文件里不光有视频,还有音频,封装格式的作用就是把视频和音频打包起来。 所以我们先要解封装格式,看有哪些视频流和哪些音频流,此时的音频流和视频流都还是压缩数据,不能直接用于显示的,这就需要解码。

        

        如FFmpeg 视频文件就是一个容器 (视频流(H264) 音频流(aac))。

      1、视频文件封装格式:

          封装格式(也叫容器),就是将已经编码压缩好的视频轨和音频轨按照一定的格式放到一个文件中,也就是说仅仅是一个外壳,或者大家把它当成一个放视频轨和音频轨的文件夹也可以。

      2、音视频编码方式:

  • 视频编码方式:将视频像素数据(RGB,YUV 等)压缩成视频码流,从而降低视频的数据量。包含有HEVC(H265)、H264、MPEG4、MPEG2、VP9等;
  • 音频编码方式:将音频采样数据(PCM 等)压缩成音频码流,从而降低音频的数据量。包含有AAC、MP3、WMV、AC-3。

       3、编解码方式和封装格式的关系:

                「视频封装格式」= 视频 + 音频 +视频编解码方式 等信息的容器。

       4、RGB/YUV概念:

        通常我们采用RGB模型来表示颜色,RGB模型中,每种颜色需要3个数字分别表示R、G、B,每个数字占用1个bit字节,这样总共需要24bits

        YUV能更高效颜色模型用更少的bit来表示颜色,Y——表示亮度,也就是灰阶值,U和V表示色度分量。

  •  YCbCr颜色模型基本原理:

        假设我们定义一个 「亮度(Luminance)」 的概念来表示颜色的亮度,那它就可以用含 R、G、B 的表达式表示为:

    Y = kr*R + kg*G + kb*B

        Y 即「亮度」,kr、kg、kb 即 R、G、B 的权重值。

        可以定义一个 「色度(Chrominance)」 的概念来表示颜色的差异

    Cr = R – Y
    Cg = G – Y
    Cb = B – Y

        Cr、Cg、Cb 分别表示在 R、G、B 上的色度分量.。

  • YUV:关键是在于它的亮度信号 Y 和色度信号 U、V 是分离的,那就是说即使只有 Y 信号分量而没有 U、V 分量,我们仍然可以表示出图像,只不过图像是黑白灰度图像。在YCbCr 中 Y 是指亮度分量,Cb 指蓝色色度分量,而 Cr 指红色色度分量。
  • YCbCr 与 RGB 相互转换的公式:
    Y = 0.299R + 0.587G + 0.114B
    Cb = 0.564(B - Y)
    Cr = 0.713(R - Y)
    R = Y + 1.402Cr
    G = Y - 0.344Cb - 0.714Cr
    B = Y + 1.772Cb

        

二、H264编解码框架:

         视频编码方式就是指通过特定的压缩技术,将某个视频格式的文件转换成另一种视频格式的文件的方式。H.264和H265编码是目前视频格式中用得最广泛的编码方式,H.264创造了多参考帧、多块类型、整数变换、帧内预测等新的压缩技术,使用了更精细的分像素运动矢量(1/4、1/8)和新一代的环路滤波器,使得压缩性能大大提高,系统更加完善。H.265是ITUTVCEG继H.264之后所制定的新的视频编码标准。H.265标准围绕着现有的视频编码标准H.264,保留原来的某些技术,同时对一些相关技术加以改进。H.265旨在在有限的带宽下传输更高质量的网络视频,仅需要原先的一半带宽即可播放相同质量的视频。

        1、H264码流文件分层:

  • VCL(Video Coding Layer,视频编码层):负责高效的视频内容表示,VCL数据即编码处理的输出,它表示被压缩编码后的视频数据序列。
  • NAL(Network AbstractionLayer,网络提取层):负责以网络所要求的恰当的方式对数据进行打包和传送,是传输层。不管是在本地播放还是在网络上播放,都要通过这一层来传输。

        2、H264编码原理:

  •  H.264/AVC并未明确表述一个编解码器如何实现,而是规定了一个编码的视频比特流的句法和该比特流的解码方法,因此在实现上有较大的灵活性。H264和以前的H261、H.263、MPEG-1、MPEG-4 等的编解码器功能模块的组成类似,不同的部分是其内部各功能模块的细节部分,H.264编解码器的功能组成如下:

        

  •  H.264/AVC 编解码器的工作原理。H.264编码器采用变换和预测混合编码方式。编码时,首先输入的帧或场Fn以宏块为单位被编码器处理。宏块有帧内和帧间两种模式。帧内模式使用当前帧内已编码的宏块进行预测。帧间模式使用以往一个或多个帧作为参考进行运动预测。然后,对预测值和原始值的差值进行变换、量化、重新排序和编码,对量化系统X进行逆量化、逆变换后,与预测系统相加,得到未经滤波的uF*帧,对uF*帧进行块间滤波,得到当前重构帧 Fn*。而解码过程相对比较简单,对于编码器的各部分进行逆向操作,结果经逆量化、逆变换后通过滤波器得到重构输出图像。H.264编解码器工作原理如图:

        

         3、H264码流分析:

        H264码流的结构中包含 :H264视频序列——图像——片组——片——NALU——宏块 ——像素。从大到小排序               

  • H264编码格式:在 VCL数据传输或存储之前,这些编码的VCL数据先被映射或封装进NAL单元中。每个NAL单元包括一个原始字节序列负载(RBSP,RawByteSequencePayload)和一组对应于视频编码的 NAL 头信息。RBSP的基本结构:在原始编码数据的后面添加了结尾标记,一个比特“1”和若干比特“0”,以便字节对齐。H.264码流NAL单元序列如图        
  •  NAL Header:NAL头由一个字节组成,禁止位(1位)、重要性指示位(2位)、NALU类型(5位)。         

        

  •  RBSP:包括一系列的NAL单元,每个NAL单元包含一个RBSP。典型的RBSP单元序列。每个单元都按独立的NAL单元传送。NAL单元的信息头(1字节)定义了RBSP单元的类型,NAL单元的其余部分为RBSP数据。        

     

  • SODB ,String Of Data Bits 原始数据比特流:因为它是流的形式,所以长度不一定是8倍数,它是由 VLC 层产生的。由于我们计算机是以8倍数去处理数据所以计算机在处理H264时,就需要 RBSP。
  • RBSP,SODB + tailing bits (原始字节序列载荷):由于它是一个压缩流,SODB 不知道是在何处结束,所以算法在SODB最后一位补一个1,没有按字节对齐的则补 0。
  • EBSP (扩展字节序列载荷):在生成压缩流之后,在每一帧的开头加一个起始位,这个起始位一般是 00 00 00 01 或者是 00 00 01。所以在h264码流中规定每有两个连续的00 00,就增加一个0x03。
  • EBSP 和 RBSP的区别:NALU的组成部分为(NALU = NALU Header + RBSP),严格来说NALU的组成部分为(NALU = NALU Header + EBSP);
  •  NALU单元中的参数集:SPS(序列参数集)作用于一系列连续的编码图像;PSS(图像参数集)作用于编码视频序列中一个或多个独立的图像。参数集是一个独立的数据单位,不依赖于参数集外的其他句法元素。一个参数集不对应某个特定的图像或序列,同一序列参数集可以被一个或者多个图像参数集引用。同理,同一个图像参数集也可以被一个或者多个图像引用只在编码器认为需要更新参数集的内容时,才会发出新的参数集。         
  •  NALU中的视频帧:生成的H264视频帧是由多个切片组成的。一个H264的帧至少由一个切片组成,不能没有切片,可以是一个到多个不能没有。在网络传输的时候一个H264帧可能需要切开去传,一个一次传不完,这就按照切片来切。每一个切片组成一个NAL Unit。
  • 切片与宏块的关系:在切片数据中,包含若干个宏块。在一个宏块中,又包含了宏块类型、宏块预测、残差数据。

        4、H264码流结构图:        

         5、H264码流NAL单元解码流程:

        首先从NAL单元中提取出RBSP语法结构,然后按照下图所示的流程处理RBSP语法结构。输入的是NAL单元,输出结果是经过解码的当前图像的样值点。 NAL单元中分别包含了序列参数集和图像参数集。图像参数集和序列参数集在其他NAL单元传输过程中作为参考使用,在这些数据NAL单元的片头中,通过语法元素pic_parameter_set_id设置它们所使用的图像参数集编号;而相应的每个图像参数集中,通过语法元素seq_paramter_set_id设置他们使用的序列参数集编号。        

         6、H264解码详解:

         H264是新一代的编码标准,以高压缩高质量和支持多种网络的流媒体传输著称,在编码方面,我理解的他的理论依据是:参照一段时间内图像的统计结果表明,在相邻几幅图像画面中,一般有差别的像素只有10%以内的点,亮度差值变化不超过2%,而色度差值的变化只有1%以内。所以对于一段变化不大图像画面,我们可以先编码出一个完整的图像帧A,随后的B帧就不编码全部图像,只写入与A帧的差别,这样B帧的大小就只有完整帧的1/10或更小!B帧之后的C帧如果变化不大,我们可以继续以参考B的方式编码C帧,这样循环下去。这段图像我们称为一个序列(序列就是有相同特点的一段数据),当某个图像与之前的图像变化很大,无法参考前面的帧来生成,那我们就结束上一个序列,开始下一段序列,也就是对这个图像生成一个完整帧A1,随后的图像就参考A1生成,只写入与A1的差别内容。

  • GOP:在H264中图像以序列为单位进行组织,一个序列是一段图像编码后的数据流,以I帧开始,到下一个I帧结束。 

  • GOP序列说明:在 H.264协议里定义了3种帧,完整编码的帧叫I帧,参考之前的I帧生成的只对差异部分进行编码的帧叫P帧,还有一种参考前后的帧进行编码的帧叫B帧。在H264中图像以序列为单位进行组织,一个序列是一段图像编码后的数据流,以帧开始,到下一个I帧结束,中间部分也被称为一个GOP。一个序列的第一个图像叫作IDR图像(立即刷新图像),IDR图像都是I帧图像。H.264引入IDR图像是为了解码的重新同步,当解码器解码到IDR图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找下一个参数集,开始解码一个新的序列。这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码。一个序列就是一段内容差异不太大的图像编码后生成的一串数据流。当运动变化比较少时,一个序列可以很长,因为运动变化少就代表图像画面的内容变动很小,所以就可以是一个Ⅰ帧,然后一直是P帧、B帧。当运动变化多时,一个序列可能会比较短,比如只包含一个I和几个P、B帧。
  •  I帧:指帧内编码帧,I帧表示关键帧,你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)。特点如下:
    1. 它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;
    2. 解码时仅用I帧的数据就可以重构完整图像;
    3. I帧描述了图像背景和运动主体的详情;
    4. I帧不需要参考其他画面生成;
    5. I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各的质量);
    6. I帧是帧组GOP的基础帧(第1帧),在一组中只有一个I帧;
    7. I帧不需要考虑运动矢量;
    8. I帧所占数据的信息量比较大。
  • P帧的预测与重构:P帧是以I帧为参考帧,在I帧中找出P帧“某点”的预测值和运动矢量,取预测差值和运动矢量一起传送。在接收端根据运动矢量从I帧中找出P帧“某点”的预测值并与差值相加以得到P帧“某点”样值,从而可得到完整的P帧。 P帧特点如下::
    1. P帧是I帧后面相隔1~2帧的编码帧;
    2. P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差);
    3. 解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;
    4. P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧;
    5. P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧;
    6. 由于P帧是参考帧,它可能造成解码错误的扩散; 7.由于是差值传送,P帧的压缩比较高。
  • B帧:双向预测内插编码帧。B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别(具体比较复杂,有4种情况,但我这样说简单些),换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累。

        7、H264压缩技术原理:

        H264的基本原理其实非常简单,下我们就简单的描述一下H264压缩数据的过程。通过摄像头采集到的视频帧(按每秒 30 帧算),被送到 H264 编码器的缓冲区中。编码器先要为每一幅图片划分宏块。

        过程是:划分宏块——>划分子块——>帧分组——>运动估计与补偿——>帧间预测

  • 划分宏块:H264默认是使用 16X16 大小的区域作为一个宏块,也可以划分成 8X8 大小。划分好宏块后,计算宏块的象素值。
  •  划分子块:H264对比较平坦的图像使用 16X16 大小的宏块。但为了更高的压缩率,还可以在 16X16 的宏块上更划分出更小的子块。子块的大小可以是 8X16、 16X8、 8X8、 4X8、 8X4、 4X4非常的灵活。
  • 帧分组:为了达到相关帧通过预测的方法来压缩数据,就需要将视频帧进行分组。H264编码器会按顺序,每次取出两幅相邻的帧进行宏块比较,计算两帧的相似度。在这样一组帧中,经过编码后,我们只保留第一帖的完整数据,其它帧都通过参考上一帧计算出来。我们称第一帧为IDR/I帧,其它帧我们称为P/B帧,这样编码后的数据帧组我们称为GOP。
  • 运动估计与补偿:在H264编码器中将帧分组后,就要计算帧组内物体的运动矢量了。
  • 帧间预测:人眼对图象都有一个识别度,对低频的亮度很敏感,对高频的亮度不太敏感。所以基于一些研究,可以将一幅图像中人眼不敏感的数据去除掉。这样就提出了帧内预测技术。一幅图像被划分好宏块后,对每个宏块可以进行 9 种模式的预测。找出与原图最接近的一种预测模式。
  • 对残差数据做DCT:可以将残差数据做整数离散余弦变换,去掉数据的相关性,进一步压缩数据。
  • CABAC:帧内压缩是属于有损压缩技术。也就是说图像被压缩后,无法完全复原。而CABAC属于无损压缩技术。

        对于视频数据主要有两类数据冗余,一类是时间上的数据冗余,另一类是空间上的数据冗余。其中时间上的数据冗余是最大的。

        帧内(Intraframe)压缩也称为空间压缩(Spatial compression)。当压缩一帧图像时,仅考虑本帧的数据而不考虑相邻帧之间的冗余信息,这实际上与静态图像压缩类似。帧内一般采用有损压缩算法,由于帧内压缩是编码一个完整的图像,因此可以独立的解码、显示。帧内压缩一般达不到很高的压缩,跟编码jpeg差不多。

        ​ 帧间(Interframe)压缩的原理是:相邻几帧的数据有很大的相关性,或者说前后两帧信息变化很小的特点,也即连续的视频及其相邻帧之间具有冗余信息,根据这一特性,压缩相邻帧之间的冗余量就可以进一步提高压缩量,减少压缩比。帧间压缩也称为时间压缩,它通过比较时间轴上不同帧之间的数据进行压缩。帧间压缩一般是无损的。帧差值(Frame differencing)算法是一种典型的时间压缩发,它通过比较本帧与相邻帧之间的差异,仅记录本帧与其相邻帧的差值,这样可以大大减少数据量。

      8、H264压缩方法:

  • 分组:把几帧图像分为一组(GOP,也就是一个序列),为防止运动变化,帧数不宜取多;
  • 定义帧:将每组内各帧图像定义为三种类型,即 I 帧、B帧和P帧;
  • 预测帧:以帧作为基础帧,以帧预测P帧,再由 I 帧和P帧预测B帧;
  • 数据传输:最后将 I 帧数据与预测的差值信息进行存储和传输

三、H265编解码框架:

          H265又被称为HEVC(全称 HighEciency Video Coding,高效率视频编码)。

        1、与H264的编码类比:

  • 以宏块来划分图像,并最终以块来细分。
  • 使用帧内压缩技术减少空间冗余。
  • 使用帧内压缩技术减少时间冗余(运动估计和补偿)。
  • 使用转换和量化来进行残留数据压缩。
  • 使用熵编码减少残留、运动矢量传输和信号发送中的最后几余,

        2、H265码流结构:

        

        3、网络分层结构 VCL和 NAL:

        与 H264/AVC 类似,H265/HEVC采用了视频编码层(Video Code Layer,VCL)和网络适配层(Network Abstract Layer,NAL),VCL层包含了视频数据的内容,NAL主要负责对视频压缩后的数据进行划分和封装,保证数据能在不同的网络环境中传输。通过NAL,视频压缩数据将被根据其内容特性分割成具有不同特性的NAL单元(NALUnit,NALU),并对NALU的内容特性进行标示。因此,传输网络根据NALU的标示就可以优化视频传输的性能,而不需要再分析视频的内容特征。NALU可以直接作为载体进行传输,而由于不同网络支持的最大传输单元(Maximum Transmission Unit,MTU)是不一样的,因此存在一个网络分组包含一个或者多个NALU,或者多个网络分组包含一个NALU。

        对于一个码流文件来说,其中包含一系列 NAL头,根据H265对NALU的类型定义,可以解析出其是 VPS、SPS、PPS等6种类型。

  • H265的一个图像序列的组成:VPS+SPS+PPS+SEI+一个I帧+若干个P帧。VPS.
    SPS、PPS、SEI、一个I帧、一个P帧都可以被称为一个 NALU。
  • H265的NALU 结构:开始码+NALU头+NALU 数据。
  • 6种类型的NALU:VPS(视频参数集)、SPS(序列参数集)、PPS(图像参数集):、SEI(补充增强信息)、I帧、P帧;
  • H.265的 NALU 打包成 RTP包的模式(两种模式):一个NALU打包成一个RTP包,只需要在一个12字节的RTP 包头后添加去掉开始码的 NALU 即可(这种模式在一个 NALU 的大小小于 MTU 时使用);   一个NALU打包成几个RTP包(FU模式),在12字节的RTP头后面有2字节的PayloadHdr和1字节的 FU header。PayloadHdr 的值等于 NALU 头的 type 位改为 49(十进制数)后的值。FU header第1位标记RTP包是否为NALU的第一片,第2位标记 RTP 包是否为 NALU的最后一片,后6位是NALU头的type位。

        4、网络适配层单元NALU:

        NAL根据视频压缩数据的规则,可以封装成不同的NALU,NALU包含 VPS、SPS、PPS类型的NALU类型信息,还包含视频片(Slice)的压缩数据。包含视频片压缩数据的NALU,被称为 VCLU(VCLNALU),包含其他信息的压缩数据的NALU,则被称为non-VCLU(non-VCLNALU)。H.265/HEVC下的NALU包含两部分数据结构:NALU头(Header)和负载(Payload),NALU头长度为固定的2字节,反映NALU的内容特征,而NALU负载长度为整数字节,包含视频压缩后的原始字节序列负载(RawByteSequencePayload,RBSP)。RBSP是对视频编码后的原始比特流片段SODB(STring OF Data Bits)进行添加尾部(添加结尾比特1,以凑足整字节)的包装。

        RBSP可以包含 VPS、SPS、PPS、SEI等基本码流所需的信息,也包含定界、序列结束比特流结束、填充数据等。在字节流环境中,如果NALU对应的Slice为1帧的开始,则其开始码为0x00000001:如果对应的Slice不是1帧的开始,则为0x000001。为避免ALU负载中的字节流片段与NALU的起始码及结束码发生冲突,需要对RBSP字节流做避免冲突处理,经过处理后的RBSP才可以直接作为NALU的负载信息。

  • 29
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
h.264视频编解码源代码.rar 详细说明:h.264标准代码,用于视频编码!可以实现各种视频编码和解码,可以在这个代码的基础上进行各种开发,比如算法的优化,转码技术,实现各种分辨了的转码-h.264 standard code, uses in the video frequency code! May realize each kind of video frequency code and the decoding, may carry on each kind of development in this code foundation, for instance the algorithm optimization, transfers the code technology, realizes each kind has distinguished extension code 文件列表: jm73 ....\JM ....\..\bin ....\..\...\decoder.cfg ....\..\...\encoder.cfg ....\..\...\lencod.exe ....\..\...\lencod.map ....\..\...\lencod.pdb ....\..\CHANGES.TXT ....\..\Changes_detail.txt ....\..\copyright.txt ....\..\disclaimer.txt ....\..\doc ....\..\...\coding_style.doc ....\..\...\doxygen.txt ....\..\...\h26l.css ....\..\...\ldecod.dox ....\..\...\lencod.dox ....\..\encoder.cfg ....\..\foreman_part_qcif.yuv ....\..\ldecod ....\..\......\inc ....\..\......\...\annexb.h ....\..\......\...\biaridecod.h ....\..\......\...\block.h ....\..\......\...\cabac.h ....\..\......\...\context_ini.h ....\..\......\...\contributors.h ....\..\......\...\ctx_tables.h ....\..\......\...\defines.h ....\..\......\...\elements.h ....\..\......\...\erc_api.h ....\..\......\...\erc_do.h ....\..\......\...\erc_globals.h ....\..\......\...\errorconcealment.h ....\..\......\...\fmo.h ....\..\......\...\global.h ....\..\......\...\header.h ....\..\......\...\image.h ....\..\......\...\leaky_bucket.h ....\..\......\...\macroblock.h ....\..\......\...\mbuffer.h ....\..\......\...\mb_access.h ....\..\......\...\memalloc.h ....\..\......\...\nalu.h ....\..\......\...\nalucommon.h ....\..\......\...\output.h ....\..\......\...\parset.h ....\..\......\...\parsetcommon.h ....\..\......\...\rtp.h ....\..\......\...\sei.h ....\..\......\...\vlc.h ....\..\......\Makefile ....\..\......\src ....\..\......\...\annexb.c ....\..\......\...\biaridecod.c ....\..\......\...\block.c ....\..\......\...\cabac.c ....\..\......\...\context_ini.c ....\..\......\...\erc_api.c ....\..\......\...\erc_do_i.c ....\..\......\...\erc_do_p.c ....\..\......\...\errorconcealment.c ....\..\......\...\filehandle.c ....\..\......\...\fmo.c ....\..\......\...\header.c ....\..\......\...\image.c ....\..\......\...\ldecod.c ....\..\......\...\leaky_bucket.c ....\..\......\...\loopFilter.c ....\..\......\...\macroblock.c ....\..\......\...\mbuffer.c ....\..\......\...\mb_access.c ....\..\......\...\memalloc.c ....\..\......\...\nal.c ....\..\......\...\nalu.c ....\..\......\...\nalucommon.c ....\..\......\...\nal_part.c ....\..\......\...\output.c ....\..\......\...\parset.c ....\..\......\...\parsetcommon.c ....\..\......\...\rtp.c ....\..\......\...\sei.c ....\..\......\...\vlc.c ....\..\ldecod.dsp ....\..\ldecod.dsw ... ...

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值