pixel_avg2_w20_neon x264像素宽度为20的均值计算

发布时间:2024年01月19日

一 C语言实现

static?inline?void?pixel_avg2_w20_altivec(uint8_t?*dst,?intptr_t?i_dst,

uint8_t?*src1,?intptr_t?i_src1,

uint8_t?*src2,?int?i_height)

{

????pixel_avg2_w16_altivec(dst,?idst,?src1,?i_src1,?src2,?i_height);?//前面16列

????pixel_avg2_w4_altivec(dst?+?16,?i_dst,?src1?+?16,?i_src1,?src2?+?16,?i_height);?//后面4列

}??

static?inline?void?pixel_avg2_w16_altivec(uint8_t?*dst,?intptr_t?i_dst,

uint8_t?*src1,?intptr_t?i_src1,?

uint8_t?*src2,?int?i_height)

{

????vec_u8_t?src1v,?src2v;

????for?(int?y?=?0;?y?<?i_height;?y++)

????{

????????src1v?=?vec_vsx_ld(0,?src1);

????????src2v?=?vec_vsx_ld(0,?src2);

????????src1v?=?vec_avg(src1v,?srcv2);

????????vec_st(src1v,?0,?dst);

????????dst?+=?i_dst;

????????src1?+=?i_src1;

????????src2?+=?i_src1;?

????}

}

static?inline?void?pixel_avg2_w4_altivec(uint8_t?*dst,?intptr_t?i_dst,

uint8_t?*src1,?intptr_t?i_src1,

uint8_t?*src2,?int?i_height)

{

????for?(int?y?=?0;?y?<?i_height;?y++)

????{

????????for?(int?x?=?0;?x?<?4;?x++)

????????????dst[x]?=?(src1[x]?+?src2[x]?+?1)?>>?1;

????????dst?+=?i_dst;

????????src1?+=?i_src1;

????????src2?+=?i_src1;

?????}

}

二?汇编实现

function?pixel_avg2_w20_neon

????ldr?ip,?[sp,?#4]

????push?{lr}

????sub?r1,?r1,?#16

????ldr?lr,?[sp,?#4]

i_height

src2

sp开始的位置,sp?+?4就是i_height

push?{lr}

lr寄存器在此,sp?+?4?就是?src2

function?pixel_avg2_w20_neon

????ldr?????????ip,??[sp,?#4]?//取参数?height?到?ip

????push????????{lr}?//push?lr到栈上,sp寄存器,也减小了?-?4

????sub?????????r1,??r1,??#16?//r1?=?r1?-?16

????ldr?????????lr,??[sp,?#4]?//src2?载入到?lr寄存器?

avg2_w20_loop:

????subs????????ip,??ip,??#2?//ip?=?ip?-?2

????vld1.64?????{d0-d2},??[r2],?r3?//先从r2(src1)处加载?24字节???d0?d1?d2

????vld1.64?????{d4-d6},??[lr],?r3?//先从lr(dst)处加载?24字节???d4?d5?d6

????vrhadd.u8???q0,??q0,??q2??//q0?=?(q0?+?q2?+?1)?>>?1??这里?q0?=?d0?d1??q2?=?d4?d4

????//因此上面这句话的意思是,?d0?=?d0?+?d4?,?d1?=?d1?+?d5??这里计算了128也就是16字节

????vrhadd.u8???d2,??d2,??d6??//d2?=?(d2?+?d6?+?1)?>>?1

????//上面这句话,是末尾还有8个字节的计算。?d2?=?d2?+?d6

????vld1.64?????{d4-d6},??[r2],?r3?//载入数据?d4?d5?d6?再次读入数据

????vld1.64?????{d16-d18},[lr],?r3?//载入数据?d16?d17?d18?再次读入数据

????vrhadd.u8???q2,??q2,??q8?//q2?=?(q2?+?q8?+?1)?>>?1

????//和上面操作类似,?q2?=?d4?d5,?q8?=?d16?d17?16个字节相加

????vst1.64?????{d0-d1},??[r0,:128]!?//d0?d1?->?存储到?r0,?128bits??存储回去128bits

????vrhadd.u8???d6,??d6,??d18?//?d6?=?(d6?+?d18?+?1)?>>?1?剩余的8字节相加?

????vst1.32?????{d2[0]},??[r0,:32],?r1?//vst1.32?{d2[0]},?[r0,:32],?r1?指令表示将寄存器??存储回去

????//d2?中的数据的低?32?位存储到内存地址?[r0?+?r1]?处。这里的?r0?是存储地址的基址,r1?是偏移量,表示存储地址的偏移量

????//vst1.32?{d2[1]},?[r0,:32],?r1?的意思是将寄存器?d2?中的数据的高?32?位存储到内存地址?

????//?[r0?+?r1]?处。这里的?r0?是存储地址的基址,r1?是偏移量,表示存储地址的偏移量。

????vst1.64?????{d4-d5},??[r0,:128]!?//d4?d5?->存储到?r0?刚才后面一组的计算结果?d4?d5存储回去

????vst1.32?????{d6[0]},??[r0,:32],?r1?//d6[0]?低?32位?存储到?r0的位置?最后计算的结果d6存储回去?

????//以上一次计算了2行的数据,所以?ip?=?ip?-?2,每次减少两行,再循环

????bgt?????????avg2_w20_loop

????pop?????????{pc}?//弹出?lr到pc上。

endfunc

文章来源:https://blog.csdn.net/fantasy_ARM9/article/details/135703170
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。