在视频处理中,常会遇到颜色空间的转换(高清和标清下的转换公式不同),下面是使用SIMD指令对RGBA颜色转换至YUYV颜色的汇编优化
假设转换公式如下:
Y = Yr * R + Yg * G + Yb * B
U = Ur * R + Ug * G + Ub * B
V = Vr * R + Vg * G + Vb * B
转换后,这里选择直接丢弃第二个像素的U和V,这里暂不考虑A通道的存储
为了考虑性能,通常会将浮点系数放大成短整型系数,经放大后最后的结果需进行0.5的补偿(同样进行放大)
下面对使用pmulhw和pmaddwd两条指令分别进行分析
从公式中可以看到,对于Y、U、V三个通道,分别需要进行3次乘法和4次加法(包括1次补偿)
于是每4个RGBA像素能得到2个YUYV,共需要进行24次乘法,按照XMM寄存器128位计算,至少需要3条pmulhw指令或者4条pmaddwd指令
分别考虑计算流程,首先是pmulhw
(1)读取内存(movdqu,movdqa,lddqu)
(2)通道数据重排(pshuflw,pshufhw,pshufd,shufps,shufpd)
(3)使用pmulhw
(3)相关通道相加,计算Y、U、V,并加上补偿,缩小(系统被放大,这里需要缩小)(paddw,paddsw,psrlw,packuswb)
然后是pmaddwd
(1)读取内存(movdqu,movdqa,lddqu)
(2)使用pmaddwd
(3)水平相加,缩小(phaddd,psrad,packssdw,packuswb)
考虑整个过程可以看到,虽然使用pmaddwd指令会多一条(pmaddwd和pmulhw的延迟和吞吐量相同),但是考虑数据混排,使用pmaddwd性能更高,并且可将0.5的补偿系统放进A通道,这样乘加一次计算完毕,编译后的代码也更少
注意:
(1)SSE2:使用完pmaddwd后,需要使用shufps(或punpckldq,punpckhdq)进行水平到垂直的重排,然后使用paddd
(2)SSSE3:使用完pmaddwd后,可直接使用phaddd进行水平相加
(3)SSSE4.1:读取内存时,可使用pmovzxbw和movntdqa