ffmpeg之H264_ffmpeg h264-程序员宅基地

技术标签: 学习  FFmpeg学习  

目录

H264概念

压缩处理

I、B、P帧简介

I帧简介

P帧简介

B帧简介

SPS 和 PPS简介

压缩方式说明

划分宏块

划分子块

运动估计与补偿

对残差数据做DCT

编码处理


H264概念

        H264视频压缩算法现在无疑是所有视频压缩技术中使用最广泛,最流行的。随着 x264/openh264以及ffmpeg等开源库的推出,大多数使用者无需再对H264的细节做过多的研究,这大降低了人们使用H264的成本。

压缩处理

  • 帧内预测压缩,解决的是空域数据冗余问题。
  • 帧间预测压缩(运动估计与补偿),解决的是时域数据冗余问题。
  • 整数离散余弦变换(DCT),将空间上的相关性变为频域上无关的数据然后进行量化。
  • CABAC压缩。

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

I、B、P帧简介

       在H264协议内定义了三种帧,分别是I帧、B帧与P帧。I帧就是之前所说的一个完整的图像帧,而B、帧与P帧所对应的就是之前说的不编码全部图像的帧。P帧与B帧的差别就是P帧是参考之前的I帧而生成的,而B帧是参考前后图像帧编码生成的。

        经过压缩后的帧分为:I帧,P帧和B帧:

        I帧:关键帧,采用帧内压缩技术。你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)
        P帧:向前参考帧,在压缩时,只参考前面已经处理的帧。采用帧间压缩技术。P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。(也就是差别帧,P帧没有完整画面数据,只有与前一帧的画面差别的数据)
        B帧:双向参考帧,在压缩时,它既参考前而的帧,又参考它后面的帧。采用帧间压缩技术。B帧记录的是本帧与前后帧的差别(具体比较复杂,有4种情况),换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累~。

还有一个概念是,IDR帧:

        一个序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像。H.264 引入 IDR 图像是为了解码的重同步,当解码器解码到 IDR 图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码。IDR 图像一定是 I 图像,但I图像不一定是 IDR 图像。一个序列中可以有很多的I图像,I 图像之后的图像可以引用 I 图像之间的图像做运动参考。

        还需要补充一个概念(序列)

        一个序列就是一段内容差异不太大的图像编码后生成的一串数据流。当运动变化比较少时,一个序列可以很长,因为运动变化少就代表图像画面的内容变动很小,所以就可以编一个 I 帧,然后一直 P 帧、B 帧了。当运动变化多时,可能一个序列就比较短了,比如就包含一个 I 帧和 3、4个P帧。将视频分割为若干小的图像序列成为图像组(group  of  pictures ,GOP)。其中GOP可以分为封闭GOP以及开放GOP。在封闭非GOP中,每个GOP以IDR图像开始各个Gop为独立编解码;而在开放的GOP中,第一个GOP中的第一个图像为IDR图像,后续GOP中的第一个帧内编码图像为non-IDR图像,使用前一个GOP中已经编码的图像进行参考

PICTURE:/home/zhao/.config/tencent-qq//AppData/file//sendpix0.jpg

        GOP是画面组,一个GOP是一组连续的画面。GOP一般有两个数字,如M=3,N=12.M制定I帧与P帧之间的距离,N指定两个I帧之间的距离。那么现在的GOP结构是

I BBP BBP BBP BB I

I帧简介

I 帧、B帧、P帧还有一些特点,如下:
I帧特点:

  1. 它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;
  2. 解码时仅用I帧的数据就可重构完整图像;
  3. I帧描述了图像背景和运动主体的详情;
  4. I帧不需要参考其他画面而生成;
  5. I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);
  6. I帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧;
  7. I帧不需要考虑运动矢量;
  8. I帧所占数据的信息量比较大。

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帧特点:

  1. B帧是由前面的I或P帧和后面的P帧来进行预测的;
  2. B帧传送的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量;
  3. B帧是双向预测编码帧;
  4. B帧压缩比最高,因为它只反映丙参考帧间运动主体的变化情况,预测比较准确;加大B帧的数量可以有效地提高视频数据的压缩比,但是在实时互动的环境下,过多的B帧会引起延时,因为B帧会过分的依赖于前后帧,在网络好的环境下,可以正常的传输帧,这样没有什么问题,但是在网络不好的时候,B帧会等待其他帧到来,会引起延时

注:I、B、P各帧是根据压缩算法的需要,是人为定义的,它们都是实实在在的物理帧。一般来说,I帧的压缩率是7(跟JPG差不多)P帧是20,B帧可以达到50。可见使用B帧能节省大量空间,节省出来的空间可以用来保存多一些I帧,这样在相同码率下,可以提供更好的画质。

SPS 和 PPS简介

        SPS即Sequence Paramater Set,又称作序列参数集。SPS中保存了一组编码视频序列(Coded video sequence)的全局参数存放包括:帧数、参考帧数目、解码图像尺寸、帧场编码模式选择标识等所谓的编码视频序列即原始视频的一帧一帧的像素数据经过编码之后的结构组成的序列。而每一帧的编码后数据所依赖的参数保存于图像参数集中。一般情况SPS和PPS的NAL Unit通常位于整个码流的起始位置。但在某些特殊情况下,在码流中间也可能出现这两种结构,主要原因可能为:

        解码器需要在码流中间开始解码;编码器在编码的过程中改变了码流的参数(如图像分辨率等);H.264中另一重要的参数集合为图像参数集Picture Paramater Set(PPS)。和图像相关的参数集,存放包括:熵编码模式选择标识、片组数目、初始量化参数和去方块滤波系数调整标识等。通常情况下,PPS类似于SPS,在H.264的裸码流中单独保存在一个NAL Unit中只是PPS NAL Unit的nal_unit_type值为8;而在封装格式中,PPS通常与SPS一起,保存在视频文件的文件头中。

        在一组帧之前,首先要收到SPS 和 PPS ,不然的话是无法解码的。这两组数据划分为I帧,是不能丢的。

视频传输中会出现连个比较常见的现象,花屏 和 卡顿

(1)如果在GOP分组中的P帧丢失,会造成解码端的图像发生错误。这就是花屏。GOP一组帧呈现出的连贯效果,由于P帧丢失,它需要更新的部分就没有,所以无法正常呈现。故出现花屏现象。

(2)为了解决花屏的问题发生,我们可以将丢失 P帧 或是 I帧 的 GOP 丢掉(包含其中的所有帧),直到下一个I帧再重新刷新图像。但是由于这一帧丢掉了,所以会出现卡顿。
 

压缩方式说明

  1. Step1:分组,也就是将一系列变换不大的图像归为一个组,也就是一个序列,也可以叫GOP(画面组);
  2. Step2:定义帧,将每组的图像帧归分为I帧、P帧和B帧三种类型;
  3. Step3:预测帧, 以I帧做为基础帧,以I帧预测P帧,再由I帧和P帧预测B帧;
  4. Step4:数据传输, 最后将I帧数据与预测的差值信息进行存储和传输。

划分宏块

H264默认是使用 16X16 大小的区域作为一个宏块,也可以划分成 8X8 大小。

划分好宏块后,计算宏块的象素值。

 

以此类推,计算一幅图像中每个宏块的像素值,所有宏块都处理完后如下面的样子。 

 

划分子块

        H264对比较平滑的图像使用 16X16 大小的宏块。但为了更高的压缩率,还可以在 16X16 的宏块上更划分出更小的子块。子块的大小可以是 8X16、 16X8、 8X8、 4X8、 8X4、 4X4非常的灵活。

        上幅图中,红框内的 16X16 宏块中大部分是蓝色背景,而三只鹰的部分图像被划在了该宏块内,为了更好的处理三只鹰的部分图像,H264就在 16X16 的宏块内又划分出了多个子块。   

      

        这样再经过帧内压缩,可以得到更高效的数据。下图是分别使用mpeg-2和H264对上面宏块进行压缩后的结果。其中左半部分为MPEG-2子块划分后压缩的结果,右半部分为H264的子块划压缩后的结果,可以看出H264的划分方法更具优势。

 

 

        对于视频数据主要有两类数据冗余一类是时间上的数据冗余另一类是空间上的数据冗余。其中时间上的数据冗余是最大的。下面我们就先来说说视频数据时间上的冗余问题。假设摄像头每秒抓取30帧,这30帧的数据大部分情况下都是相关联的。也有可能不止30帧的的数据,可能几十帧,上百帧的数据都是关联特别密切的。

        对于这些关联特别密切的帧,其实我们只需要保存一帧的数据,其它帧都可以通过这一帧再按某种规则预测出来,所以说视频数据在时间上的冗余是最多的

为了达到相关帧通过预测的方法来压缩数据,就需要将视频帧进行分组。那么如何判定某些帧关系密切,可以划为一组呢?我们来看一下例子,下面是捕获的一组运动的台球的视频帧,台球从右上角滚到了左下角。

 H264编码器会按顺序,每次取出两幅相邻的帧进行宏块比较计算两帧的相似度。如下图:

 

通过宏块扫描与宏块搜索可以发现这两个帧的关联度是非常高的。进而发现这一组帧的关联度都是非常高的。因此,上面这几帧就可以划分为一组。其算法是:在相邻几幅图像画面中,一般有差别的像素只有10%以内的点,亮度差值变化不超过2%,而色度差值的变化只有1%以内,我们认为这样的图可以分到一组。

在这样一组帧中,经过编码后,我们只保留第一帧的完整数据,其它帧都通过参考上一帧计算出来。我们称第一帧为IDR/I帧,其它帧我们称为P/B帧,这样编码后的数据帧组我们称为GOP。

运动估计与补偿

        在H264编码器中将帧分组后,就要计算帧组内物体的运动矢量了。还以上面运动的台球视频帧为例,我们来看一下它是如何计算运动矢量的

        H264编码器首先按顺序从缓冲区头部取出两帧视频数据,然后进行宏块扫描。当发现其中一幅图片中有物体时,就在另一幅图的邻近位置(搜索窗口中)进行搜索。如果此时在另一幅图中找到该物体,那么就可以计算出物体的运动矢量了。下面这幅图就是搜索后的台球移动的位置。
 

 

        运动矢量计算出来后,将相同部分(也就是绿色部分)减去,就得到了补偿数据。我们最终只需要将补偿数据进行压缩保存,以后在解码时就可以恢复原图了。压缩补偿后的数据只需要记录很少的一点数据。如下所示:

        我们把运动矢量与补偿称为帧间压缩技术,它解决的是视频帧在时间上的数据冗余。除了帧间压缩,帧内也要进行数据压缩,帧内数据压缩解决的是空间上的数据冗余。下面我们就来介绍一下帧内压缩技术。

        人眼对图象都有一个识别度,对低频的亮度很敏感,对高频的亮度不太敏感。所以基于一些研究,可以将一幅图像中人眼不敏感的数据去除掉。这样就提出了帧内预测技术。

        H264的帧内压缩与JPEG很相似。一幅图像被划分好宏块后,对每个宏块可以进行 9 种模式的预测。找出与原图最接近的一种预测模式。

下面这幅图是对整幅图中的每个宏块进行预测的过程。

 

         然后,将原始图像与帧内预测后的图像相减得残差值再将我们之前得到的预测模式信息一起保存起来,这样我们就可以在解码时恢复原图了。效果如下:

  

经过帧内与帧间的压缩后,虽然数据有大幅减少,但还有优化的空间。     

对残差数据做DCT

        可以将残差数据做整数离散余弦变换去掉数据的相关性进一步压缩数据。如下图所示,左侧为原数据的宏块,右侧为计算出的残差数据的宏块。

将残差数据宏块数字化后如下图所示:

 

将残差数据宏块进行 DCT 转换。

 

 去掉相关联的数据后,我们可以看出数据被进一步压缩了。

 

上面的帧内压缩是属于有损压缩技术。也就是说图像被压缩后,无法完全复原。而CABAC属于无损压缩技术。 

编码处理

无损压缩技术大家最熟悉的可能就是哈夫曼编码了,给高频的词一个短码,给低频词一个长码从而达到数据压缩的目的。MPEG-2中使用的VLC就是这种算法,我们以 A-Z 作为例子,A属于高频数据,Z属于低频数据。看看它是如何做的。

CABAC也是给高频数据短码,给低频数据长码。同时还会根据上下文相关性进行压缩,这种方式又比VLC高效很多。其效果如下 

 H264分层结构:

        H264的主要目标是为了有高的视频压缩比和良好的网络亲和性,为了达成这两个目标,H264的解决方案是将系统框架分为两个层面,分别是视频编码层面(VCL)网络抽象层面(NAL),如图;

         H.264原始码流(裸流)是由一个接一个NALU组成,它的功能分为两层,VCL(视频编码层)和 NAL(网络抽象层).

        

  1. VCL:包括核心压缩引擎和块宏块和片的语法级别定义,设计目标是尽可能地独立于网络进行高效的编码;
  2. NAL:负责将VCL产生的比特字符串适配到各种各样的网络和多元环境中,覆盖了所有片级以上的语法级别。

        因为H264最终还是要在网络上进行传输,在传输的时候,网络包的最大传输单元是1500字节,一个H264的帧往往是大于1500字节的,所以需要将一个帧拆成多个包进行传输。这些拆包、组包等工作都在NAL层去处理。

H264码流结构

        在VCL进行数据传输或存储之前,这些编码的VCL数据,被映射或封装进NAL单元(NALU),H264码流是由一个个的NAL单元组成,其中SPS、PPS、IDR和SLICE是NAL单元某一类型的数据。

 

        一个NALU = 一组对应于视频编码的NALU头部信息 + 一个原始字节序列负荷(RBSP,Raw Byte Sequence Payload).

        如图所示,下图中的NALU的头 + RBSP 就相当于一个NALU(Nal Unit),每个单元都按独立的NALU传送。H.264的结构全部都是以NALU为主,理解了NALU,就理解了H.264的结构。
一个原始的H.264 NALU 单元常由 [StartCode] [NALU Header] [NALU Payload] 三部分组成,其中 Start Code 用于标示这是一个NALU 单元的开始,必须是”00 00 00 01” 或”00 00 01

         3字节的0x000001只有一种场合下使用,就是一个完整的帧被编为多个slice的时候,包含这些slice的nalu使用3字节起始码。其余场合都是4字节的。

        NAL单元的头部是由forbidden_bit(1bit),nal_reference_bit(2bits)(优先级),nal_unit_type(5bits)(类型)三个部分组成的。

NAL Header

NAL单元的头部是由forbidden_bit(1bit),nal_reference_bit(2bits)(优先级),nal_unit_type(5bits)(类型)三个部分组成的。

1、F(forbiden):禁止位,占用NAL头的第一个位,当禁止位值为1时表示语法错误;

2、NRI:参考级别,占用NAL头的第二到第三个位;值越大,该NAL越重要。

3、Type:Nal单元数据类型,也就是标识该NAL单元的数据类型是哪种,占用NAL头的第四到第8个位;

00 00 00 01 06:  SEI信息  

00 00 00 01 67:  0x67&0x1f = 0x07 :SPS

00 00 00 01 68:  0x68&0x1f = 0x08 :PPS

00 00 00 01 65:  0x65&0x1f = 0x05: IDR Slice 

         在具体介绍NAL数据类型前,有必要知道NAL分为VCL和非VCL的NAL单元。其中SPS、SEI、PPS等非VCL的NAL参数对解码和显示视频都是很有用的。

        而另外一个需要了解的概念就是参数集(Parameter sets),参数集是携带解码参数的NAL单元,参数集对于正确解码是非常重要的,在一个有损耗的传输场景中,传输过程中比特列或包可能丢失或损坏,在这种网络环境下,参数集可以通过高质量的服务来发送,比如向前纠错机制或优先级机制。Parameter sets与其之外的句法元素之间的关系如图9所示:
 

VCL的NAL数据类型

1)、 头信息块,包括宏块类型,量化参数,运动矢量。这些信息是最重要的,因为离开他们,被的数据块种的码元都无法使用。该数据分块称为A类数据分块。

2)、 帧内编码信息数据块,称为B类数据分块。它包含帧内编码宏块类型,帧内编码系数。对应的slice来说,B类数据分块的可用性依赖于A类数据分块。和帧间编码信息数据块不通的是,帧内编码信息能防止进一步的偏差,因此比帧间编码信息更重要。

3)、 帧间编码信息数据块,称为C类数据分块。它包含帧间编码宏块类型,帧间编码系数。它通常是slice种最大的一部分。帧间编码信息数据块是不重要的一部分。它所包含的信息并不提供编解码器之间的同步。C类数据分块的可用性也依赖于A类数据分块,但于B类数据分块无关。

以上三种数据块每种分割被单独的存放在一个NAL单元中,因此可以被单独传输。

 

SODBRBSP
SODB 数据比特串 -> 是编码后的原始数据。RBSP 原始字节序列载荷 -> 在原始编码数据的后面添加了 结尾比特。一个 bit“1”若干比特“0”,以便字节对齐。

(1)SODB ,String Of Data Bits 原始数据比特流

        因为它是流的形式,所以长度不一定是8倍数它是由 VLC 层产生的。由于我们计算机是以8倍数去处理数据所以计算机在处理H264时,就需要 RBSP。

(2)RBSP,SODB + tailing bits (原始字节序列载荷)

        由于它是一个压缩流,SODB 不知道是在何处结束,所以算法在SODB最后一位补一个1,没有按字节对齐的则补 0。

(3)EBSP (扩展字节序列载荷)

        在生成压缩流之后,在每一帧的开头加一个起始位,这个起始位一般是 00 00 00 01 或者是 00 00 01。所以在h264码流中规定每有两个连续的00 00,就增加一个0x03。
 

H264的NAL单元与片,宏之间的联系

        其实到这里可能就比较难理解了,为什么数据NAL单元中有这么多数据类型,这个SLICE又是什么东西,为什么不直接是编码后出来的原始字节序列载荷,所以我觉得在这里再讲述帧所细分的一些片和宏的概念应该是比较合适的,也是能够参照上下文更能理解这些概念的位置,又能给这些困惑做一个合理一点的解释,所以在此做一个描述:

           1帧(一幅图像) = 1~N个片(slice)  //也可以说1到多个片为一个片组

           1个片 = 1~N个宏块(Marcroblock)

           1个宏块 = 16X16的YUV数据(原始视频采集数据)
        

        从数据层次角度来说,一幅原始的图片可以算作广义上的一帧,帧包含片组和片,片组由片来组成,片由宏块来组成,每个宏块可以是4*4、8*8、16*16像素规模的大小,它们之间的联系如图10所示。每个片都是一个独立的编码单位。

        NAL单元除了容纳Slice编码的码流外还可以容纳其他数据这也就是为什么有SPS、PPS等这些数据出现的原因,并且这些数据在传输H264码流的过程中起到不可或缺的作用,具体作用上面也是有讲到的。

        序列>图像>片>宏>像素

同时有几点需要说明一下,这样能便于理解NAL单元:

(1)、如果不采用 FMO(灵活宏块排序) 机制,则一幅图像只有一个片组;

(2)、如果不使用多个片,则一个片组只有一个片;

(3)、如果不采用 DP(数据分割)机制,则一个片就是一个 NALU,一个 NALU 也就是一个片。

   否则,一个片的组成需要由 三个 NALU 组成,也就是上面说到的A、B、C类数据块。
 

 

     如我们所见,每个分片也包含着头和数据两部分分片头中包含着分片类型、分片中的宏块类型、分片帧的数量以及对应的帧的设置和参数等信息而分片数据中则是宏块,这里就是我们要找的存储像素数据的地方;宏块是视频信息的主要承载者,因为它包含着每一个像素的亮度和色度信息。视频解码最主要的工作则是提供高效的方式从码流中获得宏块中的像素阵列。宏块数据的组成如下图所示:

 

    从上图中,可以看到,宏块中包含了宏块类型、预测类型、Coded Block Pattern、Quantization Parameter、像素的亮度和色度数据集等等信息。

至此,我们对 H.264 的码流数据结构应该有了一个大致的了解。

Slice(片):

如图所示,NALU的主体中包含了Slice(片).

一个片 = Slice Header + Slice Data

        片是H.264提出的新概念,通过编码图片后切分通过高效的方式整合出来的概念。一张图片有一个或者多个片,而片由NALU装载并进行网络传输的。但是NALU不一定是切片,这是充分不必要条件,因为 NALU 还有可能装载着其他用作描述视频的信息.

        设置片的目的是为了限制误码的扩散和传输,应使编码片相互间是独立的。某片的预测不能以其他片中的宏块为参考图像,这样某一片中的预测误差才不会传播到其他片中。

        可以看到上图中,每个图像中,若干宏块(Macroblock)被排列成片。一个视频图像可编程一个或更多个片,每片包含整数个宏块 (MB),每片至少包含一个宏块。
片有一下五种类型:

意义

I 片

只包含I宏块

P 片

包含P和I宏块

B 片

包含B和I宏块

SP 片

包含P 和/或 I宏块,用于不同码流之间的切换

SI 片

一种特殊类型的编码宏块

        宏块(Macroblock):宏块是视频信息的主要承载者。一个编码图像通常划分为多个宏块组成.包含着每一个像素的亮度和色度信息。视频解码最主要的工作则是提供高效的方式从码流中获得宏块中像素阵列。

一个宏块 = 一个16*16的亮度像素 + 一个8×8Cb + 一个8×8Cr彩色像素块组成。(YCbCr 是属于 YUV 家族的一员,在YCbCr 中 Y 是指亮度分量,Cb 指蓝色色度分量,而 Cr 指红色色度分量)

宏块分类 

  • I 宏块:利用从当前片中已解码的像素作为参考进行帧内预测
  • P 宏块:利用前面已编码图像作为参考进行帧内预测,一个帧内编码的宏块可进一步作宏块的分割:即16×16.16×8.8×16.8×8亮度像素块。如果选了8×8的子宏块,则可再分成各种子宏块的分割,其尺寸为8×8,8×4,4×8,4×4
  • B 宏块:利用双向的参考图像(当前和未来的已编码图像帧)进行帧内预测
     

 

        句法元素的分层结构有助于更有效地节省码流。例如,再一个图像中,经常会在各个片之间有相同的数据,如果每个片都同时携带这些数据,势必会造成码流的浪费。更为有效的做法是将该图像的公共信息抽取出来,形成图像一级的句法元素,而在片级只携带该片自身独有的句法元素。

 

宏块分类

意义

mb_type:确定该 MB 是帧内或帧间(P 或 B)编码模式,确定该 MB 分割的尺寸

mb_pred:确定帧内预测模式(帧内宏块)确定表 0 或表 1 参考图 像,和每一宏块分割的差分编码的运动矢量(帧间宏块,除 8×8 宏块分割的帧内 MB)

sub_mb_pred:(只对 8×8MB 分割的帧内 MB)确定每一子宏块的子宏 块分割,每一宏块分割的表 0 和/或表 1 的参考图象;每一 宏块子分割的差分编码运动矢量。

coded_block_pattern:指出哪个 8×8 块(亮度和彩色)包 编码变换系数

mb_qp_delta:量化参数的改变值

residual:预测后对应于残差图象取样的编码变换系数
 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_44632658/article/details/126826334

智能推荐

android代码svn需要忽略的文件_svn需要屏蔽build.gradle文件吗-程序员宅基地

文章浏览阅读317次。一般需要忽略.idea文件夹、.gradle文件夹、所有的build文件夹、所有的.iml文件及local.properties文件,当然build.gradle、setting.gradle是不可以忽略的,我们忽略的这些文件夹都在项目编译过程中可以自动为我们生成的_svn需要屏蔽build.gradle文件吗

若依springcloud 前后端分离 集成 websocket_springcloud集成websocket-程序员宅基地

文章浏览阅读4.2k次,点赞5次,收藏24次。添加websocket 依赖 <!--websocket--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>网管配置服务转_springcloud集成websocket

成功解决SyntaxError: future feature annotations is not defined-程序员宅基地

文章浏览阅读1.5w次,点赞9次,收藏13次。​成功解决SyntaxError:futurefeatureannotationsisnotdefined目录解决问题解决思路解决方法解决问题SyntaxError:futurefeatureannotationsisnotdefined解决思路语法错误:没有定义futurefeature注释解决方法实际上是python版本不对,该语法需要在python3.7以上,而当前版本在python3.6所以导致此错误!T1、Anaconda下安装_syntaxerror: future feature annotations is not defined

js控制输入框禁止输入和允许输入_js 某个input框的enter 其他input禁止-程序员宅基地

文章浏览阅读8.5k次。初始,部分输入框禁止输入:$(document).ready(function(){ $("#fundCode").prop("disabled",true); $("#convertFundCode").prop("disabled",true); $("#allowtradeVol").prop("disabled",true); $("#appVol")._js 某个input框的enter 其他input禁止

哈夫曼树数据压缩c语言算法,特殊的树:哈夫曼树2-程序员宅基地

文章浏览阅读143次。1.哈夫曼树的查找算法查找算法根据构建哈夫曼树算法衍生而来,我们在构建二叉树时需要查找出哪些数据最小,以符合我们哈夫曼树的最优解情况。查找权重值最小的两个结点的思想是:从待处理数据的头部位置开始,首先找到两个无父结点的结点(说明还未使用其构建成树),然后和后续无父结点的结点依次做比较,有两种情况需要考虑:l 如果比两个结点中较小的那个还小,就保留这个结点,删除原来较大的结点;l 如果介于两个结..._数据压缩赫夫曼树c语言

微信小程序之网络数据请求 wx:request的简单使用_微信小程序 wx.request-程序员宅基地

文章浏览阅读5.1k次,点赞2次,收藏15次。我们可以在微信开发者工具中,临时开启「开发环境不校验请求域名、TLS 版本及 HTTPS 证书」选项,跳过 request 合法域名的校验。例如:请求黑马微信小程序课程的一个数据接口。出于安全性方面的考虑,小程序官方对。_微信小程序 wx.request

随便推点

ACM常用模板——数据结构——优先队列(堆)_acm优先队列模板-程序员宅基地

文章浏览阅读515次。数据结构——优先队列(堆)_acm优先队列模板

Android禁止安装三方应用(屏蔽所有安装应用的方式)_禁用手动安转-程序员宅基地

文章浏览阅读2.2w次,点赞5次,收藏48次。android系统安装应用有四种方式1.系统应用安装――开机时完成,没有安装界面2.网络下载应用安装――通过market应用完成,没有安装界面3.ADB工具安装――没有安装界面。4.第三方应用安装――通过现有的APK文件安装,有安装界面,由packageinstaller.apk应用处理安装及卸载过程的界面。1.禁止ADB和应用商店安装由“frameworks\base\services\core\java\com\android\server\pm\Packag..._禁用手动安转

CentOS 7输入startx无法启动图形化界面_centos startx-程序员宅基地

文章浏览阅读3.1w次,点赞19次,收藏48次。前两天在学习linux虚拟化的时候, 发现虚拟机磁盘空间不足, 由于当初分区的时候不是用lvm来分区的, 导致无法扩容, 所以只能新建了一台虚拟机来学习. 然而在新建完成后, 按照之前老师教的一系列优化手段, 将这台手段优化到我认为最优的条件下, 重启了一下系统, 发现登录界面自动回到了字符界面. 这可把我给郁闷坏了, 好端端的怎么就变成了字符界面了呢? 于是输..._centos startx

RoseHA集群:RHEL+RoseMirror+Oracle【2】-程序员宅基地

文章浏览阅读391次。博主正在参加“2011年度IT博客大赛”,欢迎帮顶! @投票地址@---------------------------------------------三.安装Rose Mirror HA:·准备工作: 在安装 Rose Mirror HA 前检查相应的软件包是否安装,如果没有安装通过系统安装盘进行安装。要正常的运行 ..._rose ha监控脚本

nox夜神模拟器连接不上android studio,用bat脚本快速输入命令_电脑使用夜神模拟器教程,bat文件-程序员宅基地

文章浏览阅读230次。用bat命令快速使android studio连接夜神模拟器_电脑使用夜神模拟器教程,bat文件

python字典keys函数_Python字典中几个常用函数总结-程序员宅基地

文章浏览阅读1.7k次,点赞2次,收藏3次。1、get() 返回指定键的值,如果值不在字典中返回default值。语法:dict.get(key,default=None)参数:key 字典中要查找的键。default 如果指定键的值不存在时,返回该默认值值。例:dict={'Name':'alex','Age':21}print("Name is:%s"% dict.get('Name')+"\n"+ "Age is:%d"% d..._keys函数