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