avcodec/hevc: new idct + asm
[ffmpeg.git] / libavcodec / hevcdsp_template.c
1 /*
2  * HEVC video decoder
3  *
4  * Copyright (C) 2012 - 2013 Guillaume Martres
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 "get_bits.h"
24 #include "hevc.h"
25
26 #include "bit_depth_template.c"
27 #include "hevcdsp.h"
28
29
30 static void FUNC(put_pcm)(uint8_t *_dst, ptrdiff_t stride, int size,
31                           GetBitContext *gb, int pcm_bit_depth)
32 {
33     int x, y;
34     pixel *dst = (pixel *)_dst;
35
36     stride /= sizeof(pixel);
37
38     for (y = 0; y < size; y++) {
39         for (x = 0; x < size; x++)
40             dst[x] = get_bits(gb, pcm_bit_depth) << (BIT_DEPTH - pcm_bit_depth);
41         dst += stride;
42     }
43 }
44
45 static void FUNC(transquant_bypass4x4)(uint8_t *_dst, int16_t *coeffs,
46                                        ptrdiff_t stride)
47 {
48     int x, y;
49     pixel *dst = (pixel *)_dst;
50
51     stride /= sizeof(pixel);
52
53     for (y = 0; y < 4; y++) {
54         for (x = 0; x < 4; x++) {
55             dst[x] = av_clip_pixel(dst[x] + *coeffs);
56             coeffs++;
57         }
58         dst += stride;
59     }
60 }
61
62 static void FUNC(transquant_bypass8x8)(uint8_t *_dst, int16_t *coeffs,
63                                        ptrdiff_t stride)
64 {
65     int x, y;
66     pixel *dst = (pixel *)_dst;
67
68     stride /= sizeof(pixel);
69
70     for (y = 0; y < 8; y++) {
71         for (x = 0; x < 8; x++) {
72             dst[x] = av_clip_pixel(dst[x] + *coeffs);
73             coeffs++;
74         }
75         dst += stride;
76     }
77 }
78
79 static void FUNC(transquant_bypass16x16)(uint8_t *_dst, int16_t *coeffs,
80                                          ptrdiff_t stride)
81 {
82     int x, y;
83     pixel *dst = (pixel *)_dst;
84
85     stride /= sizeof(pixel);
86
87     for (y = 0; y < 16; y++) {
88         for (x = 0; x < 16; x++) {
89             dst[x] = av_clip_pixel(dst[x] + *coeffs);
90             coeffs++;
91         }
92         dst += stride;
93     }
94 }
95
96 static void FUNC(transquant_bypass32x32)(uint8_t *_dst, int16_t *coeffs,
97                                          ptrdiff_t stride)
98 {
99     int x, y;
100     pixel *dst = (pixel *)_dst;
101
102     stride /= sizeof(pixel);
103
104     for (y = 0; y < 32; y++) {
105         for (x = 0; x < 32; x++) {
106             dst[x] = av_clip_pixel(dst[x] + *coeffs);
107             coeffs++;
108         }
109         dst += stride;
110     }
111 }
112
113 static void FUNC(transform_skip)(uint8_t *_dst, int16_t *coeffs,
114                                  ptrdiff_t stride)
115 {
116     pixel *dst = (pixel *)_dst;
117     int shift  = 13 - BIT_DEPTH;
118 #if BIT_DEPTH <= 13
119     int offset = 1 << (shift - 1);
120 #else
121     int offset = 0;
122 #endif
123     int x, y;
124
125     stride /= sizeof(pixel);
126
127     for (y = 0; y < 4 * 4; y += 4) {
128         for (x = 0; x < 4; x++)
129             dst[x] = av_clip_pixel(dst[x] + ((coeffs[y + x] + offset) >> shift));
130         dst += stride;
131     }
132 }
133
134 #define SET(dst, x)   (dst) = (x)
135 #define SCALE(dst, x) (dst) = av_clip_int16(((x) + add) >> shift)
136 #define ADD_AND_SCALE(dst, x)                                           \
137     (dst) = av_clip_pixel((dst) + av_clip_int16(((x) + add) >> shift))
138
139 #define TR_4x4_LUMA(dst, src, step, assign)                             \
140     do {                                                                \
141         int c0 = src[0 * step] + src[2 * step];                         \
142         int c1 = src[2 * step] + src[3 * step];                         \
143         int c2 = src[0 * step] - src[3 * step];                         \
144         int c3 = 74 * src[1 * step];                                    \
145                                                                         \
146         assign(dst[2 * step], 74 * (src[0 * step] -                     \
147                                     src[2 * step] +                     \
148                                     src[3 * step]));                    \
149         assign(dst[0 * step], 29 * c0 + 55 * c1 + c3);                  \
150         assign(dst[1 * step], 55 * c2 - 29 * c1 + c3);                  \
151         assign(dst[3 * step], 55 * c0 + 29 * c2 - c3);                  \
152     } while (0)
153
154 static void FUNC(transform_4x4_luma_add)(uint8_t *_dst, int16_t *coeffs,
155                                          ptrdiff_t stride)
156 {
157     int i;
158     pixel *dst   = (pixel *)_dst;
159     int shift    = 7;
160     int add      = 1 << (shift - 1);
161     int16_t *src = coeffs;
162
163     stride /= sizeof(pixel);
164
165     for (i = 0; i < 4; i++) {
166         TR_4x4_LUMA(src, src, 4, SCALE);
167         src++;
168     }
169
170     shift = 20 - BIT_DEPTH;
171     add   = 1 << (shift - 1);
172     for (i = 0; i < 4; i++) {
173         TR_4x4_LUMA(dst, coeffs, 1, ADD_AND_SCALE);
174         coeffs += 4;
175         dst    += stride;
176     }
177 }
178
179 #undef TR_4x4_LUMA
180
181 #define TR_4(dst, src, dstep, sstep, assign, end)                              \
182     do {                                                                       \
183         const int e0 = 64 * src[0 * sstep] + 64 * src[2 * sstep];              \
184         const int e1 = 64 * src[0 * sstep] - 64 * src[2 * sstep];              \
185         const int o0 = 83 * src[1 * sstep] + 36 * src[3 * sstep];              \
186         const int o1 = 36 * src[1 * sstep] - 83 * src[3 * sstep];              \
187                                                                                \
188         assign(dst[0 * dstep], e0 + o0);                                       \
189         assign(dst[1 * dstep], e1 + o1);                                       \
190         assign(dst[2 * dstep], e1 - o1);                                       \
191         assign(dst[3 * dstep], e0 - o0);                                       \
192     } while (0)
193
194 #define TR_8(dst, src, dstep, sstep, assign, end)                              \
195     do {                                                                       \
196         int i, j;                                                              \
197         int e_8[4];                                                            \
198         int o_8[4] = { 0 };                                                    \
199         for (i = 0; i < 4; i++)                                                \
200             for (j = 1; j < end; j += 2)                                       \
201                 o_8[i] += transform[4 * j][i] * src[j * sstep];                \
202         TR_4(e_8, src, 1, 2 * sstep, SET, 4);                                  \
203                                                                                \
204         for (i = 0; i < 4; i++) {                                              \
205             assign(dst[i * dstep], e_8[i] + o_8[i]);                           \
206             assign(dst[(7 - i) * dstep], e_8[i] - o_8[i]);                     \
207         }                                                                      \
208     } while (0)
209
210 #define TR_16(dst, src, dstep, sstep, assign, end)                             \
211     do {                                                                       \
212         int i, j;                                                              \
213         int e_16[8];                                                           \
214         int o_16[8] = { 0 };                                                   \
215         for (i = 0; i < 8; i++)                                                \
216             for (j = 1; j < end; j += 2)                                       \
217                 o_16[i] += transform[2 * j][i] * src[j * sstep];               \
218         TR_8(e_16, src, 1, 2 * sstep, SET, 8);                                 \
219                                                                                \
220         for (i = 0; i < 8; i++) {                                              \
221             assign(dst[i * dstep], e_16[i] + o_16[i]);                         \
222             assign(dst[(15 - i) * dstep], e_16[i] - o_16[i]);                  \
223         }                                                                      \
224     } while (0)
225
226 #define TR_32(dst, src, dstep, sstep, assign, end)                             \
227     do {                                                                       \
228         int i, j;                                                              \
229         int e_32[16];                                                          \
230         int o_32[16] = { 0 };                                                  \
231         for (i = 0; i < 16; i++)                                               \
232             for (j = 1; j < end; j += 2)                                       \
233                 o_32[i] += transform[j][i] * src[j * sstep];                   \
234         TR_16(e_32, src, 1, 2 * sstep, SET, end/2);                            \
235                                                                                \
236         for (i = 0; i < 16; i++) {                                             \
237             assign(dst[i * dstep], e_32[i] + o_32[i]);                         \
238             assign(dst[(31 - i) * dstep], e_32[i] - o_32[i]);                  \
239         }                                                                      \
240     } while (0)
241
242 #define TRANSFORM_ADD(H)                                                       \
243 static void FUNC(transform_##H ##x ##H ##_add)(                                \
244     uint8_t *_dst, int16_t *coeffs, ptrdiff_t _stride, int col_limit) {        \
245     int i;                                                                     \
246     pixel    *dst    = (pixel *)_dst;                                          \
247     int      stride  = _stride/sizeof(pixel);                                  \
248     int      shift   = 7;                                                      \
249     int      add     = 1 << (shift - 1);                                       \
250     int16_t *src     = coeffs;                                                 \
251     int      limit   = FFMIN(col_limit + 4, H);                                \
252                                                                                \
253     for (i = 0; i < H; i++) {                                                  \
254         TR_ ## H(src, src, H, H, SCALE, limit);                                \
255         if (limit < H && i%4 == 0 && !!i)                                      \
256             limit -= 4;                                                        \
257         src++;                                                                 \
258     }                                                                          \
259     limit   = FFMIN(col_limit, H);                                             \
260                                                                                \
261     shift   = 20 - BIT_DEPTH;                                                  \
262     add     = 1 << (shift - 1);                                                \
263     for (i = 0; i < H; i++) {                                                  \
264         TR_ ## H(dst, coeffs, 1, 1, ADD_AND_SCALE, limit);                     \
265         coeffs += H;                                                           \
266         dst    += stride;                                                      \
267     }                                                                          \
268 }
269
270 #define TRANSFORM_DC_ADD(H)                                                    \
271 static void FUNC(transform_##H ##x ##H ##_dc_add)(                             \
272     uint8_t *_dst, int16_t *coeffs, ptrdiff_t _stride) {                       \
273     int i, j;                                                                  \
274     pixel    *dst    = (pixel *)_dst;                                          \
275     int      stride  = _stride/sizeof(pixel);                                  \
276     int      shift   = 14 - BIT_DEPTH;                                         \
277     int      add     = 1 << (shift - 1);                                       \
278     int      coeff   = (((coeffs[0] + 1) >> 1) + add) >> shift;                \
279                                                                                \
280     for (j = 0; j < H; j++) {                                                  \
281         for (i = 0; i < H; i++) {                                              \
282             dst[i+j*stride] = av_clip_pixel(dst[i+j*stride] + coeff);          \
283         }                                                                      \
284     }                                                                          \
285 }
286
287 TRANSFORM_ADD( 4)
288 TRANSFORM_ADD( 8)
289 TRANSFORM_ADD(16)
290 TRANSFORM_ADD(32)
291
292 TRANSFORM_DC_ADD( 4)
293 TRANSFORM_DC_ADD( 8)
294 TRANSFORM_DC_ADD(16)
295 TRANSFORM_DC_ADD(32)
296
297
298 static void FUNC(sao_band_filter)(uint8_t *_dst, uint8_t *_src,
299                                   ptrdiff_t stride, SAOParams *sao,
300                                   int *borders, int width, int height,
301                                   int c_idx, int class)
302 {
303     pixel *dst = (pixel *)_dst;
304     pixel *src = (pixel *)_src;
305     int offset_table[32] = { 0 };
306     int k, y, x;
307     int chroma = !!c_idx;
308     int shift  = BIT_DEPTH - 5;
309     int *sao_offset_val = sao->offset_val[c_idx];
310     int sao_left_class  = sao->band_position[c_idx];
311     int init_y = 0, init_x = 0;
312
313     stride /= sizeof(pixel);
314
315     switch (class) {
316     case 0:
317         if (!borders[2])
318             width -= (8 >> chroma) + 2;
319         if (!borders[3])
320             height -= (4 >> chroma) + 2;
321         break;
322     case 1:
323         init_y = -(4 >> chroma) - 2;
324         if (!borders[2])
325             width -= (8 >> chroma) + 2;
326         height = (4 >> chroma) + 2;
327         break;
328     case 2:
329         init_x = -(8 >> chroma) - 2;
330         width  =  (8 >> chroma) + 2;
331         if (!borders[3])
332             height -= (4 >> chroma) + 2;
333         break;
334     case 3:
335         init_y = -(4 >> chroma) - 2;
336         init_x = -(8 >> chroma) - 2;
337         width  =  (8 >> chroma) + 2;
338         height =  (4 >> chroma) + 2;
339         break;
340     }
341
342     dst = dst + (init_y * stride + init_x);
343     src = src + (init_y * stride + init_x);
344     for (k = 0; k < 4; k++)
345         offset_table[(k + sao_left_class) & 31] = sao_offset_val[k + 1];
346     for (y = 0; y < height; y++) {
347         for (x = 0; x < width; x++)
348             dst[x] = av_clip_pixel(src[x] + offset_table[src[x] >> shift]);
349         dst += stride;
350         src += stride;
351     }
352 }
353
354 static void FUNC(sao_band_filter_0)(uint8_t *dst, uint8_t *src,
355                                     ptrdiff_t stride, SAOParams *sao,
356                                     int *borders, int width, int height,
357                                     int c_idx)
358 {
359     FUNC(sao_band_filter)(dst, src, stride, sao, borders,
360                           width, height, c_idx, 0);
361 }
362
363 static void FUNC(sao_band_filter_1)(uint8_t *dst, uint8_t *src,
364                                     ptrdiff_t stride, SAOParams *sao,
365                                     int *borders, int width, int height,
366                                     int c_idx)
367 {
368     FUNC(sao_band_filter)(dst, src, stride, sao, borders,
369                           width, height, c_idx, 1);
370 }
371
372 static void FUNC(sao_band_filter_2)(uint8_t *dst, uint8_t *src,
373                                     ptrdiff_t stride, SAOParams *sao,
374                                     int *borders, int width, int height,
375                                     int c_idx)
376 {
377     FUNC(sao_band_filter)(dst, src, stride, sao, borders,
378                           width, height, c_idx, 2);
379 }
380
381 static void FUNC(sao_band_filter_3)(uint8_t *_dst, uint8_t *_src,
382                                     ptrdiff_t stride, SAOParams *sao,
383                                     int *borders, int width, int height,
384                                     int c_idx)
385 {
386     FUNC(sao_band_filter)(_dst, _src, stride, sao, borders,
387                           width, height, c_idx, 3);
388 }
389
390 static void FUNC(sao_edge_filter_0)(uint8_t *_dst, uint8_t *_src,
391                                     ptrdiff_t stride, SAOParams *sao,
392                                     int *borders, int _width, int _height,
393                                     int c_idx, uint8_t vert_edge,
394                                     uint8_t horiz_edge, uint8_t diag_edge)
395 {
396     int x, y;
397     pixel *dst = (pixel *)_dst;
398     pixel *src = (pixel *)_src;
399     int chroma = !!c_idx;
400     int *sao_offset_val = sao->offset_val[c_idx];
401     int sao_eo_class    = sao->eo_class[c_idx];
402     int init_x = 0, init_y = 0, width = _width, height = _height;
403
404     static const int8_t pos[4][2][2] = {
405         { { -1,  0 }, {  1, 0 } }, // horizontal
406         { {  0, -1 }, {  0, 1 } }, // vertical
407         { { -1, -1 }, {  1, 1 } }, // 45 degree
408         { {  1, -1 }, { -1, 1 } }, // 135 degree
409     };
410     static const uint8_t edge_idx[] = { 1, 2, 0, 3, 4 };
411
412 #define CMP(a, b) ((a) > (b) ? 1 : ((a) == (b) ? 0 : -1))
413
414     stride /= sizeof(pixel);
415
416     if (!borders[2])
417         width -= (8 >> chroma) + 2;
418     if (!borders[3])
419         height -= (4 >> chroma) + 2;
420
421     dst = dst + (init_y * stride + init_x);
422     src = src + (init_y * stride + init_x);
423     init_y = init_x = 0;
424     if (sao_eo_class != SAO_EO_VERT) {
425         if (borders[0]) {
426             int offset_val = sao_offset_val[0];
427             int y_stride   = 0;
428             for (y = 0; y < height; y++) {
429                 dst[y_stride] = av_clip_pixel(src[y_stride] + offset_val);
430                 y_stride     += stride;
431             }
432             init_x = 1;
433         }
434         if (borders[2]) {
435             int offset_val = sao_offset_val[0];
436             int x_stride   = width - 1;
437             for (x = 0; x < height; x++) {
438                 dst[x_stride] = av_clip_pixel(src[x_stride] + offset_val);
439                 x_stride     += stride;
440             }
441             width--;
442         }
443     }
444     if (sao_eo_class != SAO_EO_HORIZ) {
445         if (borders[1]) {
446             int offset_val = sao_offset_val[0];
447             for (x = init_x; x < width; x++)
448                 dst[x] = av_clip_pixel(src[x] + offset_val);
449             init_y = 1;
450         }
451         if (borders[3]) {
452             int offset_val = sao_offset_val[0];
453             int y_stride   = stride * (height - 1);
454             for (x = init_x; x < width; x++)
455                 dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + offset_val);
456             height--;
457         }
458     }
459     {
460         int y_stride = init_y * stride;
461         int pos_0_0  = pos[sao_eo_class][0][0];
462         int pos_0_1  = pos[sao_eo_class][0][1];
463         int pos_1_0  = pos[sao_eo_class][1][0];
464         int pos_1_1  = pos[sao_eo_class][1][1];
465
466         int y_stride_0_1 = (init_y + pos_0_1) * stride;
467         int y_stride_1_1 = (init_y + pos_1_1) * stride;
468         for (y = init_y; y < height; y++) {
469             for (x = init_x; x < width; x++) {
470                 int diff0         = CMP(src[x + y_stride], src[x + pos_0_0 + y_stride_0_1]);
471                 int diff1         = CMP(src[x + y_stride], src[x + pos_1_0 + y_stride_1_1]);
472                 int offset_val    = edge_idx[2 + diff0 + diff1];
473                 dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + sao_offset_val[offset_val]);
474             }
475             y_stride     += stride;
476             y_stride_0_1 += stride;
477             y_stride_1_1 += stride;
478         }
479     }
480
481     {
482         // Restore pixels that can't be modified
483         int save_upper_left = !diag_edge && sao_eo_class == SAO_EO_135D && !borders[0] && !borders[1];
484         if (vert_edge && sao_eo_class != SAO_EO_VERT)
485             for (y = init_y+save_upper_left; y< height; y++)
486                 dst[y*stride] = src[y*stride];
487         if(horiz_edge && sao_eo_class != SAO_EO_HORIZ)
488             for(x = init_x+save_upper_left; x<width; x++)
489                 dst[x] = src[x];
490         if(diag_edge && sao_eo_class == SAO_EO_135D)
491             dst[0] = src[0];
492     }
493
494 #undef CMP
495 }
496
497 static void FUNC(sao_edge_filter_1)(uint8_t *_dst, uint8_t *_src,
498                                     ptrdiff_t stride, SAOParams *sao,
499                                     int *borders, int _width, int _height,
500                                     int c_idx, uint8_t vert_edge,
501                                     uint8_t horiz_edge, uint8_t diag_edge)
502 {
503     int x, y;
504     pixel *dst = (pixel *)_dst;
505     pixel *src = (pixel *)_src;
506     int chroma = !!c_idx;
507     int *sao_offset_val = sao->offset_val[c_idx];
508     int sao_eo_class    = sao->eo_class[c_idx];
509     int init_x = 0, init_y = 0, width = _width, height = _height;
510
511     static const int8_t pos[4][2][2] = {
512         { { -1, 0  }, { 1,  0 } }, // horizontal
513         { { 0,  -1 }, { 0,  1 } }, // vertical
514         { { -1, -1 }, { 1,  1 } }, // 45 degree
515         { { 1,  -1 }, { -1, 1 } }, // 135 degree
516     };
517     static const uint8_t edge_idx[] = { 1, 2, 0, 3, 4 };
518
519 #define CMP(a, b) ((a) > (b) ? 1 : ((a) == (b) ? 0 : -1))
520
521     stride /= sizeof(pixel);
522
523     init_y = -(4 >> chroma) - 2;
524     if (!borders[2])
525         width -= (8 >> chroma) + 2;
526     height = (4 >> chroma) + 2;
527
528     dst = dst + (init_y * stride + init_x);
529     src = src + (init_y * stride + init_x);
530     init_y = init_x = 0;
531     if (sao_eo_class != SAO_EO_VERT) {
532         if (borders[0]) {
533             int offset_val = sao_offset_val[0];
534             int y_stride   = 0;
535             for (y = 0; y < height; y++) {
536                 dst[y_stride] = av_clip_pixel(src[y_stride] + offset_val);
537                 y_stride     += stride;
538             }
539             init_x = 1;
540         }
541         if (borders[2]) {
542             int offset_val = sao_offset_val[0];
543             int x_stride   = width - 1;
544             for (x = 0; x < height; x++) {
545                 dst[x_stride] = av_clip_pixel(src[x_stride] + offset_val);
546                 x_stride     += stride;
547             }
548             width--;
549         }
550     }
551     {
552         int y_stride = init_y * stride;
553         int pos_0_0  = pos[sao_eo_class][0][0];
554         int pos_0_1  = pos[sao_eo_class][0][1];
555         int pos_1_0  = pos[sao_eo_class][1][0];
556         int pos_1_1  = pos[sao_eo_class][1][1];
557
558         int y_stride_0_1 = (init_y + pos_0_1) * stride;
559         int y_stride_1_1 = (init_y + pos_1_1) * stride;
560         for (y = init_y; y < height; y++) {
561             for (x = init_x; x < width; x++) {
562                 int diff0         = CMP(src[x + y_stride], src[x + pos_0_0 + y_stride_0_1]);
563                 int diff1         = CMP(src[x + y_stride], src[x + pos_1_0 + y_stride_1_1]);
564                 int offset_val    = edge_idx[2 + diff0 + diff1];
565                 dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + sao_offset_val[offset_val]);
566             }
567             y_stride     += stride;
568             y_stride_0_1 += stride;
569             y_stride_1_1 += stride;
570         }
571     }
572
573     {
574         // Restore pixels that can't be modified
575         int save_lower_left = !diag_edge && sao_eo_class == SAO_EO_45D && !borders[0];
576         if(vert_edge && sao_eo_class != SAO_EO_VERT)
577             for(y = init_y; y< height-save_lower_left; y++)
578                 dst[y*stride] = src[y*stride];
579         if(horiz_edge && sao_eo_class != SAO_EO_HORIZ)
580             for(x = init_x+save_lower_left; x<width; x++)
581                 dst[(height-1)*stride+x] = src[(height-1)*stride+x];
582         if(diag_edge && sao_eo_class == SAO_EO_45D)
583             dst[stride*(height-1)] = src[stride*(height-1)];
584     }
585
586 #undef CMP
587 }
588
589 static void FUNC(sao_edge_filter_2)(uint8_t *_dst, uint8_t *_src,
590                                     ptrdiff_t stride, SAOParams *sao,
591                                     int *borders, int _width, int _height,
592                                     int c_idx, uint8_t vert_edge,
593                                     uint8_t horiz_edge, uint8_t diag_edge)
594 {
595     int x, y;
596     pixel *dst = (pixel *)_dst;
597     pixel *src = (pixel *)_src;
598     int chroma = !!c_idx;
599     int *sao_offset_val = sao->offset_val[c_idx];
600     int sao_eo_class    = sao->eo_class[c_idx];
601     int init_x = 0, init_y = 0, width = _width, height = _height;
602
603     static const int8_t pos[4][2][2] = {
604         { { -1,  0 }, {  1, 0 } }, // horizontal
605         { {  0, -1 }, {  0, 1 } }, // vertical
606         { { -1, -1 }, {  1, 1 } }, // 45 degree
607         { {  1, -1 }, { -1, 1 } }, // 135 degree
608     };
609     static const uint8_t edge_idx[] = { 1, 2, 0, 3, 4 };
610
611 #define CMP(a, b) ((a) > (b) ? 1 : ((a) == (b) ? 0 : -1))
612
613     stride /= sizeof(pixel);
614
615     init_x = -(8 >> chroma) - 2;
616     width  =  (8 >> chroma) + 2;
617     if (!borders[3])
618         height -= (4 >> chroma) + 2;
619
620     dst = dst + (init_y * stride + init_x);
621     src = src + (init_y * stride + init_x);
622     init_y = init_x = 0;
623     if (sao_eo_class != SAO_EO_HORIZ) {
624         if (borders[1]) {
625             int offset_val = sao_offset_val[0];
626             for (x = init_x; x < width; x++)
627                 dst[x] = av_clip_pixel(src[x] + offset_val);
628             init_y = 1;
629         }
630         if (borders[3]) {
631             int offset_val = sao_offset_val[0];
632             int y_stride   = stride * (height - 1);
633             for (x = init_x; x < width; x++)
634                 dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + offset_val);
635             height--;
636         }
637     }
638     {
639         int y_stride = init_y * stride;
640         int pos_0_0  = pos[sao_eo_class][0][0];
641         int pos_0_1  = pos[sao_eo_class][0][1];
642         int pos_1_0  = pos[sao_eo_class][1][0];
643         int pos_1_1  = pos[sao_eo_class][1][1];
644
645         int y_stride_0_1 = (init_y + pos_0_1) * stride;
646         int y_stride_1_1 = (init_y + pos_1_1) * stride;
647         for (y = init_y; y < height; y++) {
648             for (x = init_x; x < width; x++) {
649                 int diff0         = CMP(src[x + y_stride], src[x + pos_0_0 + y_stride_0_1]);
650                 int diff1         = CMP(src[x + y_stride], src[x + pos_1_0 + y_stride_1_1]);
651                 int offset_val    = edge_idx[2 + diff0 + diff1];
652                 dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + sao_offset_val[offset_val]);
653             }
654             y_stride     += stride;
655             y_stride_0_1 += stride;
656             y_stride_1_1 += stride;
657         }
658     }
659
660     {
661         // Restore pixels that can't be modified
662         int save_upper_right = !diag_edge && sao_eo_class == SAO_EO_45D && !borders[1];
663         if(vert_edge && sao_eo_class != SAO_EO_VERT)
664             for(y = init_y+save_upper_right; y< height; y++)
665                 dst[y*stride+width-1] = src[y*stride+width-1];
666         if(horiz_edge && sao_eo_class != SAO_EO_HORIZ)
667             for(x = init_x; x<width-save_upper_right; x++)
668                 dst[x] = src[x];
669         if(diag_edge && sao_eo_class == SAO_EO_45D)
670             dst[width-1] = src[width-1];
671     }
672 #undef CMP
673 }
674
675 static void FUNC(sao_edge_filter_3)(uint8_t *_dst, uint8_t *_src,
676                                     ptrdiff_t stride, SAOParams *sao,
677                                     int *borders, int _width, int _height,
678                                     int c_idx, uint8_t vert_edge,
679                                     uint8_t horiz_edge, uint8_t diag_edge)
680 {
681     int x, y;
682     pixel *dst = (pixel *)_dst;
683     pixel *src = (pixel *)_src;
684     int chroma = !!c_idx;
685     int *sao_offset_val = sao->offset_val[c_idx];
686     int sao_eo_class    = sao->eo_class[c_idx];
687     int init_x = 0, init_y = 0, width = _width, height = _height;
688
689     static const int8_t pos[4][2][2] = {
690         { { -1,  0 }, {  1, 0 } }, // horizontal
691         { {  0, -1 }, {  0, 1 } }, // vertical
692         { { -1, -1 }, {  1, 1 } }, // 45 degree
693         { {  1, -1 }, { -1, 1 } }, // 135 degree
694     };
695     static const uint8_t edge_idx[] = { 1, 2, 0, 3, 4 };
696
697 #define CMP(a, b) ((a) > (b) ? 1 : ((a) == (b) ? 0 : -1))
698
699     stride /= sizeof(pixel);
700
701     init_y = -(4 >> chroma) - 2;
702     init_x = -(8 >> chroma) - 2;
703     width  =  (8 >> chroma) + 2;
704     height =  (4 >> chroma) + 2;
705
706
707     dst    = dst + (init_y * stride + init_x);
708     src    = src + (init_y * stride + init_x);
709     init_y = init_x = 0;
710
711     {
712         int y_stride = init_y * stride;
713         int pos_0_0  = pos[sao_eo_class][0][0];
714         int pos_0_1  = pos[sao_eo_class][0][1];
715         int pos_1_0  = pos[sao_eo_class][1][0];
716         int pos_1_1  = pos[sao_eo_class][1][1];
717
718         int y_stride_0_1 = (init_y + pos_0_1) * stride;
719         int y_stride_1_1 = (init_y + pos_1_1) * stride;
720
721         for (y = init_y; y < height; y++) {
722             for (x = init_x; x < width; x++) {
723                 int diff0         = CMP(src[x + y_stride], src[x + pos_0_0 + y_stride_0_1]);
724                 int diff1         = CMP(src[x + y_stride], src[x + pos_1_0 + y_stride_1_1]);
725                 int offset_val    = edge_idx[2 + diff0 + diff1];
726                 dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + sao_offset_val[offset_val]);
727             }
728             y_stride     += stride;
729             y_stride_0_1 += stride;
730             y_stride_1_1 += stride;
731         }
732     }
733
734     {
735         // Restore pixels that can't be modified
736         int save_lower_right = !diag_edge && sao_eo_class == SAO_EO_135D;
737         if(vert_edge && sao_eo_class != SAO_EO_VERT)
738             for(y = init_y; y< height-save_lower_right; y++)
739                 dst[y*stride+width-1] = src[y*stride+width-1];
740         if(horiz_edge && sao_eo_class != SAO_EO_HORIZ)
741             for(x = init_x; x<width-save_lower_right; x++)
742                 dst[(height-1)*stride+x] = src[(height-1)*stride+x];
743         if(diag_edge && sao_eo_class == SAO_EO_135D)
744             dst[stride*(height-1)+width-1] = src[stride*(height-1)+width-1];
745     }
746 #undef CMP
747 }
748
749 #undef SET
750 #undef SCALE
751 #undef ADD_AND_SCALE
752 #undef TR_4
753 #undef TR_8
754 #undef TR_16
755 #undef TR_32
756
757
758 ////////////////////////////////////////////////////////////////////////////////
759 //
760 ////////////////////////////////////////////////////////////////////////////////
761 static void FUNC(put_hevc_pel_pixels)(int16_t *dst, ptrdiff_t dststride,
762                                       uint8_t *_src, ptrdiff_t _srcstride,
763                                       int height, intptr_t mx, intptr_t my, int width)
764 {
765     int x, y;
766     pixel *src          = (pixel *)_src;
767     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
768
769     for (y = 0; y < height; y++) {
770         for (x = 0; x < width; x++)
771             dst[x] = src[x] << (14 - BIT_DEPTH);
772         src += srcstride;
773         dst += dststride;
774     }
775 }
776
777 static void FUNC(put_hevc_pel_uni_pixels)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
778                                           int height, intptr_t mx, intptr_t my, int width)
779 {
780     int y;
781     pixel *src          = (pixel *)_src;
782     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
783     pixel *dst          = (pixel *)_dst;
784     ptrdiff_t dststride = _dststride / sizeof(pixel);
785
786     for (y = 0; y < height; y++) {
787         memcpy(dst, src, width * sizeof(pixel));
788         src += srcstride;
789         dst += dststride;
790     }
791 }
792
793 static void FUNC(put_hevc_pel_bi_pixels)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
794                                          int16_t *src2, ptrdiff_t src2stride,
795                                          int height, intptr_t mx, intptr_t my, int width)
796 {
797     int x, y;
798     pixel *src          = (pixel *)_src;
799     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
800     pixel *dst          = (pixel *)_dst;
801     ptrdiff_t dststride = _dststride / sizeof(pixel);
802
803     int shift = 14  + 1 - BIT_DEPTH;
804 #if BIT_DEPTH < 14
805     int offset = 1 << (shift - 1);
806 #else
807     int offset = 0;
808 #endif
809
810     for (y = 0; y < height; y++) {
811         for (x = 0; x < width; x++)
812             dst[x] = av_clip_pixel(((src[x] << (14 - BIT_DEPTH)) + src2[x] + offset) >> shift);
813         src  += srcstride;
814         dst  += dststride;
815         src2 += src2stride;
816     }
817 }
818
819 static void FUNC(put_hevc_pel_uni_w_pixels)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
820                                             int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width)
821 {
822     int x, y;
823     pixel *src          = (pixel *)_src;
824     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
825     pixel *dst          = (pixel *)_dst;
826     ptrdiff_t dststride = _dststride / sizeof(pixel);
827     int shift = denom + 14 - BIT_DEPTH;
828 #if BIT_DEPTH < 14
829     int offset = 1 << (shift - 1);
830 #else
831     int offset = 0;
832 #endif
833
834     ox     = ox * (1 << (BIT_DEPTH - 8));
835     for (y = 0; y < height; y++) {
836         for (x = 0; x < width; x++)
837             dst[x] = av_clip_pixel((((src[x] << (14 - BIT_DEPTH)) * wx + offset) >> shift) + ox);
838         src += srcstride;
839         dst += dststride;
840     }
841 }
842
843 static void FUNC(put_hevc_pel_bi_w_pixels)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
844                                            int16_t *src2, ptrdiff_t src2stride,
845                                            int height, int denom, int wx0, int wx1,
846                                            int ox0, int ox1, intptr_t mx, intptr_t my, int width)
847 {
848     int x, y;
849     pixel *src          = (pixel *)_src;
850     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
851     pixel *dst          = (pixel *)_dst;
852     ptrdiff_t dststride = _dststride / sizeof(pixel);
853
854     int shift = 14  + 1 - BIT_DEPTH;
855     int log2Wd = denom + shift - 1;
856
857     ox0     = ox0 * (1 << (BIT_DEPTH - 8));
858     ox1     = ox1 * (1 << (BIT_DEPTH - 8));
859     for (y = 0; y < height; y++) {
860         for (x = 0; x < width; x++) {
861             dst[x] = av_clip_pixel(( (src[x] << (14 - BIT_DEPTH)) * wx1 + src2[x] * wx0 + ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1));
862         }
863         src  += srcstride;
864         dst  += dststride;
865         src2 += src2stride;
866     }
867 }
868
869 ////////////////////////////////////////////////////////////////////////////////
870 //
871 ////////////////////////////////////////////////////////////////////////////////
872 #define QPEL_FILTER(src, stride)                                               \
873     (filter[0] * src[x - 3 * stride] +                                         \
874      filter[1] * src[x - 2 * stride] +                                         \
875      filter[2] * src[x -     stride] +                                         \
876      filter[3] * src[x             ] +                                         \
877      filter[4] * src[x +     stride] +                                         \
878      filter[5] * src[x + 2 * stride] +                                         \
879      filter[6] * src[x + 3 * stride] +                                         \
880      filter[7] * src[x + 4 * stride])
881
882 static void FUNC(put_hevc_qpel_h)(int16_t *dst,  ptrdiff_t dststride,
883                                   uint8_t *_src, ptrdiff_t _srcstride,
884                                   int height, intptr_t mx, intptr_t my, int width)
885 {
886     int x, y;
887     pixel        *src       = (pixel*)_src;
888     ptrdiff_t     srcstride = _srcstride / sizeof(pixel);
889     const int8_t *filter    = ff_hevc_qpel_filters[mx - 1];
890     for (y = 0; y < height; y++) {
891         for (x = 0; x < width; x++)
892             dst[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8);
893         src += srcstride;
894         dst += dststride;
895     }
896 }
897
898 static void FUNC(put_hevc_qpel_v)(int16_t *dst,  ptrdiff_t dststride,
899                                   uint8_t *_src, ptrdiff_t _srcstride,
900                                   int height, intptr_t mx, intptr_t my, int width)
901 {
902     int x, y;
903     pixel        *src       = (pixel*)_src;
904     ptrdiff_t     srcstride = _srcstride / sizeof(pixel);
905     const int8_t *filter    = ff_hevc_qpel_filters[my - 1];
906     for (y = 0; y < height; y++)  {
907         for (x = 0; x < width; x++)
908             dst[x] = QPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8);
909         src += srcstride;
910         dst += dststride;
911     }
912 }
913
914 static void FUNC(put_hevc_qpel_hv)(int16_t *dst,
915                                    ptrdiff_t dststride,
916                                    uint8_t *_src,
917                                    ptrdiff_t _srcstride,
918                                    int height, intptr_t mx,
919                                    intptr_t my, int width)
920 {
921     int x, y;
922     const int8_t *filter;
923     pixel *src = (pixel*)_src;
924     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
925     int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE];
926     int16_t *tmp = tmp_array;
927
928     src   -= QPEL_EXTRA_BEFORE * srcstride;
929     filter = ff_hevc_qpel_filters[mx - 1];
930     for (y = 0; y < height + QPEL_EXTRA; y++) {
931         for (x = 0; x < width; x++)
932             tmp[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8);
933         src += srcstride;
934         tmp += MAX_PB_SIZE;
935     }
936
937     tmp    = tmp_array + QPEL_EXTRA_BEFORE * MAX_PB_SIZE;
938     filter = ff_hevc_qpel_filters[my - 1];
939     for (y = 0; y < height; y++) {
940         for (x = 0; x < width; x++)
941             dst[x] = QPEL_FILTER(tmp, MAX_PB_SIZE) >> 6;
942         tmp += MAX_PB_SIZE;
943         dst += dststride;
944     }
945 }
946
947 static void FUNC(put_hevc_qpel_uni_h)(uint8_t *_dst,  ptrdiff_t _dststride,
948                                       uint8_t *_src, ptrdiff_t _srcstride,
949                                       int height, intptr_t mx, intptr_t my, int width)
950 {
951     int x, y;
952     pixel        *src       = (pixel*)_src;
953     ptrdiff_t     srcstride = _srcstride / sizeof(pixel);
954     pixel *dst          = (pixel *)_dst;
955     ptrdiff_t dststride = _dststride / sizeof(pixel);
956     const int8_t *filter    = ff_hevc_qpel_filters[mx - 1];
957     int shift = 14 - BIT_DEPTH;
958
959 #if BIT_DEPTH < 14
960     int offset = 1 << (shift - 1);
961 #else
962     int offset = 0;
963 #endif
964
965     for (y = 0; y < height; y++) {
966         for (x = 0; x < width; x++)
967             dst[x] = av_clip_pixel(((QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) + offset) >> shift);
968         src += srcstride;
969         dst += dststride;
970     }
971 }
972
973 static void FUNC(put_hevc_qpel_bi_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
974                                      int16_t *src2, ptrdiff_t src2stride,
975                                      int height, intptr_t mx, intptr_t my, int width)
976 {
977     int x, y;
978     pixel        *src       = (pixel*)_src;
979     ptrdiff_t     srcstride = _srcstride / sizeof(pixel);
980     pixel *dst          = (pixel *)_dst;
981     ptrdiff_t dststride = _dststride / sizeof(pixel);
982
983     const int8_t *filter    = ff_hevc_qpel_filters[mx - 1];
984
985     int shift = 14  + 1 - BIT_DEPTH;
986 #if BIT_DEPTH < 14
987     int offset = 1 << (shift - 1);
988 #else
989     int offset = 0;
990 #endif
991
992     for (y = 0; y < height; y++) {
993         for (x = 0; x < width; x++)
994             dst[x] = av_clip_pixel(((QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) + src2[x] + offset) >> shift);
995         src  += srcstride;
996         dst  += dststride;
997         src2 += src2stride;
998     }
999 }
1000
1001 static void FUNC(put_hevc_qpel_uni_v)(uint8_t *_dst,  ptrdiff_t _dststride,
1002                                      uint8_t *_src, ptrdiff_t _srcstride,
1003                                      int height, intptr_t mx, intptr_t my, int width)
1004 {
1005     int x, y;
1006     pixel        *src       = (pixel*)_src;
1007     ptrdiff_t     srcstride = _srcstride / sizeof(pixel);
1008     pixel *dst          = (pixel *)_dst;
1009     ptrdiff_t dststride = _dststride / sizeof(pixel);
1010     const int8_t *filter    = ff_hevc_qpel_filters[my - 1];
1011     int shift = 14 - BIT_DEPTH;
1012
1013 #if BIT_DEPTH < 14
1014     int offset = 1 << (shift - 1);
1015 #else
1016     int offset = 0;
1017 #endif
1018
1019     for (y = 0; y < height; y++) {
1020         for (x = 0; x < width; x++)
1021             dst[x] = av_clip_pixel(((QPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) + offset) >> shift);
1022         src += srcstride;
1023         dst += dststride;
1024     }
1025 }
1026
1027
1028 static void FUNC(put_hevc_qpel_bi_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1029                                      int16_t *src2, ptrdiff_t src2stride,
1030                                      int height, intptr_t mx, intptr_t my, int width)
1031 {
1032     int x, y;
1033     pixel        *src       = (pixel*)_src;
1034     ptrdiff_t     srcstride = _srcstride / sizeof(pixel);
1035     pixel *dst          = (pixel *)_dst;
1036     ptrdiff_t dststride = _dststride / sizeof(pixel);
1037
1038     const int8_t *filter    = ff_hevc_qpel_filters[my - 1];
1039
1040     int shift = 14 + 1 - BIT_DEPTH;
1041 #if BIT_DEPTH < 14
1042     int offset = 1 << (shift - 1);
1043 #else
1044     int offset = 0;
1045 #endif
1046
1047     for (y = 0; y < height; y++) {
1048         for (x = 0; x < width; x++)
1049             dst[x] = av_clip_pixel(((QPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) + src2[x] + offset) >> shift);
1050         src  += srcstride;
1051         dst  += dststride;
1052         src2 += src2stride;
1053     }
1054 }
1055
1056 static void FUNC(put_hevc_qpel_uni_hv)(uint8_t *_dst,  ptrdiff_t _dststride,
1057                                        uint8_t *_src, ptrdiff_t _srcstride,
1058                                        int height, intptr_t mx, intptr_t my, int width)
1059 {
1060     int x, y;
1061     const int8_t *filter;
1062     pixel *src = (pixel*)_src;
1063     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
1064     pixel *dst          = (pixel *)_dst;
1065     ptrdiff_t dststride = _dststride / sizeof(pixel);
1066     int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE];
1067     int16_t *tmp = tmp_array;
1068     int shift =  14 - BIT_DEPTH;
1069
1070 #if BIT_DEPTH < 14
1071     int offset = 1 << (shift - 1);
1072 #else
1073     int offset = 0;
1074 #endif
1075
1076     src   -= QPEL_EXTRA_BEFORE * srcstride;
1077     filter = ff_hevc_qpel_filters[mx - 1];
1078     for (y = 0; y < height + QPEL_EXTRA; y++) {
1079         for (x = 0; x < width; x++)
1080             tmp[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8);
1081         src += srcstride;
1082         tmp += MAX_PB_SIZE;
1083     }
1084
1085     tmp    = tmp_array + QPEL_EXTRA_BEFORE * MAX_PB_SIZE;
1086     filter = ff_hevc_qpel_filters[my - 1];
1087
1088     for (y = 0; y < height; y++) {
1089         for (x = 0; x < width; x++)
1090             dst[x] = av_clip_pixel(((QPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) + offset) >> shift);
1091         tmp += MAX_PB_SIZE;
1092         dst += dststride;
1093     }
1094 }
1095
1096 static void FUNC(put_hevc_qpel_bi_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1097                                       int16_t *src2, ptrdiff_t src2stride,
1098                                       int height, intptr_t mx, intptr_t my, int width)
1099 {
1100     int x, y;
1101     const int8_t *filter;
1102     pixel *src = (pixel*)_src;
1103     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
1104     pixel *dst          = (pixel *)_dst;
1105     ptrdiff_t dststride = _dststride / sizeof(pixel);
1106     int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE];
1107     int16_t *tmp = tmp_array;
1108     int shift = 14 + 1 - BIT_DEPTH;
1109 #if BIT_DEPTH < 14
1110     int offset = 1 << (shift - 1);
1111 #else
1112     int offset = 0;
1113 #endif
1114
1115     src   -= QPEL_EXTRA_BEFORE * srcstride;
1116     filter = ff_hevc_qpel_filters[mx - 1];
1117     for (y = 0; y < height + QPEL_EXTRA; y++) {
1118         for (x = 0; x < width; x++)
1119             tmp[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8);
1120         src += srcstride;
1121         tmp += MAX_PB_SIZE;
1122     }
1123
1124     tmp    = tmp_array + QPEL_EXTRA_BEFORE * MAX_PB_SIZE;
1125     filter = ff_hevc_qpel_filters[my - 1];
1126
1127     for (y = 0; y < height; y++) {
1128         for (x = 0; x < width; x++)
1129             dst[x] = av_clip_pixel(((QPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) + src2[x] + offset) >> shift);
1130         tmp  += MAX_PB_SIZE;
1131         dst  += dststride;
1132         src2 += src2stride;
1133     }
1134 }
1135
1136 static void FUNC(put_hevc_qpel_uni_w_h)(uint8_t *_dst,  ptrdiff_t _dststride,
1137                                         uint8_t *_src, ptrdiff_t _srcstride,
1138                                         int height, int denom, int wx, int ox,
1139                                         intptr_t mx, intptr_t my, int width)
1140 {
1141     int x, y;
1142     pixel        *src       = (pixel*)_src;
1143     ptrdiff_t     srcstride = _srcstride / sizeof(pixel);
1144     pixel *dst          = (pixel *)_dst;
1145     ptrdiff_t dststride = _dststride / sizeof(pixel);
1146     const int8_t *filter    = ff_hevc_qpel_filters[mx - 1];
1147     int shift = denom + 14 - BIT_DEPTH;
1148 #if BIT_DEPTH < 14
1149     int offset = 1 << (shift - 1);
1150 #else
1151     int offset = 0;
1152 #endif
1153
1154     ox = ox * (1 << (BIT_DEPTH - 8));
1155     for (y = 0; y < height; y++) {
1156         for (x = 0; x < width; x++)
1157             dst[x] = av_clip_pixel((((QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) * wx + offset) >> shift) + ox);
1158         src += srcstride;
1159         dst += dststride;
1160     }
1161 }
1162
1163 static void FUNC(put_hevc_qpel_bi_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1164                                        int16_t *src2, ptrdiff_t src2stride,
1165                                        int height, int denom, int wx0, int wx1,
1166                                        int ox0, int ox1, intptr_t mx, intptr_t my, int width)
1167 {
1168     int x, y;
1169     pixel        *src       = (pixel*)_src;
1170     ptrdiff_t     srcstride = _srcstride / sizeof(pixel);
1171     pixel *dst          = (pixel *)_dst;
1172     ptrdiff_t dststride = _dststride / sizeof(pixel);
1173
1174     const int8_t *filter    = ff_hevc_qpel_filters[mx - 1];
1175
1176     int shift = 14  + 1 - BIT_DEPTH;
1177     int log2Wd = denom + shift - 1;
1178
1179     ox0     = ox0 * (1 << (BIT_DEPTH - 8));
1180     ox1     = ox1 * (1 << (BIT_DEPTH - 8));
1181     for (y = 0; y < height; y++) {
1182         for (x = 0; x < width; x++)
1183             dst[x] = av_clip_pixel(((QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) * wx1 + src2[x] * wx0 +
1184                                     ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1));
1185         src  += srcstride;
1186         dst  += dststride;
1187         src2 += src2stride;
1188     }
1189 }
1190
1191 static void FUNC(put_hevc_qpel_uni_w_v)(uint8_t *_dst,  ptrdiff_t _dststride,
1192                                         uint8_t *_src, ptrdiff_t _srcstride,
1193                                         int height, int denom, int wx, int ox,
1194                                         intptr_t mx, intptr_t my, int width)
1195 {
1196     int x, y;
1197     pixel        *src       = (pixel*)_src;
1198     ptrdiff_t     srcstride = _srcstride / sizeof(pixel);
1199     pixel *dst          = (pixel *)_dst;
1200     ptrdiff_t dststride = _dststride / sizeof(pixel);
1201     const int8_t *filter    = ff_hevc_qpel_filters[my - 1];
1202     int shift = denom + 14 - BIT_DEPTH;
1203 #if BIT_DEPTH < 14
1204     int offset = 1 << (shift - 1);
1205 #else
1206     int offset = 0;
1207 #endif
1208
1209     ox = ox * (1 << (BIT_DEPTH - 8));
1210     for (y = 0; y < height; y++) {
1211         for (x = 0; x < width; x++)
1212             dst[x] = av_clip_pixel((((QPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) * wx + offset) >> shift) + ox);
1213         src += srcstride;
1214         dst += dststride;
1215     }
1216 }
1217
1218 static void FUNC(put_hevc_qpel_bi_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1219                                        int16_t *src2, ptrdiff_t src2stride,
1220                                        int height, int denom, int wx0, int wx1,
1221                                        int ox0, int ox1, intptr_t mx, intptr_t my, int width)
1222 {
1223     int x, y;
1224     pixel        *src       = (pixel*)_src;
1225     ptrdiff_t     srcstride = _srcstride / sizeof(pixel);
1226     pixel *dst          = (pixel *)_dst;
1227     ptrdiff_t dststride = _dststride / sizeof(pixel);
1228
1229     const int8_t *filter    = ff_hevc_qpel_filters[my - 1];
1230
1231     int shift = 14 + 1 - BIT_DEPTH;
1232     int log2Wd = denom + shift - 1;
1233
1234     ox0     = ox0 * (1 << (BIT_DEPTH - 8));
1235     ox1     = ox1 * (1 << (BIT_DEPTH - 8));
1236     for (y = 0; y < height; y++) {
1237         for (x = 0; x < width; x++)
1238             dst[x] = av_clip_pixel(((QPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) * wx1 + src2[x] * wx0 +
1239                                     ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1));
1240         src  += srcstride;
1241         dst  += dststride;
1242         src2 += src2stride;
1243     }
1244 }
1245
1246 static void FUNC(put_hevc_qpel_uni_w_hv)(uint8_t *_dst,  ptrdiff_t _dststride,
1247                                          uint8_t *_src, ptrdiff_t _srcstride,
1248                                          int height, int denom, int wx, int ox,
1249                                          intptr_t mx, intptr_t my, int width)
1250 {
1251     int x, y;
1252     const int8_t *filter;
1253     pixel *src = (pixel*)_src;
1254     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
1255     pixel *dst          = (pixel *)_dst;
1256     ptrdiff_t dststride = _dststride / sizeof(pixel);
1257     int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE];
1258     int16_t *tmp = tmp_array;
1259     int shift = denom + 14 - BIT_DEPTH;
1260 #if BIT_DEPTH < 14
1261     int offset = 1 << (shift - 1);
1262 #else
1263     int offset = 0;
1264 #endif
1265
1266     src   -= QPEL_EXTRA_BEFORE * srcstride;
1267     filter = ff_hevc_qpel_filters[mx - 1];
1268     for (y = 0; y < height + QPEL_EXTRA; y++) {
1269         for (x = 0; x < width; x++)
1270             tmp[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8);
1271         src += srcstride;
1272         tmp += MAX_PB_SIZE;
1273     }
1274
1275     tmp    = tmp_array + QPEL_EXTRA_BEFORE * MAX_PB_SIZE;
1276     filter = ff_hevc_qpel_filters[my - 1];
1277
1278     ox = ox * (1 << (BIT_DEPTH - 8));
1279     for (y = 0; y < height; y++) {
1280         for (x = 0; x < width; x++)
1281             dst[x] = av_clip_pixel((((QPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) * wx + offset) >> shift) + ox);
1282         tmp += MAX_PB_SIZE;
1283         dst += dststride;
1284     }
1285 }
1286
1287 static void FUNC(put_hevc_qpel_bi_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1288                                         int16_t *src2, ptrdiff_t src2stride,
1289                                         int height, int denom, int wx0, int wx1,
1290                                         int ox0, int ox1, intptr_t mx, intptr_t my, int width)
1291 {
1292     int x, y;
1293     const int8_t *filter;
1294     pixel *src = (pixel*)_src;
1295     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
1296     pixel *dst          = (pixel *)_dst;
1297     ptrdiff_t dststride = _dststride / sizeof(pixel);
1298     int16_t tmp_array[(MAX_PB_SIZE + QPEL_EXTRA) * MAX_PB_SIZE];
1299     int16_t *tmp = tmp_array;
1300     int shift = 14 + 1 - BIT_DEPTH;
1301     int log2Wd = denom + shift - 1;
1302
1303     src   -= QPEL_EXTRA_BEFORE * srcstride;
1304     filter = ff_hevc_qpel_filters[mx - 1];
1305     for (y = 0; y < height + QPEL_EXTRA; y++) {
1306         for (x = 0; x < width; x++)
1307             tmp[x] = QPEL_FILTER(src, 1) >> (BIT_DEPTH - 8);
1308         src += srcstride;
1309         tmp += MAX_PB_SIZE;
1310     }
1311
1312     tmp    = tmp_array + QPEL_EXTRA_BEFORE * MAX_PB_SIZE;
1313     filter = ff_hevc_qpel_filters[my - 1];
1314
1315     ox0     = ox0 * (1 << (BIT_DEPTH - 8));
1316     ox1     = ox1 * (1 << (BIT_DEPTH - 8));
1317     for (y = 0; y < height; y++) {
1318         for (x = 0; x < width; x++)
1319             dst[x] = av_clip_pixel(((QPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) * wx1 + src2[x] * wx0 +
1320                                     ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1));
1321         tmp  += MAX_PB_SIZE;
1322         dst  += dststride;
1323         src2 += src2stride;
1324     }
1325 }
1326
1327 ////////////////////////////////////////////////////////////////////////////////
1328 //
1329 ////////////////////////////////////////////////////////////////////////////////
1330 #define EPEL_FILTER(src, stride)                                               \
1331     (filter[0] * src[x - stride] +                                             \
1332      filter[1] * src[x]          +                                             \
1333      filter[2] * src[x + stride] +                                             \
1334      filter[3] * src[x + 2 * stride])
1335
1336 static void FUNC(put_hevc_epel_h)(int16_t *dst, ptrdiff_t dststride,
1337                                   uint8_t *_src, ptrdiff_t _srcstride,
1338                                   int height, intptr_t mx, intptr_t my, int width)
1339 {
1340     int x, y;
1341     pixel *src = (pixel *)_src;
1342     ptrdiff_t srcstride  = _srcstride / sizeof(pixel);
1343     const int8_t *filter = ff_hevc_epel_filters[mx - 1];
1344     for (y = 0; y < height; y++) {
1345         for (x = 0; x < width; x++)
1346             dst[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8);
1347         src += srcstride;
1348         dst += dststride;
1349     }
1350 }
1351
1352 static void FUNC(put_hevc_epel_v)(int16_t *dst, ptrdiff_t dststride,
1353                                   uint8_t *_src, ptrdiff_t _srcstride,
1354                                   int height, intptr_t mx, intptr_t my, int width)
1355 {
1356     int x, y;
1357     pixel *src = (pixel *)_src;
1358     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
1359     const int8_t *filter = ff_hevc_epel_filters[my - 1];
1360
1361     for (y = 0; y < height; y++) {
1362         for (x = 0; x < width; x++)
1363             dst[x] = EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8);
1364         src += srcstride;
1365         dst += dststride;
1366     }
1367 }
1368
1369 static void FUNC(put_hevc_epel_hv)(int16_t *dst, ptrdiff_t dststride,
1370                                    uint8_t *_src, ptrdiff_t _srcstride,
1371                                    int height, intptr_t mx, intptr_t my, int width)
1372 {
1373     int x, y;
1374     pixel *src = (pixel *)_src;
1375     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
1376     const int8_t *filter = ff_hevc_epel_filters[mx - 1];
1377     int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE];
1378     int16_t *tmp = tmp_array;
1379
1380     src -= EPEL_EXTRA_BEFORE * srcstride;
1381
1382     for (y = 0; y < height + EPEL_EXTRA; y++) {
1383         for (x = 0; x < width; x++)
1384             tmp[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8);
1385         src += srcstride;
1386         tmp += MAX_PB_SIZE;
1387     }
1388
1389     tmp      = tmp_array + EPEL_EXTRA_BEFORE * MAX_PB_SIZE;
1390     filter = ff_hevc_epel_filters[my - 1];
1391
1392     for (y = 0; y < height; y++) {
1393         for (x = 0; x < width; x++)
1394             dst[x] = EPEL_FILTER(tmp, MAX_PB_SIZE) >> 6;
1395         tmp += MAX_PB_SIZE;
1396         dst += dststride;
1397     }
1398 }
1399
1400 static void FUNC(put_hevc_epel_uni_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1401                                       int height, intptr_t mx, intptr_t my, int width)
1402 {
1403     int x, y;
1404     pixel *src = (pixel *)_src;
1405     ptrdiff_t srcstride  = _srcstride / sizeof(pixel);
1406     pixel *dst          = (pixel *)_dst;
1407     ptrdiff_t dststride = _dststride / sizeof(pixel);
1408     const int8_t *filter = ff_hevc_epel_filters[mx - 1];
1409     int shift = 14 - BIT_DEPTH;
1410 #if BIT_DEPTH < 14
1411     int offset = 1 << (shift - 1);
1412 #else
1413     int offset = 0;
1414 #endif
1415
1416     for (y = 0; y < height; y++) {
1417         for (x = 0; x < width; x++)
1418             dst[x] = av_clip_pixel(((EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) + offset) >> shift);
1419         src += srcstride;
1420         dst += dststride;
1421     }
1422 }
1423
1424 static void FUNC(put_hevc_epel_bi_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1425                                      int16_t *src2, ptrdiff_t src2stride,
1426                                      int height, intptr_t mx, intptr_t my, int width)
1427 {
1428     int x, y;
1429     pixel *src = (pixel *)_src;
1430     ptrdiff_t srcstride  = _srcstride / sizeof(pixel);
1431     pixel *dst          = (pixel *)_dst;
1432     ptrdiff_t dststride = _dststride / sizeof(pixel);
1433     const int8_t *filter = ff_hevc_epel_filters[mx - 1];
1434     int shift = 14 + 1 - BIT_DEPTH;
1435 #if BIT_DEPTH < 14
1436     int offset = 1 << (shift - 1);
1437 #else
1438     int offset = 0;
1439 #endif
1440
1441     for (y = 0; y < height; y++) {
1442         for (x = 0; x < width; x++) {
1443             dst[x] = av_clip_pixel(((EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) + src2[x] + offset) >> shift);
1444         }
1445         dst  += dststride;
1446         src  += srcstride;
1447         src2 += src2stride;
1448     }
1449 }
1450
1451 static void FUNC(put_hevc_epel_uni_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1452                                       int height, intptr_t mx, intptr_t my, int width)
1453 {
1454     int x, y;
1455     pixel *src = (pixel *)_src;
1456     ptrdiff_t srcstride  = _srcstride / sizeof(pixel);
1457     pixel *dst          = (pixel *)_dst;
1458     ptrdiff_t dststride = _dststride / sizeof(pixel);
1459     const int8_t *filter = ff_hevc_epel_filters[my - 1];
1460     int shift = 14 - BIT_DEPTH;
1461 #if BIT_DEPTH < 14
1462     int offset = 1 << (shift - 1);
1463 #else
1464     int offset = 0;
1465 #endif
1466
1467     for (y = 0; y < height; y++) {
1468         for (x = 0; x < width; x++)
1469             dst[x] = av_clip_pixel(((EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) + offset) >> shift);
1470         src += srcstride;
1471         dst += dststride;
1472     }
1473 }
1474
1475 static void FUNC(put_hevc_epel_bi_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1476                                      int16_t *src2, ptrdiff_t src2stride,
1477                                      int height, intptr_t mx, intptr_t my, int width)
1478 {
1479     int x, y;
1480     pixel *src = (pixel *)_src;
1481     ptrdiff_t srcstride  = _srcstride / sizeof(pixel);
1482     const int8_t *filter = ff_hevc_epel_filters[my - 1];
1483     pixel *dst          = (pixel *)_dst;
1484     ptrdiff_t dststride = _dststride / sizeof(pixel);
1485     int shift = 14 + 1 - BIT_DEPTH;
1486 #if BIT_DEPTH < 14
1487     int offset = 1 << (shift - 1);
1488 #else
1489     int offset = 0;
1490 #endif
1491
1492     for (y = 0; y < height; y++) {
1493         for (x = 0; x < width; x++)
1494             dst[x] = av_clip_pixel(((EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) + src2[x] + offset) >> shift);
1495         dst  += dststride;
1496         src  += srcstride;
1497         src2 += src2stride;
1498     }
1499 }
1500
1501 static void FUNC(put_hevc_epel_uni_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1502                                        int height, intptr_t mx, intptr_t my, int width)
1503 {
1504     int x, y;
1505     pixel *src = (pixel *)_src;
1506     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
1507     pixel *dst          = (pixel *)_dst;
1508     ptrdiff_t dststride = _dststride / sizeof(pixel);
1509     const int8_t *filter = ff_hevc_epel_filters[mx - 1];
1510     int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE];
1511     int16_t *tmp = tmp_array;
1512     int shift = 14 - BIT_DEPTH;
1513 #if BIT_DEPTH < 14
1514     int offset = 1 << (shift - 1);
1515 #else
1516     int offset = 0;
1517 #endif
1518
1519     src -= EPEL_EXTRA_BEFORE * srcstride;
1520
1521     for (y = 0; y < height + EPEL_EXTRA; y++) {
1522         for (x = 0; x < width; x++)
1523             tmp[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8);
1524         src += srcstride;
1525         tmp += MAX_PB_SIZE;
1526     }
1527
1528     tmp      = tmp_array + EPEL_EXTRA_BEFORE * MAX_PB_SIZE;
1529     filter = ff_hevc_epel_filters[my - 1];
1530
1531     for (y = 0; y < height; y++) {
1532         for (x = 0; x < width; x++)
1533             dst[x] = av_clip_pixel(((EPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) + offset) >> shift);
1534         tmp += MAX_PB_SIZE;
1535         dst += dststride;
1536     }
1537 }
1538
1539 static void FUNC(put_hevc_epel_bi_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1540                                       int16_t *src2, ptrdiff_t src2stride,
1541                                       int height, intptr_t mx, intptr_t my, int width)
1542 {
1543     int x, y;
1544     pixel *src = (pixel *)_src;
1545     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
1546     pixel *dst          = (pixel *)_dst;
1547     ptrdiff_t dststride = _dststride / sizeof(pixel);
1548     const int8_t *filter = ff_hevc_epel_filters[mx - 1];
1549     int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE];
1550     int16_t *tmp = tmp_array;
1551     int shift = 14 + 1 - BIT_DEPTH;
1552 #if BIT_DEPTH < 14
1553     int offset = 1 << (shift - 1);
1554 #else
1555     int offset = 0;
1556 #endif
1557
1558     src -= EPEL_EXTRA_BEFORE * srcstride;
1559
1560     for (y = 0; y < height + EPEL_EXTRA; y++) {
1561         for (x = 0; x < width; x++)
1562             tmp[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8);
1563         src += srcstride;
1564         tmp += MAX_PB_SIZE;
1565     }
1566
1567     tmp      = tmp_array + EPEL_EXTRA_BEFORE * MAX_PB_SIZE;
1568     filter = ff_hevc_epel_filters[my - 1];
1569
1570     for (y = 0; y < height; y++) {
1571         for (x = 0; x < width; x++)
1572             dst[x] = av_clip_pixel(((EPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) + src2[x] + offset) >> shift);
1573         tmp  += MAX_PB_SIZE;
1574         dst  += dststride;
1575         src2 += src2stride;
1576     }
1577 }
1578
1579 static void FUNC(put_hevc_epel_uni_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1580                                         int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width)
1581 {
1582     int x, y;
1583     pixel *src = (pixel *)_src;
1584     ptrdiff_t srcstride  = _srcstride / sizeof(pixel);
1585     pixel *dst          = (pixel *)_dst;
1586     ptrdiff_t dststride = _dststride / sizeof(pixel);
1587     const int8_t *filter = ff_hevc_epel_filters[mx - 1];
1588     int shift = denom + 14 - BIT_DEPTH;
1589 #if BIT_DEPTH < 14
1590     int offset = 1 << (shift - 1);
1591 #else
1592     int offset = 0;
1593 #endif
1594
1595     ox     = ox * (1 << (BIT_DEPTH - 8));
1596     for (y = 0; y < height; y++) {
1597         for (x = 0; x < width; x++) {
1598             dst[x] = av_clip_pixel((((EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) * wx + offset) >> shift) + ox);
1599         }
1600         dst += dststride;
1601         src += srcstride;
1602     }
1603 }
1604
1605 static void FUNC(put_hevc_epel_bi_w_h)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1606                                        int16_t *src2, ptrdiff_t src2stride,
1607                                        int height, int denom, int wx0, int wx1,
1608                                        int ox0, int ox1, intptr_t mx, intptr_t my, int width)
1609 {
1610     int x, y;
1611     pixel *src = (pixel *)_src;
1612     ptrdiff_t srcstride  = _srcstride / sizeof(pixel);
1613     pixel *dst          = (pixel *)_dst;
1614     ptrdiff_t dststride = _dststride / sizeof(pixel);
1615     const int8_t *filter = ff_hevc_epel_filters[mx - 1];
1616     int shift = 14 + 1 - BIT_DEPTH;
1617     int log2Wd = denom + shift - 1;
1618
1619     ox0     = ox0 * (1 << (BIT_DEPTH - 8));
1620     ox1     = ox1 * (1 << (BIT_DEPTH - 8));
1621     for (y = 0; y < height; y++) {
1622         for (x = 0; x < width; x++)
1623             dst[x] = av_clip_pixel(((EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8)) * wx1 + src2[x] * wx0 +
1624                                     ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1));
1625         src  += srcstride;
1626         dst  += dststride;
1627         src2 += src2stride;
1628     }
1629 }
1630
1631 static void FUNC(put_hevc_epel_uni_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1632                                         int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width)
1633 {
1634     int x, y;
1635     pixel *src = (pixel *)_src;
1636     ptrdiff_t srcstride  = _srcstride / sizeof(pixel);
1637     pixel *dst          = (pixel *)_dst;
1638     ptrdiff_t dststride = _dststride / sizeof(pixel);
1639     const int8_t *filter = ff_hevc_epel_filters[my - 1];
1640     int shift = denom + 14 - BIT_DEPTH;
1641 #if BIT_DEPTH < 14
1642     int offset = 1 << (shift - 1);
1643 #else
1644     int offset = 0;
1645 #endif
1646
1647     ox     = ox * (1 << (BIT_DEPTH - 8));
1648     for (y = 0; y < height; y++) {
1649         for (x = 0; x < width; x++) {
1650             dst[x] = av_clip_pixel((((EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) * wx + offset) >> shift) + ox);
1651         }
1652         dst += dststride;
1653         src += srcstride;
1654     }
1655 }
1656
1657 static void FUNC(put_hevc_epel_bi_w_v)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1658                                        int16_t *src2, ptrdiff_t src2stride,
1659                                        int height, int denom, int wx0, int wx1,
1660                                        int ox0, int ox1, intptr_t mx, intptr_t my, int width)
1661 {
1662     int x, y;
1663     pixel *src = (pixel *)_src;
1664     ptrdiff_t srcstride  = _srcstride / sizeof(pixel);
1665     const int8_t *filter = ff_hevc_epel_filters[my - 1];
1666     pixel *dst          = (pixel *)_dst;
1667     ptrdiff_t dststride = _dststride / sizeof(pixel);
1668     int shift = 14 + 1 - BIT_DEPTH;
1669     int log2Wd = denom + shift - 1;
1670
1671     ox0     = ox0 * (1 << (BIT_DEPTH - 8));
1672     ox1     = ox1 * (1 << (BIT_DEPTH - 8));
1673     for (y = 0; y < height; y++) {
1674         for (x = 0; x < width; x++)
1675             dst[x] = av_clip_pixel(((EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8)) * wx1 + src2[x] * wx0 +
1676                                     ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1));
1677         src  += srcstride;
1678         dst  += dststride;
1679         src2 += src2stride;
1680     }
1681 }
1682
1683 static void FUNC(put_hevc_epel_uni_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1684                                          int height, int denom, int wx, int ox, intptr_t mx, intptr_t my, int width)
1685 {
1686     int x, y;
1687     pixel *src = (pixel *)_src;
1688     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
1689     pixel *dst          = (pixel *)_dst;
1690     ptrdiff_t dststride = _dststride / sizeof(pixel);
1691     const int8_t *filter = ff_hevc_epel_filters[mx - 1];
1692     int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE];
1693     int16_t *tmp = tmp_array;
1694     int shift = denom + 14 - BIT_DEPTH;
1695 #if BIT_DEPTH < 14
1696     int offset = 1 << (shift - 1);
1697 #else
1698     int offset = 0;
1699 #endif
1700
1701     src -= EPEL_EXTRA_BEFORE * srcstride;
1702
1703     for (y = 0; y < height + EPEL_EXTRA; y++) {
1704         for (x = 0; x < width; x++)
1705             tmp[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8);
1706         src += srcstride;
1707         tmp += MAX_PB_SIZE;
1708     }
1709
1710     tmp      = tmp_array + EPEL_EXTRA_BEFORE * MAX_PB_SIZE;
1711     filter = ff_hevc_epel_filters[my - 1];
1712
1713     ox     = ox * (1 << (BIT_DEPTH - 8));
1714     for (y = 0; y < height; y++) {
1715         for (x = 0; x < width; x++)
1716             dst[x] = av_clip_pixel((((EPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) * wx + offset) >> shift) + ox);
1717         tmp += MAX_PB_SIZE;
1718         dst += dststride;
1719     }
1720 }
1721
1722 static void FUNC(put_hevc_epel_bi_w_hv)(uint8_t *_dst, ptrdiff_t _dststride, uint8_t *_src, ptrdiff_t _srcstride,
1723                                         int16_t *src2, ptrdiff_t src2stride,
1724                                         int height, int denom, int wx0, int wx1,
1725                                         int ox0, int ox1, intptr_t mx, intptr_t my, int width)
1726 {
1727     int x, y;
1728     pixel *src = (pixel *)_src;
1729     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
1730     pixel *dst          = (pixel *)_dst;
1731     ptrdiff_t dststride = _dststride / sizeof(pixel);
1732     const int8_t *filter = ff_hevc_epel_filters[mx - 1];
1733     int16_t tmp_array[(MAX_PB_SIZE + EPEL_EXTRA) * MAX_PB_SIZE];
1734     int16_t *tmp = tmp_array;
1735     int shift = 14 + 1 - BIT_DEPTH;
1736     int log2Wd = denom + shift - 1;
1737
1738     src -= EPEL_EXTRA_BEFORE * srcstride;
1739
1740     for (y = 0; y < height + EPEL_EXTRA; y++) {
1741         for (x = 0; x < width; x++)
1742             tmp[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8);
1743         src += srcstride;
1744         tmp += MAX_PB_SIZE;
1745     }
1746
1747     tmp      = tmp_array + EPEL_EXTRA_BEFORE * MAX_PB_SIZE;
1748     filter = ff_hevc_epel_filters[my - 1];
1749
1750     ox0     = ox0 * (1 << (BIT_DEPTH - 8));
1751     ox1     = ox1 * (1 << (BIT_DEPTH - 8));
1752     for (y = 0; y < height; y++) {
1753         for (x = 0; x < width; x++)
1754             dst[x] = av_clip_pixel(((EPEL_FILTER(tmp, MAX_PB_SIZE) >> 6) * wx1 + src2[x] * wx0 +
1755                                     ((ox0 + ox1 + 1) << log2Wd)) >> (log2Wd + 1));
1756         tmp  += MAX_PB_SIZE;
1757         dst  += dststride;
1758         src2 += src2stride;
1759     }
1760 }// line zero
1761 #define P3 pix[-4 * xstride]
1762 #define P2 pix[-3 * xstride]
1763 #define P1 pix[-2 * xstride]
1764 #define P0 pix[-1 * xstride]
1765 #define Q0 pix[0 * xstride]
1766 #define Q1 pix[1 * xstride]
1767 #define Q2 pix[2 * xstride]
1768 #define Q3 pix[3 * xstride]
1769
1770 // line three. used only for deblocking decision
1771 #define TP3 pix[-4 * xstride + 3 * ystride]
1772 #define TP2 pix[-3 * xstride + 3 * ystride]
1773 #define TP1 pix[-2 * xstride + 3 * ystride]
1774 #define TP0 pix[-1 * xstride + 3 * ystride]
1775 #define TQ0 pix[0  * xstride + 3 * ystride]
1776 #define TQ1 pix[1  * xstride + 3 * ystride]
1777 #define TQ2 pix[2  * xstride + 3 * ystride]
1778 #define TQ3 pix[3  * xstride + 3 * ystride]
1779
1780 static void FUNC(hevc_loop_filter_luma)(uint8_t *_pix,
1781                                         ptrdiff_t _xstride, ptrdiff_t _ystride,
1782                                         int *_beta, int *_tc,
1783                                         uint8_t *_no_p, uint8_t *_no_q)
1784 {
1785     int d, j;
1786     pixel *pix        = (pixel *)_pix;
1787     ptrdiff_t xstride = _xstride / sizeof(pixel);
1788     ptrdiff_t ystride = _ystride / sizeof(pixel);
1789
1790     for (j = 0; j < 2; j++) {
1791         const int dp0  = abs(P2  - 2 * P1  + P0);
1792         const int dq0  = abs(Q2  - 2 * Q1  + Q0);
1793         const int dp3  = abs(TP2 - 2 * TP1 + TP0);
1794         const int dq3  = abs(TQ2 - 2 * TQ1 + TQ0);
1795         const int d0   = dp0 + dq0;
1796         const int d3   = dp3 + dq3;
1797         const int beta = _beta[j] << (BIT_DEPTH - 8);
1798         const int tc   = _tc[j]   << (BIT_DEPTH - 8);
1799         const int no_p = _no_p[j];
1800         const int no_q = _no_q[j];
1801
1802         if (d0 + d3 >= beta) {
1803             pix += 4 * ystride;
1804             continue;
1805         } else {
1806             const int beta_3 = beta >> 3;
1807             const int beta_2 = beta >> 2;
1808             const int tc25   = ((tc * 5 + 1) >> 1);
1809
1810             if (abs(P3  -  P0) + abs(Q3  -  Q0) < beta_3 && abs(P0  -  Q0) < tc25 &&
1811                 abs(TP3 - TP0) + abs(TQ3 - TQ0) < beta_3 && abs(TP0 - TQ0) < tc25 &&
1812                                       (d0 << 1) < beta_2 &&      (d3 << 1) < beta_2) {
1813                 // strong filtering
1814                 const int tc2 = tc << 1;
1815                 for (d = 0; d < 4; d++) {
1816                     const int p3 = P3;
1817                     const int p2 = P2;
1818                     const int p1 = P1;
1819                     const int p0 = P0;
1820                     const int q0 = Q0;
1821                     const int q1 = Q1;
1822                     const int q2 = Q2;
1823                     const int q3 = Q3;
1824                     if (!no_p) {
1825                         P0 = p0 + av_clip(((p2 + 2 * p1 + 2 * p0 + 2 * q0 + q1 + 4) >> 3) - p0, -tc2, tc2);
1826                         P1 = p1 + av_clip(((p2 + p1 + p0 + q0 + 2) >> 2) - p1, -tc2, tc2);
1827                         P2 = p2 + av_clip(((2 * p3 + 3 * p2 + p1 + p0 + q0 + 4) >> 3) - p2, -tc2, tc2);
1828                     }
1829                     if (!no_q) {
1830                         Q0 = q0 + av_clip(((p1 + 2 * p0 + 2 * q0 + 2 * q1 + q2 + 4) >> 3) - q0, -tc2, tc2);
1831                         Q1 = q1 + av_clip(((p0 + q0 + q1 + q2 + 2) >> 2) - q1, -tc2, tc2);
1832                         Q2 = q2 + av_clip(((2 * q3 + 3 * q2 + q1 + q0 + p0 + 4) >> 3) - q2, -tc2, tc2);
1833                     }
1834                     pix += ystride;
1835                 }
1836             } else { // normal filtering
1837                 int nd_p = 1;
1838                 int nd_q = 1;
1839                 const int tc_2 = tc >> 1;
1840                 if (dp0 + dp3 < ((beta + (beta >> 1)) >> 3))
1841                     nd_p = 2;
1842                 if (dq0 + dq3 < ((beta + (beta >> 1)) >> 3))
1843                     nd_q = 2;
1844
1845                 for (d = 0; d < 4; d++) {
1846                     const int p2 = P2;
1847                     const int p1 = P1;
1848                     const int p0 = P0;
1849                     const int q0 = Q0;
1850                     const int q1 = Q1;
1851                     const int q2 = Q2;
1852                     int delta0   = (9 * (q0 - p0) - 3 * (q1 - p1) + 8) >> 4;
1853                     if (abs(delta0) < 10 * tc) {
1854                         delta0 = av_clip(delta0, -tc, tc);
1855                         if (!no_p)
1856                             P0 = av_clip_pixel(p0 + delta0);
1857                         if (!no_q)
1858                             Q0 = av_clip_pixel(q0 - delta0);
1859                         if (!no_p && nd_p > 1) {
1860                             const int deltap1 = av_clip((((p2 + p0 + 1) >> 1) - p1 + delta0) >> 1, -tc_2, tc_2);
1861                             P1 = av_clip_pixel(p1 + deltap1);
1862                         }
1863                         if (!no_q && nd_q > 1) {
1864                             const int deltaq1 = av_clip((((q2 + q0 + 1) >> 1) - q1 - delta0) >> 1, -tc_2, tc_2);
1865                             Q1 = av_clip_pixel(q1 + deltaq1);
1866                         }
1867                     }
1868                     pix += ystride;
1869                 }
1870             }
1871         }
1872     }
1873 }
1874
1875 static void FUNC(hevc_loop_filter_chroma)(uint8_t *_pix, ptrdiff_t _xstride,
1876                                           ptrdiff_t _ystride, int *_tc,
1877                                           uint8_t *_no_p, uint8_t *_no_q)
1878 {
1879     int d, j, no_p, no_q;
1880     pixel *pix        = (pixel *)_pix;
1881     ptrdiff_t xstride = _xstride / sizeof(pixel);
1882     ptrdiff_t ystride = _ystride / sizeof(pixel);
1883
1884     for (j = 0; j < 2; j++) {
1885         const int tc = _tc[j] << (BIT_DEPTH - 8);
1886         if (tc <= 0) {
1887             pix += 4 * ystride;
1888             continue;
1889         }
1890         no_p = _no_p[j];
1891         no_q = _no_q[j];
1892
1893         for (d = 0; d < 4; d++) {
1894             int delta0;
1895             const int p1 = P1;
1896             const int p0 = P0;
1897             const int q0 = Q0;
1898             const int q1 = Q1;
1899             delta0 = av_clip((((q0 - p0) * 4) + p1 - q1 + 4) >> 3, -tc, tc);
1900             if (!no_p)
1901                 P0 = av_clip_pixel(p0 + delta0);
1902             if (!no_q)
1903                 Q0 = av_clip_pixel(q0 - delta0);
1904             pix += ystride;
1905         }
1906     }
1907 }
1908
1909 static void FUNC(hevc_h_loop_filter_chroma)(uint8_t *pix, ptrdiff_t stride,
1910                                             int *tc, uint8_t *no_p,
1911                                             uint8_t *no_q)
1912 {
1913     FUNC(hevc_loop_filter_chroma)(pix, stride, sizeof(pixel), tc, no_p, no_q);
1914 }
1915
1916 static void FUNC(hevc_v_loop_filter_chroma)(uint8_t *pix, ptrdiff_t stride,
1917                                             int *tc, uint8_t *no_p,
1918                                             uint8_t *no_q)
1919 {
1920     FUNC(hevc_loop_filter_chroma)(pix, sizeof(pixel), stride, tc, no_p, no_q);
1921 }
1922
1923 static void FUNC(hevc_h_loop_filter_luma)(uint8_t *pix, ptrdiff_t stride,
1924                                           int *beta, int *tc, uint8_t *no_p,
1925                                           uint8_t *no_q)
1926 {
1927     FUNC(hevc_loop_filter_luma)(pix, stride, sizeof(pixel),
1928                                 beta, tc, no_p, no_q);
1929 }
1930
1931 static void FUNC(hevc_v_loop_filter_luma)(uint8_t *pix, ptrdiff_t stride,
1932                                           int *beta, int *tc, uint8_t *no_p,
1933                                           uint8_t *no_q)
1934 {
1935     FUNC(hevc_loop_filter_luma)(pix, sizeof(pixel), stride,
1936                                 beta, tc, no_p, no_q);
1937 }
1938
1939 #undef P3
1940 #undef P2
1941 #undef P1
1942 #undef P0
1943 #undef Q0
1944 #undef Q1
1945 #undef Q2
1946 #undef Q3
1947
1948 #undef TP3
1949 #undef TP2
1950 #undef TP1
1951 #undef TP0
1952 #undef TQ0
1953 #undef TQ1
1954 #undef TQ2
1955 #undef TQ3