具体实施方式
本申请实施例中,在视频解码过程内,针对采用新型编码结构的熵解码结果所提出的视频解码方法包括:在对视频编码码流进行熵解码后,按照设定数据长度读取视频编码码流经熵解码后产生的数据,在每读取一次设定长度的数据后,根据读取的数据针对一个单位图像块的变换系数进行解码,其中,针对单位图像块进行变换系数解码包括:确定读取的设定长度的数据中每一个比特位的取值,作为标志位解码结果,并对该标志位解码结果进行保存;若根据所 述标志位解码结果确定本次读取的设定长度的数据中包含常数变换系数,则根据该标志位解码结果获得所述常数变换系数的解码值(以下称为常数level值);若根据所述标志位解码结果确定本次读取的设定长度的数据中包含逃逸escape数据变换系数,则在指定时机继续按照设定长度读取数据,并根据继续读取的数据获得所述escape数据变换系数的解码值(以下称为escape数据level值)。
基于上述方案,为了进一步提高视频解码流程的整体执行效率,较佳的,每获得一个常数level值或者escape数据level值,便通过反扫描操作确定其需要写入的寄存器地址,并将获得的一个常数level值或者escape数据level值写入相应的寄存器。
下面对非全零4x4 block为例,对本申请实施例中变换系数解码的流程进行概括性介绍。
假设某个非全零4x4 block的熵解码结果的数据结构如图1所示。实际应用中,熵解码结果内包含的变换系数通常分为两类,一类为常数变换系数,一类为escape数据变换系数。本申请实施例中,对熵解码结果进行变换系数解码时,先依次对4x4 block内的各个2x2 block包含的常数变换系数进行“区域性”解码,再依次对4x4 block内的各个2x2 block包含的escape数据变换系数进行“区域性”解码,对一个2x2 block每解码一次,都需要输入一轮16比特的数据。
本申请实施例中,视频解码装置会按照以下步骤对获得的熵解码结果进行变换系数解码:
(1)第一轮输入:
如图1所示,4x4图像单元被划分为L0~L6几个部分,第一轮输入总共输入16比特数据,用于解码level 0、level 1、level 2和level3(分别对应于图1中的L0、L1、L2和L3);该16比特数据用于传输level0~level3这四个数据的取值信息、符号位以及L4、L5、L6中是否存在下层2x2 block的信息。参阅表1所示,第一轮输入的16比特数据的各比特位的含义如下:
表1
15:14 |
13:12 |
11:10 |
9:8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|L0| |
|L1| |
|L2| |
|L3| |
not use |
L4 flag |
L5 flag |
L6 flag |
L0 sign |
L1 sign |
L2 sign |
L3 sign |
其中,如果|L0|>2或|L1|>1或|L2|>1或|L3|>1,则对应的level0、level1、level2、level3为escape型数据,需要由第五轮顺序输入的数据escape_data得到对应的level值,否则level值为常数,由|L0|、|L1|、|L2|、|L3|求得,该过程通过如下公式表示:
level0=(|L0|>2′b10)?escape_data:([3]?~|L0|:|L0|)
level1=(|L1|>2′b01)?escape_data:([2]?~|L1|:|L1|)
level2=(|L2|>2′b01)?escape_data:([1]?~|L2|:|L2|)
level3=(|L3|>2′b01)?escape_data:([0]?~|L3|:|L3|)
其中,符号“?”表示“是否判断”,符号“~”表示“负数”,符号“:”表示“否则”,“||”表示绝对值,2’b10表示两个比特的数据10,2’b01表示两个比特的数据01。
因此,上述公式的第一行可以解释为:判断是否|L0|>2,若是,则level0由第五轮输入的escape数据(称为escape_data)获得,否则,进一步判断第一轮输入数据的第3位(如表1所示,即是指L0的标志位L0 sign)是否为1,若是,则level0等于负的|L0|,否则,level0等于|L0|。
上述公式的第二、三、四行的解释方式同上,在此不再赘述。
(2)第二轮输入:
如果第一轮输入的16比特数据中第6位(如表1所示,即是指L4的标志位L4 flag)为1,则表示存在第二轮输入,第二轮输入的数据同样为16比特,用于解码level 4、level 5、level 6和level7(对应于图1中的L4,以及分别对应于图2中的L4_0、L4_1、L4_2和L4_3);如果第一轮输入的16比特数据中第6位不为1,则表示不存在第二轮输入,直接进入第三轮输入。参阅表2所示,第二轮输入的16比特数据的各比特位的含义如下:
表2
15:14 |
13:12 |
11:10 |
9:8 |
7:4 |
3 |
2 |
1 |
0 |
|L4_0| |
|L4_1| |
|L4_2| |
|L4_3| |
not use |
L4_0 sign |
L4_1 sign |
L4_2 sign |
L4_3 sign |
其中,如果|L4_0|>2或|L4_1|>1或|L4_2|>1或|L4_3|>1,则对应的level4、level5、level6、level7为escape型数据,需要由第五轮顺序输入的数据escape_data得到对应的level值,否则对应的level值为常数,由|L4_0|、|L4_1|、|L4_2|、|L4_3|求得,该过程通过如下公式表示:
level4=(|L4_0|>2′b10)?escape_data:([3]?~|L4_0|:|L4_0|)
level5=(|L4_1|>2′b01)?escape_data:([2]?~|L4_1|:|L4_1|)
level6=(|L4_2|>2′b01)?escape_data:([1]?~|L4_2|:|L4_2|)
level7=(|L4_3|>2′b01)?escape_data:([0]?~|L4_3|:|L4_3|)
(3)第三轮输入:
如果第一轮输入的16比特数据中第5位(如表1所示,即是指L5的标志位L5 flag)为1,则表示存在第三轮输入,第三轮输入的数据同样为16比特,用于解码level 8、level 9、1evel 10和1evel 11(对应于图1中的L5,以及分别对应于图3中的L5_0、L5_1、L5_2和L5_3);如果第一轮输入的16比特数据中第5位不为1,则表示不存在第三轮输入,直接进入第四轮输入。参阅表3所示,第三轮输入的16比特数据的各比特位的含义如下:
表3
15:14 |
13:12 |
11:10 |
9:8 |
7:4 |
3 |
2 |
1 |
0 |
|L5_0| |
|L5_1| |
|L5_2| |
|L5_3| |
not use |
L5_0 sign |
L5_1 sign |
L5_3 sign |
L5_3 sign |
其中,如果|L5_0|>2或|L5_1|>1或|L5_2|>1或|L5_3|>1,则对应的level8、level9、level10、level11为escape型数据,需要由第五轮输入的数据escape_data得到对应的level值,否则对应的level值为常数,由|L5_0|、|L5_1|、|L5_2|、|L5_3|求得,该过程通过如下公式表示:
level8=(|L5_0|>2′b10)?escape_data:([3]?~|L5_0|:|L5_0|)
level9=(|L5_1|>2′b01)?escape_data:([2]?~|L5_1|:|L5_1|)
level10=(|L5_2|>2′b01)?escape_data:([1]?~|L5_2|:|L5_2|)
level11=(|L5_3|>2′b01)?escape_data:([0]?~|L5_3|:|L5_3|)
(4)第四轮输入
如果第一轮输入的16比特数据中第4位(如表1所示,即是指L6的标志位L6 flag)为1,则表示存在第四轮输入,第四轮输入的数据同样为16比特,用于解码level 12、level 13、level 14和level 15(对应于图1中的L6,以及分别对应于图4中的L6_0、L6_1、L6_2和L6_3);如果第一轮输入的16比特数据中第4位不为1,则表示不存在第四轮输入,直接进入第五轮输入。参阅表4所示,第四轮输入的16比特数据的各比特位的含义如下:
表4
15:14 |
13:12 |
11:10 |
9:8 |
7:4 |
3 |
2 |
1 |
0 |
|L6_0| |
|L6_1| |
|L6_2| |
|L6_3| |
not use |
L6_0 sign |
L6_1 sign |
L6_2 sign |
L6_3 sign |
其中,如果|L6_0|>2或|L6_1|>1或|L6_2|>1或|L6_3|>1,则对应的level12、level13、level14、level15为escape型数据,需要由第五轮输入的数据escape_data得到对应的level值,否则对应的level值为常数,由|L6_0|、|L6_1|、|L6_2|、|L6_3|求得,该过程通过如下公式表示:
level12=(|L6_0|>2′b10)?escape_data:([3]?~|L6_0|:|L6_0|)
level13=(|L6_1|>2′b01)?escape data:([2]?~|L6_1|:|L6_1|)
level14=(|L6_2|>2′b01)?escape_data:([1]?~|L6_2|:|L6_2|)
level15=(|L6_3|>2′b01)?escape_data:([0]?~|L6_3|:|L6_3|)
(5)第五轮输入
如果在前四轮数据输入过程中经判断确定存在escape型数据level值,则第五轮开始顺序输入escape_data,并将输入的escape_data顺序填入前四轮输入过程中确定4x4 block内存在escape型数据level值的位置,以得到每一个escape型数据level值。如表5所示,输入escape_data时,每一次也读取16比特数据,但仅取其中的11比特作为相应的escape型数据level值的取值。
表5
这样,在前五轮输入数据结束后,便已解码得到了4x4block的图像块内包含的所有变换系数的取值,即level0~level15的取值;此时,对该图像块内包含的变换系数解码流程便已结束。
以上过程便是本申请实施例中提出的针对具有新型编码结构的熵解码结果进行变换系数解码的示意流程。在这个过程中,每解码得到一个变换系数的取值(包含常数level值和escape型数据level值),可以立即对其进行反扫描操作,使得变换系数解码过程中得到的顺序排列的16个level值(参阅图5A所示),在变换系数解码结束后,按照图5B所示的顺序重新排列,这样,便在得到变换系数解码结果的同时得到了反扫描结果。
下面结合附图对本申请优选的实施方式进行详细说明。
参阅图6所示,本申请设计了一种硬件电路结构,用于实现对上述4x4block熵解码结果进行16个变换系数的解码并同时完成变换系数的反扫描操作。
熵解码结果由总线输入,解码模块通过两个大小为32x64bit的乒乓操作存储器接收该数据,分别称为ram 0和ram 1。
首先总线将64比特的熵解码结果依次写入ram0,直至写满32个64比特数据单元;然后解码器开始读取ram 0中的数据用以进行变换系数解码,与此同时总线开始写ram 1,当解码器读空ram 0且总线写满ram 1后两者进行切换,解码器开始读取ram 1中的数据用以进行变换系数解码,总线再次写ram 0;以此反复操作,直至变换系数解码流程完毕,在此过程中,解码器和总线通过彼此之间的配合实现对两个存储器的读写乒乓操作。
将从ram 0或ram 1每次读到的64比特数据拆分为四个16比特的数据依次作为解码器的输入数据(也称为解码器读出的数据),当获得一个有效的16比特数据时(以下将此类16比特输入数据称为input_data,置标志位data_valid等于1,表示获得一个有效的输入数据。
参阅图7所示,解码器将读出的数据传输至控制装置进行后续处理,本实施例中,控制装置执行的后续处理包括变换系数解码及反扫描两个部分,如图 7B所示,控制装置包括读取单元10和解码单元,其中解码单元用于在读取单元10每读取一次设定长度的数据后,根据读取的数据针对一个单位图像块(本实施例中,单位图像块为2×2block图像块)的变换系数进行解码,解码单元包括标志位解码单元11、存储单元12、第一处理单元13和第二处理单元14,下面对各功能进行详细介绍:
读取单元10,用于按照设定长度读取数据;
标志位解码单元11,用于对读取的设定长度的数据进行标志位解码,确定所述设定长度的数据中每一个比特位的取值,以获得标志位解码结果;
存储单元12,用于保存所述标志位解码结果;
第一处理单元13,用于根据所述标志位解码结果确定本次读取的设定长度的数据中包含常数变换系数level值时,根据该标志位解码结果计算出所述常数level值;
第二处理单元14,用于根据所述标志位解码结果确定本次读取的设定长度的数据中包含逃逸escape数据level值时,在指定时机指示读取单元10继续按照设定长度读取数据,并根据继续读取的数据获得所述escape数据level值。
如图7所示,控制装置中还包括一个反扫描单元15,用于在第一处理单元13每获得一个常数level值或者第二处理单元14每获得一个escape数据level值时,通过反扫描操作确定其需要写入的寄存器地址,并将获得的一个常数level值或者escape数据level值写入相应的寄存器。
本申请实施中,反扫描单元15中进行一步设置一个控制逻辑单元16,用于控制写使能writelevel_e,在解码步骤中,每当writelevel_e等于1时表示解码了一个变换系数,此时使用writelevel_e作为level寄存器组的写使能,在写使能writelevel_e有效时将计算得到的解码数据level值寄存到level0~level15寄存器组中(一个4x4block共有16个变换系数,分别称为level0~level15)。具体寄存到level0~level15中的哪一个由反扫描单元15计算得到的写地址level_ad决定,也即是说level_ad等于0~15时分别表示将level值写入 level0~level15。控制装置将解码流程执行完毕时,最终解码得到了16个变换系数level0~level15,若同时完成了变换系数的反扫描操作,则level0~level15寄存器中的存储的变换系数值,即是变换系数解码及反扫描操作后的最终结果。
下面以具体实施例对控制装置的工作流程进行详细说明。参阅图8所示,控制装置对解码器读出的数据(即熵解码结果经解码器读出的数据)进行变换系数解码以及反扫描操作的详细流程如下:
步骤800:将寄存器组level0~level15的存储值全部重置为全0
步骤801:判断cbp标志位的取值,若cbp=0,则执行步骤802;若cbp=1,则确定4×4block解码流程结束。
本申请实施例中,cbp是单词coded block pattern的首字母缩写,它是视频编码码流中的一个语法元素,可以在熵解码过程中直接从视频编码码流中的对应位置获取。cbp值用于表示每个图像块(例如,4x4 block图像块)是否为全零变换系数块,当cbp=1时,则表示此图像块内的所有变换系数的取值均为零,无需进行变换系数解码;当cbp=0时,则表示此图像块内存在非零的变换系数取值,需要进行变换系数解码。
步骤802:读取一个16比特的数据,并对其进行标志位解码,所谓标志位解码,即是记录下读取的16比特数据中每一比特位的具体取值以备后续操作。
本申请实施例中,仍以表1所示的16比特数据为例进行介绍。
表1
15:14 |
13:12 |
11:10 |
9:8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|L0| |
|L1| |
|L2| |
|L3| |
not use |
L4 flag |
L5 flag |
L6 flag |
L0 sign |
L1 sign |
L2 sign |
L3 sign |
其中,将无需第五轮传输即可解码得到的level值统称为“常数”,即由|L0|、|L1|、|L2|和|L3|计算即可得到的level值统称为常数。
在步骤802中,读取一个16比特输入数据时,当确定这个16比特数据的data_valid=1时,再执行后续操作。
步骤803:根据标志位解码的结果判断是否存在常数状态的变换系数取值,常数level值,若是,则进行步骤804;否则,进行步骤807。.
步骤804:根据步骤802中获得的标志位解码结果,计算出一个常数level值。
步骤805:通过反扫描操作确定计算出的常数level值需要写入的寄存器地址,并将该常数level值写入相应的寄存器。
在步骤805中,在写入常数level值之前,需要将写level标志位(即写使能)writelevel_e置为1。
步骤806:判断本次执行步骤802时获得的标志位解码结果包含的常数level值是否均已解码完毕,若是,则进行步骤807;否则,返回步骤804。
步骤807:判断第一次执行步骤802时获得的标志位解码结果指示的标志位解码流程执行总次数是否达到,若是则进行步骤808;否则,返回步骤802。
本申请实施例中,所谓标志位解码流程执行总次数即是指步骤802的执行总次数。
步骤808:判断是否存在escape数据状态的变换系数取值(即判断是否存在escape数据level值),若是,则执行步骤809,否则,结束4x4block变换系数解码流程。
本实施例中,将表5所示第五轮传输的数据统称为“escape数据”。
步骤809:继续读取16比特的数据,并在读取的16比特数据中选择11比特数据作为当前获得的escape数据level值,即level x=input_data[10:0],x∈[0,15]
在步骤809中,读取一个16比特输入数据时,当确定这个16比特数据的data_valid=1时,再执行后续操作。
步骤810:通过反扫描操作确定当前获得的escape数据level值写入的寄存器地址,并将该escape数据level值写入确定的寄存器。
在步骤810中,在写入escape数据level值之前,需要将写level标志位(即 写使能)writelevel_e置为1。
步骤811:判断是否所有的escape数据level值均已解码完毕,若是,则确定4×4block解码流程结束;否则返回步骤809。
上述步骤800-步骤810是本实施例中对熵解码结果进行变换系数解码以及反扫描操作的详细流程介绍,下面对其中各步骤的具体实现方式进行详细说明。
针对步骤802,需要定义一个用于记录步骤802执行次数的计数器1,称为desp_co,初始值为0,每执行一次步骤802,便将desp_co的计数值累加1,直至进入输入escape型数据(即步骤808)的步骤后才将其清零。同时,需要定义一个预测步骤802执行总次数的计数器2,称为desp_no,当desp_co等于0,且读取到一个有效的16比特数据时,desp_no被赋值为desp_no_c,其中desp_no_c=input_data[6]+input_data[5]+input_data[4]+1′b1;input_data[6]表示16位输入数据中第6位数据的取值,input_data[5]表示16位输入数据中第5位数据的取值,input_data[4]表示16位输入数据中第4位数据的取值,1′b1表示存在1比特数据,数值为“1”,由此可见,desp_no_c的初始值最小为1。
本申请实施例中,针对每一轮输入的16比特数据,将需要解码的escape数据的个数标志参数定义为level_no_c,level_no_c=level0_escape+level1_escape+level2_escape+level3_escape;其中,如果input_data[15:14]两个比特位都为1,则level 0_escape等于1,否则level0_escape等于0、level1_escape=input_data[13]、level2_escape=input_data[11]、level3_escape=input_data[9];例如input_data[15:8]=8’b11110010,则level 0_escape=1、level1_escape=1、level2_escape=0、level3_escape=1。;另一方面,针对每一轮输入的16比特数据,将需要解码的常数level值的个数标志参数定义为const_no,当取得一个16比特数据时,const_no被赋值为const_no_c,其中const_no_c=4-level_no_c。
基于上述定义的参数,经过步骤802的标志位解码后,在步骤803中,若 根据标志位解码的结果确定const_no_c>0,则表示此轮输入的16比特数据中存在常数level值。同理,若level_no_c>0,则表示此轮输入的16比特数据中存在escape数据level值。
在步骤804中,对输入的16比特数据中包含的常数level值进行解码时,采用以下方式:
定义输入的16比特数据包含的变换系数的符号位为level_sign,当取得一个16比特数据时,level_sign被赋值为input_data[3:0],
定义变换系数中,常数level值的标志参数为level_noescape,当取得一个16比特数据时,level_noescape被赋值为input_data[15:8];
表1
15:14 |
13:12 |
11:10 |
9:8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|L0| |
|L1| |
|L2| |
|L3| |
not use |
L4 flag |
L5 flag |
L6 flag |
L0 sign |
L1 sign |
L2 sign |
L3 sign |
以表1中所表示的16比特输入数据为例,L0 sign、L1 sign、L2 sign和L3sign便是此轮输入数据中变换系数的符号位level_sign,|L0|、|L1|、|L2|和|L3|便是常数level值的标志参数level_noescape。
此外,定义此轮输入的16比特数据中,常数level值所处位置的标志位为constscan,当取得一个16比特数据时,constscan被赋初值为{~level3_escape,~level2_escape,~level1_escape,~level0_escape},
接着,要根据当前常数level值所处位置constlocal_c来修正constscan的取值,其中constlocal_c用于表示当前处理的哪个level值为常数,具体方式如下:
如果constscan[0]等于1,则定义constlocal_c=0,当constlocal_c=0时,表示输入的16比特数据(即2x2block)中的第1个level值为常数,例如,表1所示输入数据中level 0为常数;那么,修正constscan={constscan[3:1],~constscan[0]};此修正值作为下一次对constscan判断时使用,并且判断level_sign[3]的取值是否为1′b0,若是,则level x={{9{1′b0}},level_noescape[7:6]};否则level x={9′b111111111,~level_noescape[7:6]+1};其中,level x为当前计算的level值,
如果constscan[1]等于1,则定义constlocal_c=1,当constlocal_c=1时,表示输入的16比特数据(即2x2block)中的第2个level值为常数,例如,表1所示输入数据中level 1为常数,那么,修正constscan={constscan[3:2],~constscan[1],constscan[0]};并判断level_sign[2]的取值是否为l′b0,若是,则level x={{9{1′b0}},level_noescape[5:4]},否则,level x={9′b111111111,~level_noescape[5:4]+1}。
如果constscan[2]等于1,则定义constlocal_c=2,当constlocal_c等于2时,表示输入的16比特数据(即2x2block)中的第3个level值为常数,例如,表1所示输入数据中level 2为常数,那么,修正constscan={constscan[3],~constscan[2],constscan[1:0]};并判断level_sign[1]的取值是否为1′b0,若是,则level x={{9{1′b0}},level_noescape[3:2]};否则,level x={9′b111111111,~level_noescape[3:2]+1}。
如果constscan[3]等于1,则定义constlocal_c=3,当constlocal_c等于3时,表示输入的16比特数据(即2x2block)中的第4个level值为常数,例如,表1所示输入数据中level 3为常数,那么,修正constscan={~constscan[3],constscan[2:0]};并判断level_sign[0]的取值是否为1′b0,若是,则level x={9′b000000000,level_noescape[1:0]};否则,level x={9′b111111111,~level_noescape[1:0]+1}。
针对步骤805,需要定义一个用于记录步骤805执行次数的计数器3,称为const_co,初始值为0,每执行一次步骤805便将const_co的计数值累加1,直至const_co等于const_no-1(即本轮输入的16比特数据中,需要解码的常数level值的个数),才将const_co的计数值清零。
另一方面,在步骤804中每获得一个常数level值,便需要在步骤805中,计算出获得的常数level值需要写入的寄存器地址,以下称为level_ad,对于不 同位置的常数level值,计算其level_ad的方式如下:
level_ad为经过反扫描操作之后获得的常数level值的写地址,本申请实施例中,将反扫描操作之前获得的常数level值的写地址称为level_ad tmp,level_ad tmp由基地址和偏移量两部分组成,其中,
基地址为常数level值所位于的2x2block的地址,称为level_baseadd(采用二进制数表示)。例如,参阅图9所示,在4x4block中,每个2x2block具有一个基地址,如,part 0的基地址level_baseadd=2’b00,part 1的基地址level_baseadd=2’b01,part 2的基地址level_baseadd=2’bl0,part 3的基地址level_baseadd=2’b11。
而偏移量为常数level值在每个2x2block中所位于的具体的1x1block的地址,称为level_offset,例如,参阅图5所示,以part 3为例,part 3中第1个1x1block的地址level_offset=2’b00,第2个1x1block的地址level_offset=2’b01,第3个1x1block的地址level_offset=2’b10,第4个1x1block的地址level_offset=2’b11,
将基地址与偏移量相拼接,便可以得到常数level值在反扫描操作之前的写地址,即level_ad tmp={level_baseadd,level_offset},其具体实现过程如下:
定义用于表示part1~part3子块中常数level值是否存在的标志参数为despscan,
若desp_co=0(即第1次执行步骤802),则在读取一个16比特数据时,将despscan赋初值为{input_data[4],input_data[5],input_data[6]},despscan的取值在进入步骤808时清零。
若desp_co=1,(即已经执行一次步骤802),则表示正在处理第1个2x2block(part0)中的常数level值,那么,level_baseadd=2′b00;
若desp_co=2,(即已经执行两次步骤802),则表示正在处理第二个2x2block(part1或part2或part3)中的常数level值,此时,如果despscan[0]=1,则表示当前处理的2x2block为part1,那么level_baseadd=2′b01;如果 despscan[0]≠1,despscan[1]=1,则表示当前处理的2x2block为part2,那么,level_baseadd=2′b10;如果despscan[0]≠1,despscan[1]≠1,则表示表示当前处理的2x2block为part3,那么,level_baseadd=2′b11;
若desp_co=3,(即已经执行三次步骤802),则表示正在处理第三个2x2block(part2或part3)的常数level值,此时,如果despscan[1:0]=2′b11,则表示当前处理的2x2block为part2,那么level_baseadd=2′b10;如果despscan[1:0]≠2′b11,则表示当前处理的2x2block为part3,那么,level_baseadd=2′b11;
若desp_co重新累加为0,(即已经执行四次步骤802),则表示写第四个2x2block中的常数值,则表示当前处理的2x2block为part3,那么,level_baseadd=2′b11;
而偏移量level_offset即为常数level值所处位置标志位constlocal_c,即level_offset=constlocal_c。
通过上述方式便可以得到常数level值反扫描前地址level_ad tmp={level_baseadd,level_offset}
接着,采用以下方式对level_ad tmp进行反扫描操作,即可以得到常数level值经过反扫描操作之后的写地址level_ad:
判断反扫描前地址level_ad_tmp的取值是否为9或12,若是,则采用公式level_ad={level_baseadd[1],level_offset[0],level_baseadd[0],level_offset[1]}计算其level_ad;否则,采用公式level_ad={level_baseadd[1],level_offset[1],level_baseadd[0],level_offset[0]}计算其level_ad,其结果如表6所示:
表6
反扫描前地址 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
反扫描后地址 |
0 |
1 |
4 |
5 |
2 |
3 |
6 |
7 |
8 |
12 |
9 |
13 |
10 |
11 |
14 |
15 |
获得level_ad后,直接将解码得到的常数level值,写入获得的level_ad对应的寄存器中,这样就在变换系数解码的同时得到了反扫描结果,至此,步 骤805执行完毕。
在步骤805中,每将一个常数level值写入对应的寄存器,便需要执行步骤806来判断对本轮输入的16比特数据中是否还存在需要解码的常数level值,若是,则重复步骤804和步骤805对下一个常数level值进行变换系数解码以及反扫描操作,否则,表示本轮输入的16比特数据已处理完毕。
本申请实施例中,根据const_co的取值来判断本轮输入的16比特数据中是否还存在需要解码的常数level值,具体方式为:判断是否满足const_co=const_no-1?若是,则表示此轮输入的16比特数据中已不存在常数level值,继续执行步骤807;否则,表示此轮输入的16比特数据中仍存在常数level值,需要返回执行步骤804。
基于步骤806,在执行步骤807时,本实施例根据desp_co的取值来判断第一次执行步骤802时获得的标志位解码结果指示的标志位解码流程执行总次数是否达到,具体方式为:
判断是否满足desp_co=desp_no-1,若是,则第一次执行步骤802时获得的标志位解码结果指示的标志位解码流程执行总次数已达到,同时也说明所有的常数level值均已解码完毕,那么,继续执行步骤808;否则,返回步骤802继续读取下一轮16比特的数据进行常数level值解码。
基于步骤807,在常数level值全部解码完毕后,在步骤808中,要进一步判断是否存在escape数据状态的变换系数取值(即判断是否存在escape数据)具体方式为:
判断level_sum的取值是否为0?若是,则表示4x4block的解码流程结束,否则,表示存在escape数据level值,需要继续执行步骤809。其中,其中level_sum表示4x4block中存在escape数据level值的总个数,其具体计算方式如下:
仍以图9所示的4x4block为例,将其划分为四个2x2子块,分别称为part0、part1、part2、part3。
定义part0、part1、part2、part3中escape数据所处位置的标志参数分别为part0_level_scan、part1_level_scan、part2_level_scan、part3_level_scan,其求取方法如下:
在第一次进入802步骤时,即在desp_co=0状态下读取一个16比特数据时,part0_level_scan={level3_escape,level2_escape,level1_escape,level0_escape};此时,input_data[6]等于0,则part1_level_scan=4′b0000;input_data[5]等于0,则part2_level_scan=4′b0000;input_data[4]等于0,则part3_level_scan=4′b0000。
基于上述第一次进行步骤802,在第二次进入步骤802时,(已在之前第一次进入步骤802时得到part0_level_scan),在desp_co=1状态下读取一个16比特数据,并进行如下判断:
如果despscan[0]=1,则表示第二轮输入的数据是part1内的数据,那么,part1_level_scan={level3_escape’,level2_escape’,level1_escape’,level0_escape’};
如果despscan[0]≠1,despscan[1]=1,则表示第二轮输入的数据是part2内的数据,那么part2_level_scan={level3_escape’,level2_escape’,level1_escape’,level0_escape’};
如果despscan[0]≠1,despscan[1]≠1,despscan[2]=1,则表示第二轮输入的数据是part3内的数据,那么,part3_level_scan={level3_escape’,level2_escape’,level1_escape’,level0_escape’};
基于上述两次进行802步骤,在第三次进入步骤802时(已在第一次进入步骤802时得到part0_level_scan;已在第二次进入步骤802时得到part1_level_scan或者part2_level_scan);在desp_co=2状态下读取一个16比特数据,进行如下判断:
如果despscan[2]=1,则说明第三轮输入的是part2内的数据,那么part2_level_scan={level3_escape”,level2_escape”,level1_escape”,level0_escape”};
如果despscan[2]≠1despscan[3]=1,则说明第三轮输入的是par3内的数据,那么,part3_level_scan={level3_escape”,level2_escape”,level1_escape”,level0_escape”};
基于上述三次进行步骤802,在第四次进入步骤802时(已在第一次进入步骤802时得到part0_level_scan;已在第二次进入步骤802时得到part1_level_scan;已在第三次进入步骤802时得到part2_level_scan),在desp_co=3的状态下读取一个16比特数据,并计算获得:part3_level_scan={level3_escape”,level2_escape”,level1_escape”’,level0_escape”’};
如图9所示,针对part0、part1、part2和part3,定义如下参数:
定义四个2x2block中存在escape数据的个数分别为part0_level_no、part1_level_no、part2_level_no、part3_level_no,
定义前两个2x2block中存在escape数据的个数总和为level_sum_2part,level_sum_2part=part0_level_no+part1_level_no;
定义前三个2x2block中存在escape数据的个数总和为level_sum_3part,level_sum_3part=level_sum_2part+part2_level_no;
定义四个2x2block中存在escape数据的个数总和为level_sum,level_sum=level_sum_3part+part3_level_no;
其中,
part0_level_no=part0_level_scan[0]+part0_level_scan[1]+part0_level_scan[2]+part0_level_scan[3]
part1_level_no=part1_level_scan[0]+part1_level_scan[1]+part1_level_scan[2]+part1_level_scan[3]
part2_level_no=part2_level_scan[0]+part2_level_scan[1]+part2_level_scan[2]+part2_level_scan[3]
part3_level_no=part3_level_scan[0]+part3_level_scan[1]+part3_level_scan[2]+part3_level_scan[3]
这样,在步骤808中便可以获得4x4block中存在的escape数据level值的 个数level_sum,从而确定是否需要输入escape数据。
基于步骤808,在确定需要输入escape数据时,在步骤809中,继续读取16比特数据,并执行level x=input_data[10:0]从这16比特数据中截取前11比特数据作为当前获得的escape数据level值。
同时,针对步骤809,需要定义一个用于统计步骤809执行次数的计数器4,称为数据level_co,初始值为0,每执行一次步骤809,便将level_co的计数值累加1,直至level_co=level_sum-1时,才将level_co清零。
基于步骤809,在获得一个escape数据level值后,需要在步骤810中通过反扫描操作计算出该escape数据level值需要写入的寄存器地址,同样,将反扫描后的写地址称为level_ad。
与计算常数level值的写地址level_ad的方式相同,计算escape数据level值的level_ad时,同时需要先计算出反扫描前的写地址level_ad_tmp,level_ad_tmp={level_baseadd,level_offset},计算level_ad_tmp时包括:
首先,计算基地址level_baseadd:
若level_co<part0_level_no,表示已经解码的escape数据level值的个数小于part0中的escape数据数目的总和,这说明正在解码part0中的数据,则level_baseadd=2′b00;
若part0_level_no≤level_co<level_sum_2part,表示已经解码的escape数据level值的个数大于part0中escape数据数目的总和,但小于part0和part1中escape数据数目的总和,这说明正在解码part1中的数据,则level_baseadd=2′b01;
若part1_sum_2part≤level_co<level_sum_3part,表示已经解码的escape数据level值的个数大于part0和part1中escape数据数目的总和,但小于part0、part1及part2中的escape数据数年的总和,这说明正在解码part2中的数据,则,level_baseadd=2′b10;
若level_sum_3part≤level_co<level_sum,则表示已经解码的escape数据 level值的个数大于part0、part1、part2中escape数据数目的总和,但小于part0、part1、part2、part3中的escape数据数目的总和,这说明正在解码part3中的数据,则level_baseadd=2′b11。
接着,再计算偏移量level_offset:
定义一个用于记录当前2x2block中已解码的escape数据level值的数目的计数器5,称为为part_level_co,
level_co<part0_level_no时,part_level_co=level_co[1:0];
part0_level_no≤level_co<level_sum_2part时,part_level_co=level_co-part0_level_no;
part1_sum_2part≤level_co<level_sum_3part时,part_level_co=level_co-level_sum_2part;
level_sum_3part≤level_co<level_sum时,则part_level_co=level_co-level_sum_3part;
定义当前2x2block中escape数据level值所处位置的标志参数为part_level_scan,
level_co<part0_level_no时,part_level_scan=part0_level_scan;
part0_level_no≤level_co<level_sum_2part时,则part_level_scan=part1_level_scan;
part1_sum_2part≤level_co<level_sum_3part时,part_level_scan=part2_level_scan;
level_sum_3part≤level_co<level_sum时,part_level_scan=part3_level_scan;
基于上述参数定义,level_offset的求取方式如下:
1、若part_level_co=0,表示正解码当前2x2block中的第1个escape数据level值,此时,
如果part_level_scan[0]=1,则表示2x2block中的第1个数为此轮输入的16比特数据针对的escape数据level值,那么,level_offset=2′b00;
如果part_level_scan[0]≠1,part_level_scan[1]=1,则表示2x2block中的第2个数为此轮输入的16比特数据针对的escape数据level值,那么,level_offset=2′b01;
如果part_level_scan[0]≠1,part_level_scan[1]≠1,part_level_scan[2]=1,则表示2x2block中的第3个数为此轮输入的16比特数据针对的escape数据level值,则level_offset=2′b10;
如果part_level_scan[0]≠1,part_level_scan[1]≠1,part_level_scan[2]≠1,则表示2x2block中的第4个数为此轮输入的16比特数据针对的escape数据level值,那么,level_offset=2′b11;
2、若part_level_co=1,表示正解码当前2x2block中的第2个escape数据level值,此时,
如果part_level_scan[1:0]=2′b11,则表示2x2block中的第2个数为此轮输入的16比特数据针对的escape数据level值,那么,则level_offset=2′b01;
如果part_level_scan[2:0]=3′b110或part_level_scan[2:0]=3′b101,则表示2x2block中的第3个数为此轮输入的16比特数据针对的escape数据level值那么,level_offset=2′b10;
如果上述两种条件均未满足,则表示2x2block中的第4个数为此轮输入的16比特数据针对的escape数据level值,那么,level_offset=2′b11;
3、若part_level_co=2,表示正解码当前2x2block中的第3个escape数据level值,此时,
如果part_level_scan[2:0]=3′b111,则表示2x2block中的第3个数为此轮输入的16比特数据针对的escape数据level值,那么,level_offset=2′b10;
若不满足上述条件,则表示2x2block中的第4个数为此轮输入的16比特数据针对的escape数据level值,那么,level_offset=2′b11;
4、、若part_level_co=4,表示正解码当前2x2block中的第4个escape数据level值,那么,level_offset=2′b11。
至此,便可计算出当前解码获得的escape数据level值的反扫描前地址level_ad_tmp={level_baseadd,level_offset}
接着,采用以下方式对level_ad tmp进行反扫描操作,即可以得到escape数据level值经过反扫描操作之后的写地址level_ad:
判断反扫描前地址level_ad_tmp的取值是否为9或12,若是,则采用公式level_ad={level_baseadd[1],level_offset[0],level_baseadd[0],level_offset[1]}计算其level_ad;否则,采用公式level_ad={level_baseadd[1],level_offset[1],level_baseadd[0],level_offset[0]}计算其level_ad,其结果如表6所示:
表6
反扫描前地址 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
反扫描后地址 |
0 |
1 |
4 |
5 |
2 |
3 |
6 |
7 |
8 |
12 |
9 |
13 |
10 |
11 |
14 |
15 |
获得level_ad后,直接将解码得到的escape level值,写入获得的level_ad对应的寄存器中,这样就在变换系数解码的同时得到了反扫描结果,至此,步骤810执行完毕。
基于步骤810,在步骤811中,进一步判断是否已将熵解码结果中包含的所有escape数据level值解码及反扫描处理完毕,若是,则表示4x4block解码已全部完成,即针对熵解码结果的变换系数解码以及反扫描操作已全部完成,否则,返回步骤809,继续读取下一个16比特的数据,以解码下一个escape数据level值。本申请实施例中,判断熵解码结果中包含的所有escape数据level值是否解码完毕的实现方式为:判断是否level_co=level_sum-1?若是,则表示所有escape数据level值均已解码写完,否则,表示需返回步骤809,继续下一轮解码操作。
综上所述,采用本申请实施例记载的技术方案,可以适应新型的熵解码结果编码结构,从而使视频解码技术得到了进一步的发展,另一方面,每一次读取的设定长度的数据内每个比特位的具体含义可以根据应用环境而进行相应调整,只需在后续流程中对具体标志位的含义记录进行适应性调整即可,整体 流程并不需要进行大规模调整,从而减少了后期维护的工作量,节省了维护成本。进一步地,可以将反扫描操作融合于变换系数解码过程中完成,这有效增加了变换系数解码的灵活性,同时也提高了整体视频解码流程的执行效率。
显然,本领域的技术人员可以对本申请中的实施例进行各种改动和变型而不脱离本申请的精神和范围。这样,倘若本申请实施例中的这些修改和变型属于本申请权利要求及其等同技术的范围之内,则本申请中的实施例也意图包含这些改动和变型在内。