@ Do an 8x8 transpose, using q registers for the subtransposes that don't
@ need to address the indiviudal d registers.
@ r0,r1 == rq0, r2,r3 == rq1, etc
.macro transpose_q_8x8 rq0, rq1, rq2, rq3, r0, r1, r2, r3, r4, r5, r6, r7
vtrn.32 \rq0, \rq2
vtrn.32 \rq1, \rq3
vtrn.16 \rq0, \rq1
vtrn.16 \rq2, \rq3
vtrn.8 \r0, \r1
vtrn.8 \r2, \r3
vtrn.8 \r4, \r5
vtrn.8 \r6, \r7
.endm
@ Do a 4x4 transpose, using q registers for the subtransposes that don't
@ need to address the indiviudal d registers.
@ r0,r1 == rq0, r2,r3 == rq1
.macro transpose_q_4x4 rq0, rq1, r0, r1, r2, r3
vtrn.16 \rq0, \rq1
vtrn.8 \r0, \r1
vtrn.8 \r2, \r3
.endm
@ The input to and output from this macro is in the registers q8-q15,
@ and q0-q7 are used as scratch registers.
@ p3 = q8, p0 = q11, q0 = q12, q3 = q15
.macro loop_filter_q
vdup.u8 d0, r2 @ E
lsr r2, r2, #8
vdup.u8 d2, r3 @ I
lsr r3, r3, #8
vdup.u8 d1, r2 @ E
vdup.u8 d3, r3 @ I
vmovl.u8 q0, d20 @ p1
vmovl.u8 q2, d21 @ p1
vmovl.u8 q6, d26 @ q1
vmovl.u8 q7, d27 @ q1
vaddw.s8 q0, q0, d10 @ p1 + f
vaddw.s8 q2, q2, d11 @ p1 + f
vsubw.s8 q6, q6, d10 @ q1 - f
vsubw.s8 q7, q7, d11 @ q1 - f
vqmovun.s16 d0, q0 @ out p1
vqmovun.s16 d1, q2 @ out p1
vqmovun.s16 d12, q6 @ out q1
vqmovun.s16 d13, q7 @ out q1
vbit q10, q0, q3 @ if (!hev && fm && !flat8in)
vbit q13, q6, q3
.endm
@ The input to and output from this macro is in the registers d16-d31,
@ and d0-d7 are used as scratch registers.
@ p7 = d16 .. p3 = d20, p0 = d23, q0 = d24, q3 = d27, q7 = d31
@ Depending on the width of the loop filter, we either use d16-d19
@ and d28-d31 as temp registers, or d8-d15.
@ tmp1,tmp2 = tmpq1, tmp3,tmp4 = tmpq2, tmp5,tmp6 = tmpq3, tmp7,tmp8 = tmpq4
.macro loop_filter wd, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmpq1, tmpq2, tmpq3, tmpq4
vdup.u8 d0, r2 @ E
vdup.u8 d2, r3 @ I
ldr r3, [sp]
vmax.u8 d7, d7, d2
vmax.u8 d1, d1, d8
vmax.u8 d9, d9, d10
vmax.u8 d11, d11, d12
@ The rest of the calculation of flat8out is interleaved below
.else
@ The rest of the calculation of flat8in is interleaved below
.endif
.endif
vadd.u16 q0, q0, \tmpq2
@ The output here is written back into the input registers. This doesn't
@ matter for the flat8out part below, since we only update those pixels
@ which won't be touched below.
vbit d21, d2, d6
vbit d22, d3, d6
vbit d23, d4, d6
vrshrn.u16 \tmp6, q0, #3 @ out q2
vbit d24, d5, d6
vbit d25, \tmp5, d6
vbit d26, \tmp6, d6
.endif
.if \wd == 16 6:
vorr d2, d6, d7
vmov r2, r3, d2
orrs r2, r2, r3
@ If no pixels needed flat8in nor flat8out, jump to a
@ writeout of the inner 4 pixels
beq 7f
vmov r2, r3, d7
orrs r2, r2, r3
@ If no pixels need flat8out, jump to a writeout of the inner 6 pixels
beq 8f
@ flat8out
@ This writes all outputs into d2-d17 (skipping d6 and d16).
@ If this part is skipped, the output is read from d21-d26 (which is the input
@ to this section).
vshll.u8 q0, d16, #3 @ 8 * d16
vsubw.u8 q0, q0, d16 @ 7 * d16
vaddw.u8 q0, q0, d17
vaddl.u8 q4, d17, d18
vaddl.u8 q5, d19, d20
vadd.s16 q0, q0, q4
vaddl.u8 q4, d16, d17
vaddl.u8 q6, d21, d22
vadd.s16 q0, q0, q5
vaddl.u8 q5, d18, d25
vaddl.u8 q7, d23, d24
vsub.s16 q5, q5, q4
vadd.s16 q0, q0, q6
vadd.s16 q0, q0, q7
vaddl.u8 q6, d16, d18
vaddl.u8 q7, d19, d26
vrshrn.u16 d2, q0, #4
@ For wd <= 8, we use d16-d19 and d28-d31 for temp registers,
@ while we need those for inputs/outputs in wd=16 and use d8-d15
@ for temp registers there instead.
.macro loop_filter_4
loop_filter 4, d16, d17, d18, d19, d28, d29, d30, d31, q8, q9, q14, q15
.endm
@ The public functions in this file have got the following signature:
@ void loop_filter(uint8_t *dst, ptrdiff_t stride, int mb_lim, int lim, int hev_thr);
sub r12, r12, r1, lsl #2 sub r0, r0, r1, lsl #2
@ Move r0/r12 forward by 2 pixels; we don't need to rewrite the
@ outermost 2 pixels since they aren't changed.
add r12, r12, #2
add r0, r0, #2
@ Transpose the 8x8 pixels, taking advantage of q registers, to get
@ one register per column.
transpose_q_8x8 q10, q11, q12, q13, d20, d21, d22, d23, d24, d25, d26, d27
loop_filter_4
@ We only will write the mid 4 pixels back; after the loop filter,
@ these are in d22, d23, d24, d25 (q11, q12), ordered as rows
@ (8x4 pixels). We need to transpose them to columns, done with a
@ 4x4 transpose (which in practice is two 4x4 transposes of the two
@ 4x4 halves of the 8x4 pixels; into 4x8 pixels).
transpose_q_4x4 q11, q12, d22, d23, d24, d25
@ Transpose the 16x8 pixels, as two 8x8 parts
transpose_8x8 q8, q9, q10, q11, q12, q13, q14, q15
loop_filter_q
sub r12, r0, r1, lsl #4
add r0, r12, r1, lsl #3
@ Move r0/r12 forward by 2 pixels; we don't need to rewrite the
@ outermost 2 pixels since they aren't changed.
add r12, r12, #2
add r0, r0, #2
@ We only will write the mid 4 pixels back; after the loop filter,
@ these are in q10, q11, q12, q13, ordered as rows (16x4 pixels).
@ We need to transpose them to columns, done with a 4x4 transpose
@ (which in practice is four 4x4 transposes of the 4x4 blocks of
@ the 16x4 pixels; into 4x16 pixels).
transpose_4x4 q10, q11, q12, q13
@ Even though only 6 pixels per row have been changed, we write the
@ full 8 pixel registers.
transpose_q_8x8 q10, q11, q12, q13, d20, d21, d22, d23, d24, d25, d26, d27
vst1.8 {d20}, [r12], r1
vst1.8 {d24}, [r0], r1
vst1.8 {d21}, [r12], r1
vst1.8 {d25}, [r0], r1
vst1.8 {d22}, [r12], r1
vst1.8 {d26}, [r0], r1
vst1.8 {d23}, [r12], r1
vst1.8 {d27}, [r0], r1 9:
bx lr 6:
@ If we didn't need to do the flat8in part, we use the same writeback
@ as in loop_filter_h_4_8.
add r12, r12, #2
add r0, r0, #2
transpose_q_4x4 q11, q12, d22, d23, d24, d25
vst1.32 {d22[0]}, [r12], r1
vst1.32 {d22[1]}, [r0], r1
vst1.32 {d23[0]}, [r12], r1
vst1.32 {d23[1]}, [r0], r1
vst1.32 {d24[0]}, [r12], r1
vst1.32 {d24[1]}, [r0], r1
vst1.32 {d25[0]}, [r12], r1
vst1.32 {d25[1]}, [r0], r1
bx lr
endfunc
function ff_vp9_loop_filter_v_16_16_neon, export=1
ldr r12, [sp]
// The filter clobbers r2 and r3, but we need to keep them for the second round
push {r2, r3, lr}
vpush {q4-q7}
push {r12}
bl vp9_loop_filter_v_16_neon
add r0, #8
ldr r2, [sp, #68]
ldr r3, [sp, #72]
bl vp9_loop_filter_v_16_neon
add sp, sp, #4
vpop {q4-q7}
pop {r2, r3, pc}
endfunc
@ The 16x8 pixels read above is in two 8x8 blocks; the left
@ half in d16-d23, and the right half in d24-d31. Do two 8x8 transposes
@ of this, to get one column per register. This could be done with two
@ transpose_8x8 as below, but this takes advantage of the q registers.
transpose16_4x4 q8, q9, q10, q11, q12, q13, q14, q15
vtrn.8 d16, d17
vtrn.8 d18, d19
vtrn.8 d20, d21
vtrn.8 d22, d23
vtrn.8 d24, d25
vtrn.8 d26, d27
vtrn.8 d28, d29
vtrn.8 d30, d31
loop_filter_16
@ Transpose back; this is the same transpose as above, but
@ we can't take advantage of q registers for the transpose, since
@ all d registers in the transpose aren't consecutive.
transpose_8x8 d16, d2, d3, d4, d5, d6, d8, d9
transpose_8x8 d10, d11, d12, d13, d14, d15, d17, d31
function ff_vp9_loop_filter_h_16_16_neon, export=1
ldr r12, [sp]
// The filter clobbers r2 and r3, but we need to keep them for the second round
push {r2, r3, lr}
vpush {q4-q7}
push {r12}
bl vp9_loop_filter_h_16_neon
add r0, r0, r1, lsl #3
ldr r2, [sp, #68]
ldr r3, [sp, #72]
bl vp9_loop_filter_h_16_neon
add sp, sp, #4
vpop {q4-q7}
pop {r2, r3, pc}
endfunc
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet am 2026-10-01)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.