]> git.sesse.net Git - ffmpeg/blob - libavfilter/x86/vf_ssim.asm
Merge commit 'dad5fd59f3d6a8311365314cfcde0ebcd15c2b01'
[ffmpeg] / libavfilter / x86 / vf_ssim.asm
1 ;*****************************************************************************
2 ;* x86-optimized functions for ssim filter
3 ;*
4 ;* Copyright (C) 2015 Ronald S. Bultje <rsbultje@gmail.com>
5 ;*
6 ;* This file is part of FFmpeg.
7 ;*
8 ;* FFmpeg is free software; you can redistribute it and/or
9 ;* modify it under the terms of the GNU Lesser General Public
10 ;* License as published by the Free Software Foundation; either
11 ;* version 2.1 of the License, or (at your option) any later version.
12 ;*
13 ;* FFmpeg is distributed in the hope that it will be useful,
14 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 ;* Lesser General Public License for more details.
17 ;*
18 ;* You should have received a copy of the GNU Lesser General Public
19 ;* License along with FFmpeg; if not, write to the Free Software
20 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 ;******************************************************************************
22
23 %include "libavutil/x86/x86util.asm"
24
25 SECTION_RODATA
26
27 pw_1: times 8 dw 1
28 ssim_c1: times 4 dd 416 ;(.01*.01*255*255*64 + .5)
29 ssim_c2: times 4 dd 235963 ;(.03*.03*255*255*64*63 + .5)
30
31 SECTION .text
32
33 %macro SSIM_4X4_LINE 1
34 %if ARCH_X86_64
35 cglobal ssim_4x4_line, 6, 8, %1, buf, buf_stride, ref, ref_stride, sums, w, buf_stride3, ref_stride3
36 %else
37 cglobal ssim_4x4_line, 5, 7, %1, buf, buf_stride, ref, ref_stride, sums, buf_stride3, ref_stride3
38 %define wd r5mp
39 %endif
40     lea     ref_stride3q, [ref_strideq*3]
41     lea     buf_stride3q, [buf_strideq*3]
42 %if notcpuflag(xop)
43     pxor              m7, m7
44     mova             m15, [pw_1]
45 %endif
46
47 .loop:
48 %if cpuflag(xop)
49     pmovzxbw          m0, [bufq+buf_strideq*0]
50     pmovzxbw          m1, [refq+ref_strideq*0]
51     pmaddwd           m4, m0, m0
52     pmaddwd           m6, m0, m1
53     pmovzxbw          m2, [bufq+buf_strideq*1]
54     vpmadcswd         m4, m1, m1, m4
55     pmovzxbw          m3, [refq+ref_strideq*1]
56     paddw             m0, m2
57     vpmadcswd         m4, m2, m2, m4
58     vpmadcswd         m6, m2, m3, m6
59     paddw             m1, m3
60     vpmadcswd         m4, m3, m3, m4
61
62     pmovzxbw          m2, [bufq+buf_strideq*2]
63     pmovzxbw          m3, [refq+ref_strideq*2]
64     vpmadcswd         m4, m2, m2, m4
65     vpmadcswd         m6, m2, m3, m6
66     pmovzxbw          m5, [bufq+buf_stride3q]
67     pmovzxbw          m7, [refq+ref_stride3q]
68     vpmadcswd         m4, m3, m3, m4
69     vpmadcswd         m6, m5, m7, m6
70     paddw             m0, m2
71     paddw             m1, m3
72     vpmadcswd         m4, m5, m5, m4
73     paddw             m0, m5
74     paddw             m1, m7
75     vpmadcswd         m4, m7, m7, m4
76 %else
77     movh              m0, [bufq+buf_strideq*0]  ; a1
78     movh              m1, [refq+ref_strideq*0]  ; b1
79     movh              m2, [bufq+buf_strideq*1]  ; a2
80     movh              m3, [refq+ref_strideq*1]  ; b2
81     punpcklbw         m0, m7                    ; s1 [word]
82     punpcklbw         m1, m7                    ; s2 [word]
83     punpcklbw         m2, m7                    ; s1 [word]
84     punpcklbw         m3, m7                    ; s2 [word]
85     pmaddwd           m4, m0, m0                ; a1 * a1
86     pmaddwd           m5, m1, m1                ; b1 * b1
87     pmaddwd           m8, m2, m2                ; a2 * a2
88     pmaddwd           m9, m3, m3                ; b2 * b2
89     paddd             m4, m5                    ; ss
90     paddd             m8, m9                    ; ss
91     pmaddwd           m6, m0, m1                ; a1 * b1 = ss12
92     pmaddwd           m5, m2, m3                ; a2 * b2 = ss12
93     paddw             m0, m2
94     paddw             m1, m3
95     paddd             m6, m5                    ; s12
96     paddd             m4, m8                    ; ss
97
98     movh              m2, [bufq+buf_strideq*2]  ; a3
99     movh              m3, [refq+ref_strideq*2]  ; b3
100     movh              m5, [bufq+buf_stride3q]   ; a4
101     movh              m8, [refq+ref_stride3q]   ; b4
102     punpcklbw         m2, m7                    ; s1 [word]
103     punpcklbw         m3, m7                    ; s2 [word]
104     punpcklbw         m5, m7                    ; s1 [word]
105     punpcklbw         m8, m7                    ; s2 [word]
106     pmaddwd           m9, m2, m2                ; a3 * a3
107     pmaddwd          m10, m3, m3                ; b3 * b3
108     pmaddwd          m12, m5, m5                ; a4 * a4
109     pmaddwd          m13, m8, m8                ; b4 * b4
110     pmaddwd          m11, m2, m3                ; a3 * b3 = ss12
111     pmaddwd          m14, m5, m8                ; a4 * b4 = ss12
112     paddd             m9, m10
113     paddd            m12, m13
114     paddw             m0, m2
115     paddw             m1, m3
116     paddw             m0, m5
117     paddw             m1, m8
118     paddd             m6, m11
119     paddd             m4, m9
120     paddd             m6, m14
121     paddd             m4, m12
122 %endif
123
124     ; m0 = [word] s1 a,a,a,a,b,b,b,b
125     ; m1 = [word] s2 a,a,a,a,b,b,b,b
126     ; m4 = [dword] ss a,a,b,b
127     ; m6 = [dword] s12 a,a,b,b
128
129 %if cpuflag(xop)
130     vphaddwq          m0, m0                    ; [dword] s1  a, 0, b, 0
131     vphaddwq          m1, m1                    ; [dword] s2  a, 0, b, 0
132     vphadddq          m4, m4                    ; [dword] ss  a, 0, b, 0
133     vphadddq          m6, m6                    ; [dword] s12 a, 0, b, 0
134     punpckhdq     m2, m0, m1                    ; [dword] s1  b, s2 b, 0, 0
135     punpckldq         m0, m1                    ; [dword] s1  a, s2 a, 0, 0
136     punpckhdq     m3, m4, m6                    ; [dword] ss  b, s12 b, 0, 0
137     punpckldq         m4, m6                    ; [dword] ss  a, s12 a, 0, 0
138     punpcklqdq    m1, m2, m3                    ; [dword] b s1, s2, ss, s12
139     punpcklqdq        m0, m4                    ; [dword] a s1, s2, ss, s12
140 %else
141     pmaddwd           m0, m15                   ; [dword] s1 a,a,b,b
142     pmaddwd           m1, m15                   ; [dword] s2 a,a,b,b
143     phaddd            m0, m4                    ; [dword] s1 a, b, ss a, b
144     phaddd            m1, m6                    ; [dword] s2 a, b, s12 a, b
145     punpckhdq     m2, m0, m1                    ; [dword] ss a, s12 a, ss b, s12 b
146     punpckldq         m0, m1                    ; [dword] s1 a, s2 a, s1 b, s2 b
147     punpckhqdq    m1, m0, m2                    ; [dword] b s1, s2, ss, s12
148     punpcklqdq        m0, m2                    ; [dword] a s1, s2, ss, s12
149 %endif
150
151     mova  [sumsq+     0], m0
152     mova  [sumsq+mmsize], m1
153
154     add             bufq, mmsize/2
155     add             refq, mmsize/2
156     add            sumsq, mmsize*2
157     sub               wd, mmsize/8
158     jg .loop
159     RET
160 %endmacro
161
162 %if ARCH_X86_64
163 INIT_XMM ssse3
164 SSIM_4X4_LINE 16
165 %endif
166 %if HAVE_XOP_EXTERNAL
167 INIT_XMM xop
168 SSIM_4X4_LINE 8
169 %endif
170
171 INIT_XMM sse4
172 cglobal ssim_end_line, 3, 3, 6, sum0, sum1, w
173     pxor              m0, m0
174 .loop:
175     mova              m1, [sum0q+mmsize*0]
176     mova              m2, [sum0q+mmsize*1]
177     mova              m3, [sum0q+mmsize*2]
178     mova              m4, [sum0q+mmsize*3]
179     paddd             m1, [sum1q+mmsize*0]
180     paddd             m2, [sum1q+mmsize*1]
181     paddd             m3, [sum1q+mmsize*2]
182     paddd             m4, [sum1q+mmsize*3]
183     paddd             m1, m2
184     paddd             m2, m3
185     paddd             m3, m4
186     paddd             m4, [sum0q+mmsize*4]
187     paddd             m4, [sum1q+mmsize*4]
188     TRANSPOSE4x4D      1, 2, 3, 4, 5
189
190     ; m1 = fs1, m2 = fs2, m3 = fss, m4 = fs12
191     pslld             m3, 6
192     pslld             m4, 6
193     pmulld            m5, m1, m2                ; fs1 * fs2
194     pmulld            m1, m1                    ; fs1 * fs1
195     pmulld            m2, m2                    ; fs2 * fs2
196     psubd             m3, m1
197     psubd             m4, m5                    ; covariance
198     psubd             m3, m2                    ; variance
199
200     ; m1 = fs1 * fs1, m2 = fs2 * fs2, m3 = variance, m4 = covariance, m5 = fs1 * fs2
201     paddd             m4, m4                    ; 2 * covariance
202     paddd             m5, m5                    ; 2 * fs1 * fs2
203     paddd             m1, m2                    ; fs1 * fs1 + fs2 * fs2
204     paddd             m3, [ssim_c2]             ; variance + ssim_c2
205     paddd             m4, [ssim_c2]             ; 2 * covariance + ssim_c2
206     paddd             m5, [ssim_c1]             ; 2 * fs1 * fs2 + ssim_c1
207     paddd             m1, [ssim_c1]             ; fs1 * fs1 + fs2 * fs2 + ssim_c1
208
209     ; convert to float
210     cvtdq2ps          m3, m3
211     cvtdq2ps          m4, m4
212     cvtdq2ps          m5, m5
213     cvtdq2ps          m1, m1
214     mulps             m4, m5
215     mulps             m3, m1
216     divps             m4, m3                    ; ssim_endl
217     addps             m0, m4                    ; ssim
218     add            sum0q, mmsize*4
219     add            sum1q, mmsize*4
220     sub               wd, 4
221     jg .loop
222
223     ; subps the ones we added too much
224     test              wd, wd
225     jz .end
226     add               wd, 4
227     test              wd, 2
228     jz .skip2
229     psrldq            m4, 8
230 .skip2:
231     test              wd, 1
232     jz .skip1
233     psrldq            m4, 4
234 .skip1:
235     subps             m0, m4
236
237 .end:
238     movhlps           m4, m0
239     addps             m0, m4
240     movss             m4, m0
241     shufps            m0, m0, 1
242     addss             m0, m4
243 %if ARCH_X86_32
244     movss            r0m, m0
245     fld             r0mp
246 %endif
247     RET