]> git.sesse.net Git - ffmpeg/blob - libavcodec/ppc/h264chroma_template.c
nvenc: Allow different const qps for I, P and B frames
[ffmpeg] / libavcodec / ppc / h264chroma_template.c
1 /*
2  * Copyright (c) 2004 Romain Dolbeau <romain@dolbeau.org>
3  *
4  * This file is part of Libav.
5  *
6  * Libav is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * Libav is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Libav; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include "libavutil/mem.h"
22
23 /* this code assume that stride % 16 == 0 */
24
25 #define CHROMA_MC8_ALTIVEC_CORE(BIAS1, BIAS2) \
26         vsrc2ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc2uc);\
27         vsrc3ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc3uc);\
28 \
29         psum = vec_mladd(vA, vsrc0ssH, BIAS1);\
30         psum = vec_mladd(vB, vsrc1ssH, psum);\
31         psum = vec_mladd(vC, vsrc2ssH, psum);\
32         psum = vec_mladd(vD, vsrc3ssH, psum);\
33         psum = BIAS2(psum);\
34         psum = vec_sr(psum, v6us);\
35 \
36         vdst = vec_ld(0, dst);\
37         ppsum = (vec_u8)vec_pack(psum, psum);\
38         vfdst = vec_perm(vdst, ppsum, fperm);\
39 \
40         OP_U8_ALTIVEC(fsum, vfdst, vdst);\
41 \
42         vec_st(fsum, 0, dst);\
43 \
44         vsrc0ssH = vsrc2ssH;\
45         vsrc1ssH = vsrc3ssH;\
46 \
47         dst += stride;\
48         src += stride;
49
50 #define CHROMA_MC8_ALTIVEC_CORE_SIMPLE \
51 \
52         vsrc0ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc0uc);\
53         vsrc1ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc1uc);\
54 \
55         psum = vec_mladd(vA, vsrc0ssH, v32ss);\
56         psum = vec_mladd(vE, vsrc1ssH, psum);\
57         psum = vec_sr(psum, v6us);\
58 \
59         vdst = vec_ld(0, dst);\
60         ppsum = (vec_u8)vec_pack(psum, psum);\
61         vfdst = vec_perm(vdst, ppsum, fperm);\
62 \
63         OP_U8_ALTIVEC(fsum, vfdst, vdst);\
64 \
65         vec_st(fsum, 0, dst);\
66 \
67         dst += stride;\
68         src += stride;
69
70 #define noop(a) a
71 #define add28(a) vec_add(v28ss, a)
72
73 #ifdef PREFIX_h264_chroma_mc8_altivec
74 static void PREFIX_h264_chroma_mc8_altivec(uint8_t * dst, uint8_t * src,
75                                            ptrdiff_t stride, int h,
76                                            int x, int y)
77 {
78     DECLARE_ALIGNED(16, signed int, ABCD)[4] =
79                         {((8 - x) * (8 - y)),
80                          ((    x) * (8 - y)),
81                          ((8 - x) * (    y)),
82                          ((    x) * (    y))};
83     register int i;
84     vec_u8 fperm;
85     const vec_s32 vABCD = vec_ld(0, ABCD);
86     const vec_s16 vA = vec_splat((vec_s16)vABCD, 1);
87     const vec_s16 vB = vec_splat((vec_s16)vABCD, 3);
88     const vec_s16 vC = vec_splat((vec_s16)vABCD, 5);
89     const vec_s16 vD = vec_splat((vec_s16)vABCD, 7);
90     LOAD_ZERO;
91     const vec_s16 v32ss = vec_sl(vec_splat_s16(1),vec_splat_u16(5));
92     const vec_u16 v6us = vec_splat_u16(6);
93     register int loadSecond = (((unsigned long)src) % 16) <= 7 ? 0 : 1;
94     register int reallyBadAlign = (((unsigned long)src) % 16) == 15 ? 1 : 0;
95
96     vec_u8 vsrcAuc, av_uninit(vsrcBuc), vsrcperm0, vsrcperm1;
97     vec_u8 vsrc0uc, vsrc1uc;
98     vec_s16 vsrc0ssH, vsrc1ssH;
99     vec_u8 vsrcCuc, vsrc2uc, vsrc3uc;
100     vec_s16 vsrc2ssH, vsrc3ssH, psum;
101     vec_u8 vdst, ppsum, vfdst, fsum;
102
103     if (((unsigned long)dst) % 16 == 0) {
104         fperm = (vec_u8){0x10, 0x11, 0x12, 0x13,
105                          0x14, 0x15, 0x16, 0x17,
106                          0x08, 0x09, 0x0A, 0x0B,
107                          0x0C, 0x0D, 0x0E, 0x0F};
108     } else {
109         fperm = (vec_u8){0x00, 0x01, 0x02, 0x03,
110                          0x04, 0x05, 0x06, 0x07,
111                          0x18, 0x19, 0x1A, 0x1B,
112                          0x1C, 0x1D, 0x1E, 0x1F};
113     }
114
115     vsrcAuc = vec_ld(0, src);
116
117     if (loadSecond)
118         vsrcBuc = vec_ld(16, src);
119     vsrcperm0 = vec_lvsl(0, src);
120     vsrcperm1 = vec_lvsl(1, src);
121
122     vsrc0uc = vec_perm(vsrcAuc, vsrcBuc, vsrcperm0);
123     if (reallyBadAlign)
124         vsrc1uc = vsrcBuc;
125     else
126         vsrc1uc = vec_perm(vsrcAuc, vsrcBuc, vsrcperm1);
127
128     vsrc0ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc0uc);
129     vsrc1ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc1uc);
130
131     if (ABCD[3]) {
132         if (!loadSecond) {// -> !reallyBadAlign
133             for (i = 0 ; i < h ; i++) {
134                 vsrcCuc = vec_ld(stride + 0, src);
135                 vsrc2uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm0);
136                 vsrc3uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm1);
137
138                 CHROMA_MC8_ALTIVEC_CORE(v32ss, noop)
139             }
140         } else {
141             vec_u8 vsrcDuc;
142             for (i = 0 ; i < h ; i++) {
143                 vsrcCuc = vec_ld(stride + 0, src);
144                 vsrcDuc = vec_ld(stride + 16, src);
145                 vsrc2uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm0);
146                 if (reallyBadAlign)
147                     vsrc3uc = vsrcDuc;
148                 else
149                     vsrc3uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm1);
150
151                 CHROMA_MC8_ALTIVEC_CORE(v32ss, noop)
152             }
153         }
154     } else {
155         const vec_s16 vE = vec_add(vB, vC);
156         if (ABCD[2]) { // x == 0 B == 0
157             if (!loadSecond) {// -> !reallyBadAlign
158                 for (i = 0 ; i < h ; i++) {
159                     vsrcCuc = vec_ld(stride + 0, src);
160                     vsrc1uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm0);
161                     CHROMA_MC8_ALTIVEC_CORE_SIMPLE
162
163                     vsrc0uc = vsrc1uc;
164                 }
165             } else {
166                 vec_u8 vsrcDuc;
167                 for (i = 0 ; i < h ; i++) {
168                     vsrcCuc = vec_ld(stride + 0, src);
169                     vsrcDuc = vec_ld(stride + 15, src);
170                     vsrc1uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm0);
171                     CHROMA_MC8_ALTIVEC_CORE_SIMPLE
172
173                     vsrc0uc = vsrc1uc;
174                 }
175             }
176         } else { // y == 0 C == 0
177             if (!loadSecond) {// -> !reallyBadAlign
178                 for (i = 0 ; i < h ; i++) {
179                     vsrcCuc = vec_ld(0, src);
180                     vsrc0uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm0);
181                     vsrc1uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm1);
182
183                     CHROMA_MC8_ALTIVEC_CORE_SIMPLE
184                 }
185             } else {
186                 vec_u8 vsrcDuc;
187                 for (i = 0 ; i < h ; i++) {
188                     vsrcCuc = vec_ld(0, src);
189                     vsrcDuc = vec_ld(15, src);
190                     vsrc0uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm0);
191                     if (reallyBadAlign)
192                         vsrc1uc = vsrcDuc;
193                     else
194                         vsrc1uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm1);
195
196                     CHROMA_MC8_ALTIVEC_CORE_SIMPLE
197                 }
198             }
199         }
200     }
201 }
202 #endif
203
204 /* this code assume that stride % 16 == 0 */
205 #ifdef PREFIX_no_rnd_vc1_chroma_mc8_altivec
206 static void PREFIX_no_rnd_vc1_chroma_mc8_altivec(uint8_t *dst, uint8_t *src,
207                                                  ptrdiff_t stride, int h,
208                                                  int x, int y)
209 {
210    DECLARE_ALIGNED(16, signed int, ABCD)[4] =
211                         {((8 - x) * (8 - y)),
212                          ((    x) * (8 - y)),
213                          ((8 - x) * (    y)),
214                          ((    x) * (    y))};
215     register int i;
216     vec_u8 fperm;
217     const vec_s32 vABCD = vec_ld(0, ABCD);
218     const vec_s16 vA = vec_splat((vec_s16)vABCD, 1);
219     const vec_s16 vB = vec_splat((vec_s16)vABCD, 3);
220     const vec_s16 vC = vec_splat((vec_s16)vABCD, 5);
221     const vec_s16 vD = vec_splat((vec_s16)vABCD, 7);
222     LOAD_ZERO;
223     const vec_s16 v28ss = vec_sub(vec_sl(vec_splat_s16(1),vec_splat_u16(5)),vec_splat_s16(4));
224     const vec_u16 v6us  = vec_splat_u16(6);
225     register int loadSecond     = (((unsigned long)src) % 16) <= 7 ? 0 : 1;
226     register int reallyBadAlign = (((unsigned long)src) % 16) == 15 ? 1 : 0;
227
228     vec_u8 vsrcAuc, av_uninit(vsrcBuc), vsrcperm0, vsrcperm1;
229     vec_u8 vsrc0uc, vsrc1uc;
230     vec_s16 vsrc0ssH, vsrc1ssH;
231     vec_u8 vsrcCuc, vsrc2uc, vsrc3uc;
232     vec_s16 vsrc2ssH, vsrc3ssH, psum;
233     vec_u8 vdst, ppsum, vfdst, fsum;
234
235     if (((unsigned long)dst) % 16 == 0) {
236         fperm = (vec_u8){0x10, 0x11, 0x12, 0x13,
237                          0x14, 0x15, 0x16, 0x17,
238                          0x08, 0x09, 0x0A, 0x0B,
239                          0x0C, 0x0D, 0x0E, 0x0F};
240     } else {
241         fperm = (vec_u8){0x00, 0x01, 0x02, 0x03,
242                          0x04, 0x05, 0x06, 0x07,
243                          0x18, 0x19, 0x1A, 0x1B,
244                          0x1C, 0x1D, 0x1E, 0x1F};
245     }
246
247     vsrcAuc = vec_ld(0, src);
248
249     if (loadSecond)
250         vsrcBuc = vec_ld(16, src);
251     vsrcperm0 = vec_lvsl(0, src);
252     vsrcperm1 = vec_lvsl(1, src);
253
254     vsrc0uc = vec_perm(vsrcAuc, vsrcBuc, vsrcperm0);
255     if (reallyBadAlign)
256         vsrc1uc = vsrcBuc;
257     else
258         vsrc1uc = vec_perm(vsrcAuc, vsrcBuc, vsrcperm1);
259
260     vsrc0ssH = (vec_s16)vec_mergeh(zero_u8v, (vec_u8)vsrc0uc);
261     vsrc1ssH = (vec_s16)vec_mergeh(zero_u8v, (vec_u8)vsrc1uc);
262
263     if (!loadSecond) {// -> !reallyBadAlign
264         for (i = 0 ; i < h ; i++) {
265
266
267             vsrcCuc = vec_ld(stride + 0, src);
268
269             vsrc2uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm0);
270             vsrc3uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm1);
271
272             CHROMA_MC8_ALTIVEC_CORE(vec_splat_s16(0), add28)
273         }
274     } else {
275         vec_u8 vsrcDuc;
276         for (i = 0 ; i < h ; i++) {
277             vsrcCuc = vec_ld(stride + 0, src);
278             vsrcDuc = vec_ld(stride + 16, src);
279
280             vsrc2uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm0);
281             if (reallyBadAlign)
282                 vsrc3uc = vsrcDuc;
283             else
284                 vsrc3uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm1);
285
286             CHROMA_MC8_ALTIVEC_CORE(vec_splat_s16(0), add28)
287         }
288     }
289 }
290 #endif
291
292 #undef noop
293 #undef add28
294 #undef CHROMA_MC8_ALTIVEC_CORE