xavs中子像素差值汇编实现的坑

编码器功能实现之后,一般都需要进行效率优化。其他手段用完之后,最终避免不了还需要汇编优化。
用oprofile或者vtune等工具进行分析,把耗时大头揪出来改写汇编,收益比较大。

下面记录的是xavs汇编改写过程中,子像素差值部分改写汇编遇到的问题。
将mc_luma调用的pixel_avg用汇编代码实现。(十几年前还是MMX、SSE指令集)
其中有两种情况:
(1)idx为1,3,4,12和5,7,13,15这两种情况每次处理8组数据,这些情况最大值为255552=0x31CE不会有溢出问题;
(2)idx为9,11,6,14每次处理4组数据,这些情况中会出现的最大值为255
965+25542*5=0x 2AF4E乘法器或加法器肯定会溢出。

针对第二种情况一开始使用一种近似计算方法,原来是先乘96求和之后加512右移10位,现在为先右移3位再乘96求和,最后再加64右移7位。
汇编改写过程中发现,如果有近似计算(先移位再计算)就会损失一些精度,因此分析可见在计算1/4像素插值的过程中,先得到1/2像素,在这个过程中已经经过了移位操作,然后再用这些精度损失过的数据去计算1/4像素,精度进一步损失,就会造成与C代码复杂计算得到的结果有偏差,随着GOP的增长误差积累,偏差会变大,会有马赛克和噪点,导致主观质量下降。
而C代码复杂计算是完全利用整像素点带入1/2滤波公式和1/4滤波公式得到的,只有最后一次移位,虽然也会有精度损失,但只有一次,对主观质量的影响不明显。
因此对这四个点的计算过程进行重新规划,1/4像素差值全部用整像素值来计算,不使用已经有精度损失的1/2像素值。同时避免乘法器和加法器的溢出,乘法器保持在字以内,并使用双字的加法器,这样改写之后,9.11两点的计算就可以使用汇编来实现了;但6.14两点,虽然乘法器和加法器不再溢出,但减法器发生了溢出,即出现了负数的情况,而且乘法器和加法器的位宽不同,导致中间结果无法顺利过渡,因此此两点仍采用C语言实现。

随着后续更高效的指令集的出现,有更多更宽的寄存器,这些问题也就迎刃而解了。

虽然子像素差值的汇编不再费劲了,但随着更复杂的计算的出现,仍然存在着寄存器不够用的情况。这些古老的数据搬移问题和寄存器利用的问题依然存在,下笔之前理清这些思路仍然非常重要。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值