sw_scale中实现yuv420转rgb888——neon汇编优化
2015-01-01 23:39
621 查看
在全志a31s上 使用ffmpeg库中sw_scale转换格式yuv4202rgbx888时,1920x1080的转换耗时有50多ms,渲染50多ms,实际效果无法达到声音视频同步。后在网上找到neon汇编优化代码,移植到sw_scale函数中,效果仍未能改善。
发现主要耗时在加载/存储内存指令上。现将移植部分代码贴上,以备后来再做分析。
c部分接口
由于有些视频解码后宽度变大,改进后实现切边
后期可能会尝试进步优化,现在暂时没有好的想法...
发现主要耗时在加载/存储内存指令上。现将移植部分代码贴上,以备后来再做分析。
.text .global ImgYUV2RGB24_neon .global ImgYUV2RGB24_neon1 @void ImgYUV2RGB24_neon(u8 *pu8RgbBuffer, u8 *pu8SrcYUV, l32 l32Width, l32 l32Height) ImgYUV2RGB24_neon: @push {r4, r5, r6, r7, r8, r9, r10,r11,r12, lr} stmfd sp!, {r4-r10,lr} mov r6, r2 mov r7, r3 ldr r2, [sp,#32] ldr r3, [sp,#36] add r4, r2, r2 add r4, r4, r2 @r4 : DstStride =4 * Width add r4, r4, r2 @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 : Width add r5, r0, r4 @r5 : pu8Dst2 = pu8Dst - l32DstStride mov r9, #16 vdup.8 d8, r9 @d8: 16 mov r10, #128 vdup.8 d9, r10 @d9: 128 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.s16 q2, 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 q2, 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 d25, q13, #6 @@@@@@@@@@@@@@@@@@第一行的G vqrshrun.s16 d29, q14, #6 @@@@@@@@@@@@@@@@@@第二行的G @得到两行的B分量 vqadd.s16 q10, q0, q11 vqadd.s16 q11, q1, q11 vqrshrun.s16 d26, q10, #6 @@@@@@@@@@@@@@@@@@第一行的B vqrshrun.s16 d30, q11, #6 @@@@@@@@@@@@@@@@@@第二行的B @得到两行的R分量 vqadd.s16 q11, q0, q2 vqadd.s16 q2, q1, q2 vqrshrun.s16 d24, q11, #6 @@@@@@@@@@@@@@@@@@第一行的R vqrshrun.s16 d28, q2, #6 @@@@@@@@@@@@@@@@@@第二行的R @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @做interleave操作,形成RGBx形式,然后存入目标buffer vst4.8 {d24,d25,d26,d27}, [r0]! vst4.8 {d28,d29,d30,d31}, [r5]! bgt loop_col subs lr, lr, #1 add r0, r0, r4 add r5, r0, r4 add r1, r1, r2 add r3, r3, r2 @ add r6, r6, r11 @ add r7, r7, r11 mov r8, r2, lsr #3 bgt loop_row @pop {r4, r5, r6, r7, r8, r9, r10, lr} ldmfd sp!, {r4-r10,lr} bx lr
c部分接口
static int yuv420_rgb24_neon(SwsContext *c, const uint8_t *src[], int srcStride[], int sliceY, int sliceH, uint8_t *dst[], int dstStride[]) { if(srcStride[0]>c->srcW) ImgYUV2RGB24_neon1(dst[0],src[0],src[1],src[2],c->srcW,c->srcH); else ImgYUV2RGB24_neon(dst[0],src[0],src[1],src[2],c->srcW,c->srcH); return 0; }
由于有些视频解码后宽度变大,改进后实现切边
ImgYUV2RGB24_neon1: stmfd sp!, {r4-r10,lr} mov r6, r2 mov r7, r3 ldr r2, [sp,#32] ldr r3, [sp,#36] add r4, r2, r2 add r4, r4, r2 @r4 : DstStride = 4 * l32Width add r4, r4, r2 mov r8, r2, lsr #3 @r8 记录了col的循环次数, r2记录了YUV图像宽度 mov lr, r3, lsr #1 @lr 记录了Row的循环次数, r3记录了YUV图像高度 add r3, r1, r2 @r1, pu8Src1@ r3 : pu8Src2, r2 : l32Width add r3, r3, #16 add r5, r0, r4 @r5 : pu8Dst2 = pu8Dst - l32DstStride mov r9, #16 vdup.8 d8, r9 @d8: 16 mov r10, #128 vdup.8 d9, r10 @d9: 128 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_row1: loop_col1: 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.s16 q2, 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 q2, 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 d25, q13, #6 @@@@@@@@@@@@@@@@@@第一行的G vqrshrun.s16 d29, q14, #6 @@@@@@@@@@@@@@@@@@第二行的G @得到两行的B分量 vqadd.s16 q10, q0, q11 vqadd.s16 q11, q1, q11 vqrshrun.s16 d26, q10, #6 @@@@@@@@@@@@@@@@@@第一行的B vqrshrun.s16 d30, q11, #6 @@@@@@@@@@@@@@@@@@第二行的B @得到两行的R分量 vqadd.s16 q11, q0, q2 vqadd.s16 q2, q1, q2 vqrshrun.s16 d24, q11, #6 @@@@@@@@@@@@@@@@@@第一行的R vqrshrun.s16 d28, q2, #6 @@@@@@@@@@@@@@@@@@第二行的R @做interleave操作,形成RGBx形式,然后存入目标buffer vst4.8 {d24,d25,d26,d27}, [r0]! vst4.8 {d28,d29,d30,d31}, [r5]! bgt loop_col1 subs lr, lr, #1 add 4000 r0, r0, r4 add r5, r0, r4 add r1, r1, #16 add r3, r3, #16 add r1, r1, r2 add r3, r3, r2 add r1, r1, #16 add r3, r3, #16 add r6, r6, #8 add r7, r7, #8 mov r8, r2, lsr #3 bgt loop_row1 @pop {r4, r5, r6, r7, r8, r9, r10, lr} ldmfd sp!, {r4-r10,lr} bx lr
后期可能会尝试进步优化,现在暂时没有好的想法...
相关文章推荐
- neon优化的yuv420转rgb24汇编代码,iOS/Android可用
- 采用6个参数的C语言的汇编实现yuv转rgb
- yuv转rgb的汇编实现
- YUV转RGB(NV21-ARGB)的Neon优化代码
- YUV转RGB(NV21-ARGB)的Neon优化代码
- 【数字图像处理】YUV420转RGB并BMP存储<纯C++实现>
- neon内嵌汇编实现一个yuv转rgb的功能stopped原因
- YUV转RGB(NV21-ARGB)的Neon优化代码
- YUV转RGB(NV21-ARGB)的Neon优化代码
- 使用PMULHW或PMADDWD指令对RGB颜色转换至YCbCr颜色的汇编优化
- 算法优化:rgb向yuv的转化最优算法,快得让你吃惊!
- 利用ov511的webeye v2000摄像头实现YUV420P格式转RGB24格式来抓取一张图片
- 图像RGB与YUV转换优化
- 算法优化:rgb向yuv的转化最优算法,ALPHABLEND算法优化快得让你吃惊!
- 高速率AVS整数变换的汇编实现与优化
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- 利用ov511的webeye v2000摄像头实现YUV420P格式转RGB24格式来抓取一张图片
- 图片颜色处理/ 关于RGB转换YUV的探讨与实现
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- YUV420转RGB