yuv12转rgb24 c语言,neon指令进行yuv420到rgb24转换效率

转载:http://blog.csdn.net/alien75/article/details/7377179

从网上找到了一个用neon指令优化yuv420转换成rgb24的代码, 在cortex-A8架构、主频1G的cpu下进行对一帧qcif(176x144)数据测试,另外用网上很流行的用C写的算法做比较,发现前者的速度是后者的700多倍:前者循环1000次用时112ms,后者88645ms。相关代码如下:

汇编语言

AREA |.text|, CODE, READONLY      ; name this block of code

EXPORT ImgYUV2RGB24_neon

ALIGN

;void ImgYUV2RGB24_neon(u8 *pu8RgbBuffer, u8 *pu8SrcYUV, l32 l32Width, l32 l32Height)

ImgYUV2RGB24_neon

;push            {r4, r5, r6, r7, r8, r9, r10, lr}

stmfdsp!, {r4-r10,lr}

add             r4,  r2, r2

add             r4,  r4, r2             ;r4 : DstStride = 3 * l32Width

mul             r5, r4, r3

sub             r5, r5, r4

add             r0, r0, r5             ;r0: pu8Dst = pu8Dst + l32DstStride * (l32Height - 1)

mul             r5, r2, r3

add             r6, r1, r5             ;r6 : pu8SrcU = pu8SrcYUV + l32Width * l32Height

add             r7, r6, r5, lsr #2     ;r7 : pu8SrcV = pu8SrcU + ((l32Width * l32Height)>>2)

;lsr             r8, r2, #3             ;r8 记录了col的循环次数, r2记录了YUV图像宽度

mov r8, r2, lsr #3

;lsr             lr, r3, #1             ;lr 记录了Row的循环次数, r3记录了YUV图像高度

mov lr, r3, lsr #1

add             r3, r1, r2             ;r1, pu8Src1;  r3 : pu8Src2, r2 : l32Width

sub             r5, r0, r4             ;r5 : pu8Dst2 = pu8Dst - l32DstStride

mov             r9, #16

vdup.8          d8, r9

mov             r10, #128

vdup.8          d9, r10

mov             r9, #75

vdup.16         q5, r9 ;q5: 75

mov             r10, #102

vdup.16         q6, r10;q6: 102

mov             r9, #25

vdup.16         q7, r9 ;q7: 25

mov             r10, #52

vdup.16         q8, r10;q8: 52

mov             r9, #129

vdup.16         q9, r9;q9: 129

loop_row

loop_col

subs            r8, r8, #1

vld1.u8         d0, [r1]!     ;YLine1

vld1.u8         d2, [r3]!     ;YLine2

vld1.32         {d4[0]}, [r6]!      ;U

vld1.32         {d4[1]}, [r7]!;V

vsubl.u8        q0, d0, d8         ;YLine2 - 16

vsubl.u8        q1, d2, d8         ;YLine1 - 16

vsubl.u8        q2, d4, d9

vmov            q3, q2

vzip.s16q2, q3               ;q2:U - 128  q3: V-128

;开始计算乘法部分

vmul.s16         q10, q3, q8

vmla.s16         q10, q2, q7 ;得到计算G分量所需要的后半部分U、V之和

vmul.s16         q11, q2, q9 ;得到计算B分量的后半部分所需要的U

vmul.s16         q12, q3, q6 ;得到计算R分量的后半部分所需要的V

;计算Y的部分乘积

vmul.s16       q0, q0, q5     ;q0、q1得到第一行Y的共8点乘积

vmul.s16        q1, q1, q5     ;q2、q3得到第二行Y的共8点乘积

;得到两行的G分量

vqsub.s16        q13, q0, q10

vqsub.s16        q14, q1, q10

vqrshrun.s16     d27, q13, #6  ;;;;;;;;;;;;;;;;;;第一行的G

vqrshrun.s16     d30, q14, #6;;;;;;;;;;;;;;;;;;第二行的G

;得到两行的B分量

vqadd.s16       q10, q0, q11

vqadd.s16       q11, q1, q11

vqrshrun.s16    d26, q10, #6;;;;;;;;;;;;;;;;;;第一行的B

vqrshrun.s16    d29, q11, #6;;;;;;;;;;;;;;;;;;第二行的B

;得到两行的R分量

vqadd.s16       q11, q0, q12

vqadd.s16       q12, q1, q12

vqrshrun.s16    d28, q11, #6;;;;;;;;;;;;;;;;;;第一行的R

vqrshrun.s16    d31, q12, #6;;;;;;;;;;;;;;;;;;第二行的R

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;做interleave操作,形成RGB形式,然后存入目标buffer

vst3.8          {d26, d27, d28}, [r0]!

vst3.8          {d29, d30, d31}, [r5]!

bgt             loop_col

subs            lr, lr, #1

sub             r0, r5, r4, lsl #1

sub             r5, r0, r4

add             r1, r1, r2

add             r3, r3, r2

;lsr             r8, r2, #3

movr8, r2, lsr #3

bgt             loop_row

;pop             {r4, r5, r6, r7, r8, r9, r10, lr}

ldmfdsp!, {r4-r10,lr}

bx              lr

END

C语言

void YUV420p_to_RGB24(unsigned char *yuv420[3], unsigned char *rgb24, int width, int height)

{

//  int begin = GetTickCount();

int R,G,B,Y,U,V;

int x,y;

int nWidth = width>>1; //色度信号宽度

for (y=0;y

{

for (x=0;x

{

Y = *(yuv420[0] + y*width + x);

U = *(yuv420[1] + ((y>>1)*nWidth) + (x>>1));

V = *(yuv420[2] + ((y>>1)*nWidth) + (x>>1));

R = Y + 1.402*(V-128);

G = Y - 0.34414*(U-128) - 0.71414*(V-128);

B = Y + 1.772*(U-128);

//防止越界

if (R>255)R=255;

if (R<0)R=0;

if (G>255)G=255;

if (G<0)G=0;

if (B>255)B=255;

if (B<0)B=0;

*(rgb24 + ((height-y-1)*width + x)*3) = B;

*(rgb24 + ((height-y-1)*width + x)*3 + 1) = G;

*(rgb24 + ((height-y-1)*width + x)*3 + 2) = R;

//    *(rgb24 + (y*width + x)*3) = B;

//    *(rgb24 + (y*width + x)*3 + 1) = G;

//    *(rgb24 + (y*width + x)*3 + 2) = R;

}

}

}

阅读(1489) | 评论(0) | 转发(0) |

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值