lavc: add a HEVC decoder.
[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 "bit_depth_template.c"
25 #include "hevcdsp.h"
26 #include "hevc.h"
27
28 #define SET(dst, x) (dst) = (x)
29 #define SCALE(dst, x) (dst) = av_clip_int16(((x) + add) >> shift)
30 #define ADD_AND_SCALE(dst, x) (dst) = av_clip_pixel((dst) + av_clip_int16(((x) + add) >> shift))
31
32 static void FUNC(put_pcm)(uint8_t *_dst, ptrdiff_t _stride, int size,
33                           GetBitContext *gb, int pcm_bit_depth)
34 {
35     int x, y;
36     pixel *dst = (pixel*)_dst;
37     ptrdiff_t stride = _stride / sizeof(pixel);
38
39     for (y = 0; y < size; y++) {
40         for (x = 0; x < size; x++)
41             dst[x] = get_bits(gb, pcm_bit_depth) << (BIT_DEPTH - pcm_bit_depth);
42         dst += stride;
43     }
44 }
45
46 static void FUNC(transquant_bypass4x4)(uint8_t *_dst, int16_t *coeffs, ptrdiff_t _stride)
47 {
48     int x, y;
49     pixel *dst = (pixel*)_dst;
50     ptrdiff_t stride = _stride / sizeof(pixel);
51
52     for (y = 0; y < 4; y++) {
53         for (x = 0; x < 4; x++) {
54             dst[x] += *coeffs;
55             coeffs++;
56         }
57         dst += stride;
58     }
59
60 }
61
62 static void FUNC(transquant_bypass8x8)(uint8_t *_dst, int16_t *coeffs, ptrdiff_t _stride)
63 {
64     int x, y;
65     pixel *dst = (pixel*)_dst;
66     ptrdiff_t stride = _stride / sizeof(pixel);
67
68     for (y = 0; y < 8; y++) {
69         for (x = 0; x < 8; x++) {
70             dst[x] += *coeffs;
71             coeffs++;
72         }
73         dst += stride;
74     }
75 }
76
77 static void FUNC(transquant_bypass16x16)(uint8_t *_dst, int16_t *coeffs, ptrdiff_t _stride)
78 {
79     int x, y;
80     pixel *dst = (pixel*)_dst;
81     ptrdiff_t stride = _stride / sizeof(pixel);
82
83     for (y = 0; y < 16; y++) {
84         for (x = 0; x < 16; x++) {
85             dst[x] += *coeffs;
86             coeffs++;
87         }
88         dst += stride;
89     }
90
91 }
92
93 static void FUNC(transquant_bypass32x32)(uint8_t *_dst, int16_t *coeffs, ptrdiff_t _stride)
94 {
95     int x, y;
96     pixel *dst = (pixel*)_dst;
97     ptrdiff_t stride = _stride / sizeof(pixel);
98
99     for (y = 0; y < 32; y++) {
100         for (x = 0; x < 32; x++) {
101             dst[x] += *coeffs;
102             coeffs++;
103         }
104         dst += stride;
105     }
106 }
107
108 static void FUNC(transform_skip)(uint8_t *_dst, int16_t *coeffs, ptrdiff_t _stride)
109 {
110     pixel *dst = (pixel*)_dst;
111     ptrdiff_t stride = _stride / sizeof(pixel);
112     int size = 4;
113     int shift = 13 - BIT_DEPTH;
114 #if BIT_DEPTH <= 13
115     int offset = 1 << (shift - 1);
116 #else
117     int offset = 0;
118 #endif
119     int x, y;
120     switch (size){
121         case 32:
122             for (y = 0; y < 32*32; y+=32) {
123                 for (x = 0; x < 32; x++) {
124                     dst[x] = av_clip_pixel(dst[x] + ((coeffs[y + x] + offset) >> shift));
125                 }
126                 dst += stride;
127             }
128             break;
129         case 16:
130             for (y = 0; y < 16*16; y+=16) {
131                 for (x = 0; x < 16; x++) {
132                     dst[x] = av_clip_pixel(dst[x] + ((coeffs[y + x] + offset) >> shift));
133                 }
134                 dst += stride;
135             }
136             break;
137         case 8:
138             for (y = 0; y < 8*8; y+=8) {
139                 for (x = 0; x < 8; x++) {
140                     dst[x] = av_clip_pixel(dst[x] + ((coeffs[y + x] + offset) >> shift));
141                 }
142                 dst += stride;
143             }
144             break;
145         case 4:
146             for (y = 0; y < 4*4; y+=4) {
147                 for (x = 0; x < 4; x++) {
148                     dst[x] = av_clip_pixel(dst[x] + ((coeffs[y + x] + offset) >> shift));
149                 }
150                 dst += stride;
151             }
152             break;
153     }
154 }
155
156 static void FUNC(transform_4x4_luma_add)(uint8_t *_dst, int16_t *coeffs, ptrdiff_t _stride)
157 {
158 #define TR_4x4_LUMA(dst, src, step, assign)                                     \
159     do {                                                                        \
160         int c0 = src[0*step] + src[2*step];                                     \
161         int c1 = src[2*step] + src[3*step];                                     \
162         int c2 = src[0*step] - src[3*step];                                     \
163         int c3 = 74 * src[1*step];                                              \
164                                                                                 \
165         assign(dst[2*step], 74 * (src[0*step] - src[2*step] + src[3*step]));    \
166         assign(dst[0*step], 29 * c0 + 55 * c1 + c3);                            \
167         assign(dst[1*step], 55 * c2 - 29 * c1 + c3);                            \
168         assign(dst[3*step], 55 * c0 + 29 * c2 - c3);                            \
169     } while (0)
170
171     int i;
172     pixel *dst = (pixel*)_dst;
173     ptrdiff_t stride = _stride / sizeof(pixel);
174     int shift = 7;
175     int add = 1 << (shift - 1);
176     int16_t *src = coeffs;
177
178     for (i = 0; i < 4; i++) {
179         TR_4x4_LUMA(src, src, 4, SCALE);
180         src++;
181     }
182
183     shift = 20 - BIT_DEPTH;
184     add = 1 << (shift - 1);
185     for (i = 0; i < 4; i++) {
186         TR_4x4_LUMA(dst, coeffs, 1, ADD_AND_SCALE);
187         coeffs += 4;
188         dst += stride;
189     }
190
191 #undef TR_4x4_LUMA
192 }
193
194 #define TR_4(dst, src, dstep, sstep, assign)                                    \
195     do {                                                                        \
196         const int e0 = transform[8*0][0] * src[0*sstep] +                       \
197                        transform[8*2][0] * src[2*sstep];                        \
198         const int e1 = transform[8*0][1] * src[0*sstep] +                       \
199                        transform[8*2][1] * src[2*sstep];                        \
200         const int o0 = transform[8*1][0] * src[1*sstep] +                       \
201                        transform[8*3][0] * src[3*sstep];                        \
202         const int o1 = transform[8*1][1] * src[1*sstep] +                       \
203                        transform[8*3][1] * src[3*sstep];                        \
204                                                                                 \
205         assign(dst[0*dstep], e0 + o0);                                          \
206         assign(dst[1*dstep], e1 + o1);                                          \
207         assign(dst[2*dstep], e1 - o1);                                          \
208         assign(dst[3*dstep], e0 - o0);                                          \
209     } while (0)
210 #define TR_4_1(dst, src) TR_4(dst, src, 4, 4, SCALE)
211 #define TR_4_2(dst, src) TR_4(dst, src, 1, 1, ADD_AND_SCALE)
212
213 static void FUNC(transform_4x4_add)(uint8_t *_dst, int16_t *coeffs, ptrdiff_t _stride)
214 {
215     int i;
216     pixel *dst = (pixel*)_dst;
217     ptrdiff_t stride = _stride / sizeof(pixel);
218     int shift = 7;
219     int add = 1 << (shift - 1);
220     int16_t *src = coeffs;
221
222     for (i = 0; i < 4; i++) {
223         TR_4_1(src, src);
224         src++;
225     }
226
227     shift = 20 - BIT_DEPTH;
228     add = 1 << (shift - 1);
229     for (i = 0; i < 4; i++) {
230         TR_4_2(dst, coeffs);
231         coeffs += 4;
232         dst += stride;
233     }
234 }
235
236 #define TR_8(dst, src, dstep, sstep, assign)                \
237     do {                                                    \
238         int i, j;                                           \
239         int e_8[4];                                         \
240         int o_8[4] = { 0 };                                 \
241         for (i = 0; i < 4; i++)                             \
242             for (j = 1; j < 8; j += 2)                      \
243                 o_8[i] += transform[4*j][i] * src[j*sstep]; \
244         TR_4(e_8, src, 1, 2*sstep, SET);                    \
245                                                             \
246         for (i = 0; i < 4; i++) {                           \
247             assign(dst[i*dstep], e_8[i] + o_8[i]);          \
248             assign(dst[(7-i)*dstep], e_8[i] - o_8[i]);      \
249         }                                                   \
250     } while (0)
251 #define TR_16(dst, src, dstep, sstep, assign)                   \
252     do {                                                        \
253         int i, j;                                               \
254         int e_16[8];                                            \
255         int o_16[8] = { 0 };                                    \
256         for (i = 0; i < 8; i++)                                 \
257             for (j = 1; j < 16; j += 2)                         \
258                 o_16[i] += transform[2*j][i] * src[j*sstep];    \
259         TR_8(e_16, src, 1, 2*sstep, SET);                       \
260                                                                 \
261         for (i = 0; i < 8; i++) {                               \
262             assign(dst[i*dstep], e_16[i] + o_16[i]);            \
263             assign(dst[(15-i)*dstep], e_16[i] - o_16[i]);       \
264         }                                                       \
265     } while (0)
266 #define TR_32(dst, src, dstep, sstep, assign)               \
267     do {                                                    \
268         int i, j;                                           \
269         int e_32[16];                                       \
270         int o_32[16] = { 0 };                               \
271         for (i = 0; i < 16; i++)                            \
272             for (j = 1; j < 32; j += 2)                     \
273                 o_32[i] += transform[j][i] * src[j*sstep];  \
274         TR_16(e_32, src, 1, 2*sstep, SET);                \
275                                                             \
276         for (i = 0; i < 16; i++) {                          \
277             assign(dst[i*dstep], e_32[i] + o_32[i]);        \
278             assign(dst[(31-i)*dstep], e_32[i] - o_32[i]);   \
279         }                                                   \
280     } while (0)
281
282 #define TR_8_1(dst, src) TR_8(dst, src, 8, 8, SCALE)
283 #define TR_16_1(dst, src) TR_16(dst, src, 16, 16, SCALE)
284 #define TR_32_1(dst, src) TR_32(dst, src, 32, 32, SCALE)
285
286 #define TR_8_2(dst, src) TR_8(dst, src, 1, 1, ADD_AND_SCALE)
287 #define TR_16_2(dst, src) TR_16(dst, src, 1, 1, ADD_AND_SCALE)
288 #define TR_32_2(dst, src) TR_32(dst, src, 1, 1, ADD_AND_SCALE)
289
290 static void FUNC(transform_8x8_add)(uint8_t *_dst, int16_t *coeffs, ptrdiff_t _stride)
291 {
292     int i;
293     pixel *dst = (pixel*)_dst;
294     ptrdiff_t stride = _stride / sizeof(pixel);
295     int shift = 7;
296     int add = 1 << (shift - 1);
297     int16_t *src = coeffs;
298
299     for (i = 0; i < 8; i++) {
300         TR_8_1(src, src);
301         src++;
302     }
303
304     shift = 20 - BIT_DEPTH;
305     add = 1 << (shift - 1);
306     for (i = 0; i < 8; i++) {
307         TR_8_2(dst, coeffs);
308         coeffs += 8;
309         dst += stride;
310     }
311 }
312
313 static void FUNC(transform_16x16_add)(uint8_t *_dst, int16_t *coeffs, ptrdiff_t _stride)
314 {
315     int i;
316     pixel *dst = (pixel*)_dst;
317     ptrdiff_t stride = _stride / sizeof(pixel);
318     int shift = 7;
319     int add = 1 << (shift - 1);
320     int16_t *src = coeffs;
321
322     for (i = 0; i < 16; i++) {
323         TR_16_1(src, src);
324         src++;
325     }
326
327     shift = 20 - BIT_DEPTH;
328     add = 1 << (shift - 1);
329     for (i = 0; i < 16; i++) {
330         TR_16_2(dst, coeffs);
331         coeffs += 16;
332         dst += stride;
333     }
334 }
335
336 static void FUNC(transform_32x32_add)(uint8_t *_dst, int16_t *coeffs, ptrdiff_t _stride)
337 {
338 #define IT32x32_even(i,w) ( src[ 0*w] * transform[ 0][i] ) + ( src[16*w] * transform[16][i] )
339 #define IT32x32_odd(i,w)  ( src[ 8*w] * transform[ 8][i] ) + ( src[24*w] * transform[24][i] )
340 #define IT16x16(i,w)      ( src[ 4*w] * transform[ 4][i] ) + ( src[12*w] * transform[12][i] ) + ( src[20*w] * transform[20][i] ) + ( src[28*w] * transform[28][i] )
341 #define IT8x8(i,w)        ( src[ 2*w] * transform[ 2][i] ) + ( src[ 6*w] * transform[ 6][i] ) + ( src[10*w] * transform[10][i] ) + ( src[14*w] * transform[14][i] ) + \
342                           ( src[18*w] * transform[18][i] ) + ( src[22*w] * transform[22][i] ) + ( src[26*w] * transform[26][i] ) + ( src[30*w] * transform[30][i] )
343 #define IT4x4(i,w)        ( src[ 1*w] * transform[ 1][i] ) + ( src[ 3*w] * transform[ 3][i] ) + ( src[ 5*w] * transform[ 5][i] ) + ( src[ 7*w] * transform[ 7][i] ) + \
344                           ( src[ 9*w] * transform[ 9][i] ) + ( src[11*w] * transform[11][i] ) + ( src[13*w] * transform[13][i] ) + ( src[15*w] * transform[15][i] ) + \
345                           ( src[17*w] * transform[17][i] ) + ( src[19*w] * transform[19][i] ) + ( src[21*w] * transform[21][i] ) + ( src[23*w] * transform[23][i] ) + \
346                           ( src[25*w] * transform[25][i] ) + ( src[27*w] * transform[27][i] ) + ( src[29*w] * transform[29][i] ) + ( src[31*w] * transform[31][i] )
347     int i;
348     pixel *dst = (pixel*)_dst;
349     ptrdiff_t stride = _stride / sizeof(pixel);
350     int shift = 7;
351     int add = 1 << (shift - 1);
352     int16_t *src = coeffs;
353
354     for (i = 0; i < 32; i++) {
355         TR_32_1(src, src);
356         src++;
357     }
358     src   = coeffs;
359     shift = 20 - BIT_DEPTH;
360     add   = 1 << (shift - 1);
361     for (i = 0; i < 32; i++) {
362         TR_32_2(dst, coeffs);
363         coeffs += 32;
364         dst += stride;
365     }
366 #undef IT32x32_even
367 #undef IT32x32_odd
368 #undef IT16x16
369 #undef IT8x8
370 #undef IT4x4
371 }
372
373 static void FUNC(sao_band_filter)(uint8_t *_dst, uint8_t *_src,
374                                   ptrdiff_t _stride, SAOParams *sao,
375                                   int *borders, int width, int height,
376                                   int c_idx, int class)
377 {
378     pixel *dst = (pixel*)_dst;
379     pixel *src = (pixel*)_src;
380     ptrdiff_t stride = _stride / sizeof(pixel);
381     int offset_table[32] = { 0 };
382     int k, y, x;
383     int chroma = !!c_idx;
384     int shift = BIT_DEPTH - 5;
385     int *sao_offset_val = sao->offset_val[c_idx];
386     int sao_left_class  = sao->band_position[c_idx];
387     int init_y = 0, init_x = 0;
388
389     switch (class) {
390     case 0:
391         if (!borders[2])
392             width -= ((8 >> chroma) + 2);
393         if (!borders[3])
394             height -= ((4 >> chroma) + 2);
395         break;
396     case 1:
397         init_y = -(4 >> chroma) - 2;
398         if (!borders[2])
399             width -= ((8 >> chroma) + 2);
400         height = (4 >> chroma) + 2;
401         break;
402     case 2:
403         init_x = -(8 >> chroma) - 2;
404         width  =  (8 >> chroma) + 2;
405         if (!borders[3])
406             height -= ((4 >> chroma) + 2);
407         break;
408     case 3:
409         init_y = -(4 >> chroma) - 2;
410         init_x = -(8 >> chroma) - 2;
411         width  =  (8 >> chroma) + 2;
412         height =  (4 >> chroma) + 2;
413         break;
414     }
415
416     dst = dst + (init_y * stride + init_x);
417     src = src + (init_y * stride + init_x);
418     for (k = 0; k < 4; k++)
419         offset_table[(k + sao_left_class) & 31] = sao_offset_val[k + 1];
420     for (y = 0; y < height; y++) {
421         for (x = 0; x < width; x++)
422             dst[x] = av_clip_pixel(src[x] + offset_table[av_clip_pixel(src[x] >> shift)]);
423         dst += stride;
424         src += stride;
425     }
426 }
427
428 static void FUNC(sao_band_filter_0)(uint8_t *dst, uint8_t *src,
429                                     ptrdiff_t stride, SAOParams *sao,
430                                     int *borders, int width, int height,
431                                     int c_idx)
432 {
433     FUNC(sao_band_filter)(dst, src, stride, sao, borders, width, height, c_idx, 0);
434 }
435
436 static void FUNC(sao_band_filter_1)(uint8_t *dst, uint8_t *src,
437                                     ptrdiff_t stride, SAOParams *sao,
438                                     int *borders, int width, int height,
439                                     int c_idx)
440 {
441     FUNC(sao_band_filter)(dst, src, stride, sao, borders, width, height, c_idx, 1);
442 }
443
444 static void FUNC(sao_band_filter_2)(uint8_t *dst, uint8_t *src,
445                                     ptrdiff_t stride, SAOParams *sao,
446                                     int *borders, int width, int height,
447                                     int c_idx)
448 {
449     FUNC(sao_band_filter)(dst, src, stride, sao, borders, width, height, c_idx, 2);
450 }
451
452 static void FUNC(sao_band_filter_3)(uint8_t *_dst, uint8_t *_src,
453                                     ptrdiff_t _stride, SAOParams *sao,
454                                     int *borders, int width, int height,
455                                     int c_idx)
456 {
457     FUNC(sao_band_filter)(_dst, _src, _stride, sao, borders, width, height, c_idx, 3);
458 }
459
460 static void FUNC(sao_edge_filter_0)(uint8_t *_dst, uint8_t *_src,
461                                     ptrdiff_t _stride, SAOParams *sao,
462                                     int *borders, int _width, int _height,
463                                     int c_idx,
464                                     uint8_t vert_edge, uint8_t horiz_edge, uint8_t diag_edge)
465 {
466     int x, y;
467     pixel *dst = (pixel*)_dst;
468     pixel *src = (pixel*)_src;
469     ptrdiff_t stride = _stride / sizeof(pixel);
470     int chroma = !!c_idx;
471     int *sao_offset_val = sao->offset_val[c_idx];
472     int sao_eo_class = sao->eo_class[c_idx];
473
474     static const int8_t pos[4][2][2] = {
475         {{ -1,  0}, { 1, 0}}, // horizontal
476         {{  0, -1}, { 0, 1}}, // vertical
477         {{ -1, -1}, { 1, 1}}, // 45 degree
478         {{  1, -1}, {-1, 1}}, // 135 degree
479     };
480     static const uint8_t edge_idx[] = { 1, 2, 0, 3, 4 };
481
482     int init_x = 0, init_y = 0, width = _width, height = _height;
483
484 #define CMP(a, b) ((a) > (b) ? 1 : ((a) == (b) ? 0 : -1))
485
486     if (!borders[2])
487         width -= (8 >> chroma) + 2;
488     if (!borders[3])
489         height -= (4 >> chroma) + 2;
490
491     dst = dst + (init_y * stride + init_x);
492     src = src + (init_y * stride + init_x);
493     init_y = init_x = 0;
494     if (sao_eo_class != SAO_EO_VERT) {
495         if (borders[0]) {
496             int offset_val = sao_offset_val[0];
497             int y_stride   = 0;
498             for (y = 0; y < height; y++) {
499                 dst[y_stride] = av_clip_pixel(src[y_stride] + offset_val);
500                 y_stride += stride;
501             }
502             init_x = 1;
503         }
504         if (borders[2]) {
505             int offset_val = sao_offset_val[0];
506             int x_stride   = width - 1;
507             for (x = 0; x < height; x++) {
508                 dst[x_stride] = av_clip_pixel(src[x_stride] + offset_val);
509                 x_stride += stride;
510             }
511             width --;
512         }
513
514     }
515     if (sao_eo_class != SAO_EO_HORIZ ) {
516         if (borders[1]){
517             int offset_val = sao_offset_val[0];
518             for (x = init_x; x < width; x++) {
519                 dst[x] = av_clip_pixel(src[x] + offset_val);
520             }
521             init_y = 1;
522         }
523         if (borders[3]){
524             int offset_val = sao_offset_val[0];
525             int y_stride   = stride * (height - 1);
526             for (x = init_x; x < width; x++) {
527                 dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + offset_val);
528             }
529             height--;
530         }
531     }
532     {
533         int y_stride     = init_y * stride;
534         int pos_0_0      = pos[sao_eo_class][0][0];
535         int pos_0_1      = pos[sao_eo_class][0][1];
536         int pos_1_0      = pos[sao_eo_class][1][0];
537         int pos_1_1      = pos[sao_eo_class][1][1];
538
539         int y_stride_0_1 = (init_y + pos_0_1) * stride;
540         int y_stride_1_1 = (init_y + pos_1_1) * stride;
541         for (y = init_y; y < height; y++) {
542             for (x = init_x; x < width; x++) {
543                 int diff0         = CMP(src[x + y_stride], src[x + pos_0_0 + y_stride_0_1]);
544                 int diff1         = CMP(src[x + y_stride], src[x + pos_1_0 + y_stride_1_1]);
545                 int offset_val    = edge_idx[2 + diff0 + diff1];
546                 dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + sao_offset_val[offset_val]);
547             }
548             y_stride     += stride;
549             y_stride_0_1 += stride;
550             y_stride_1_1 += stride;
551         }
552     }
553
554     {
555         // Restore pixels that can't be modified
556         int save_upper_left = !diag_edge && sao_eo_class == SAO_EO_135D && !borders[0] && !borders[1];
557         if (vert_edge && sao_eo_class != SAO_EO_VERT)
558             for (y = init_y+save_upper_left; y< height; y++)
559                 dst[y*stride] = src[y*stride];
560         if(horiz_edge && sao_eo_class != SAO_EO_HORIZ)
561             for(x = init_x+save_upper_left; x<width; x++)
562                 dst[x] = src[x];
563         if(diag_edge && sao_eo_class == SAO_EO_135D)
564             dst[0] = src[0];
565     }
566
567 #undef CMP
568 }
569
570 static void FUNC(sao_edge_filter_1)(uint8_t *_dst, uint8_t *_src,
571                                     ptrdiff_t _stride, SAOParams *sao,
572                                     int *borders, int _width, int _height,
573                                     int c_idx,
574                                     uint8_t vert_edge, uint8_t horiz_edge, uint8_t diag_edge)
575 {
576     int x, y;
577     pixel *dst = (pixel*)_dst;
578     pixel *src = (pixel*)_src;
579     ptrdiff_t stride = _stride / sizeof(pixel);
580     int chroma = !!c_idx;
581     int *sao_offset_val = sao->offset_val[c_idx];
582     int sao_eo_class = sao->eo_class[c_idx];
583
584     static const int8_t pos[4][2][2] = {
585         {{ -1,  0}, { 1, 0 }}, // horizontal
586         {{  0, -1}, { 0, 1 }}, // vertical
587         {{ -1, -1}, { 1, 1 }}, // 45 degree
588         {{  1, -1}, {-1, 1 }}, // 135 degree
589     };
590     static const uint8_t edge_idx[] = { 1, 2, 0, 3, 4 };
591
592     int init_x = 0, init_y = 0, width = _width, height = _height;
593
594 #define CMP(a, b) ((a) > (b) ? 1 : ((a) == (b) ? 0 : -1))
595
596     init_y = -(4 >> chroma) - 2;
597     if (!borders[2])
598         width -= (8 >> chroma) + 2;
599     height = (4 >> chroma) + 2;
600
601     dst = dst + (init_y * stride + init_x);
602     src = src + (init_y * stride + init_x);
603     init_y = init_x = 0;
604     if (sao_eo_class != SAO_EO_VERT) {
605         if (borders[0]) {
606             int offset_val = sao_offset_val[0];
607             int y_stride   = 0;
608             for (y = 0; y < height; y++) {
609                 dst[y_stride] = av_clip_pixel(src[y_stride] + offset_val);
610                 y_stride += stride;
611             }
612             init_x = 1;
613         }
614         if (borders[2]) {
615             int offset_val = sao_offset_val[0];
616             int x_stride   = width - 1;
617             for (x = 0; x < height; x++) {
618                 dst[x_stride] = av_clip_pixel(src[x_stride] + offset_val);
619                 x_stride += stride;
620             }
621             width--;
622         }
623
624     }
625     {
626         int y_stride     = init_y * stride;
627         int pos_0_0      = pos[sao_eo_class][0][0];
628         int pos_0_1      = pos[sao_eo_class][0][1];
629         int pos_1_0      = pos[sao_eo_class][1][0];
630         int pos_1_1      = pos[sao_eo_class][1][1];
631
632         int y_stride_0_1 = (init_y + pos_0_1) * stride;
633         int y_stride_1_1 = (init_y + pos_1_1) * stride;
634         for (y = init_y; y < height; y++) {
635             for (x = init_x; x < width; x++) {
636                 int diff0         = CMP(src[x + y_stride], src[x + pos_0_0 + y_stride_0_1]);
637                 int diff1         = CMP(src[x + y_stride], src[x + pos_1_0 + y_stride_1_1]);
638                 int offset_val    = edge_idx[2 + diff0 + diff1];
639                 dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + sao_offset_val[offset_val]);
640             }
641             y_stride     += stride;
642             y_stride_0_1 += stride;
643             y_stride_1_1 += stride;
644         }
645     }
646
647     {
648         // Restore pixels that can't be modified
649         int save_lower_left = !diag_edge && sao_eo_class == SAO_EO_45D && !borders[0];
650         if(vert_edge && sao_eo_class != SAO_EO_VERT)
651             for(y = init_y; y< height-save_lower_left; y++)
652                 dst[y*stride] = src[y*stride];
653         if(horiz_edge && sao_eo_class != SAO_EO_HORIZ)
654             for(x = init_x+save_lower_left; x<width; x++)
655                 dst[(height-1)*stride+x] = src[(height-1)*stride+x];
656         if(diag_edge && sao_eo_class == SAO_EO_45D)
657             dst[stride*(height-1)] = src[stride*(height-1)];
658     }
659
660 #undef CMP
661 }
662
663 static void FUNC(sao_edge_filter_2)(uint8_t *_dst, uint8_t *_src,
664                                     ptrdiff_t _stride, SAOParams *sao,
665                                     int *borders, int _width, int _height,
666                                     int c_idx,
667                                     uint8_t vert_edge, uint8_t horiz_edge, uint8_t diag_edge)
668 {
669     int x, y;
670     pixel *dst = (pixel*)_dst;
671     pixel *src = (pixel*)_src;
672     ptrdiff_t stride = _stride / sizeof(pixel);
673     int chroma = !!c_idx;
674     int *sao_offset_val = sao->offset_val[c_idx];
675     int sao_eo_class = sao->eo_class[c_idx];
676
677     static const int8_t pos[4][2][2] = {
678         {{ -1,  0}, { 1, 0}}, // horizontal
679         {{  0, -1}, { 0, 1}}, // vertical
680         {{ -1, -1}, { 1, 1}}, // 45 degree
681         {{  1, -1}, {-1, 1}}, // 135 degree
682     };
683     static const uint8_t edge_idx[] = { 1, 2, 0, 3, 4 };
684
685     int init_x = 0, init_y = 0, width = _width, height = _height;
686
687 #define CMP(a, b) ((a) > (b) ? 1 : ((a) == (b) ? 0 : -1))
688
689     init_x = -(8 >> chroma) - 2;
690     width  =  (8 >> chroma) + 2;
691     if (!borders[3])
692         height -= (4 >> chroma) + 2;
693
694     dst = dst + (init_y * stride + init_x);
695     src = src + (init_y * stride + init_x);
696     init_y = init_x = 0;
697     if (sao_eo_class != SAO_EO_HORIZ) {
698         if (borders[1]){
699             int offset_val = sao_offset_val[0];
700             for (x = init_x; x < width; x++) {
701                 dst[x] = av_clip_pixel(src[x] + offset_val);
702             }
703             init_y = 1;
704         }
705         if (borders[3]){
706             int offset_val = sao_offset_val[0];
707             int y_stride   = stride * (height - 1);
708             for (x = init_x; x < width; x++) {
709                 dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + offset_val);
710             }
711             height--;
712         }
713     }
714     {
715         int y_stride     = init_y * stride;
716         int pos_0_0      = pos[sao_eo_class][0][0];
717         int pos_0_1      = pos[sao_eo_class][0][1];
718         int pos_1_0      = pos[sao_eo_class][1][0];
719         int pos_1_1      = pos[sao_eo_class][1][1];
720
721         int y_stride_0_1 = (init_y + pos_0_1) * stride;
722         int y_stride_1_1 = (init_y + pos_1_1) * stride;
723         for (y = init_y; y < height; y++) {
724             for (x = init_x; x < width; x++) {
725                 int diff0         = CMP(src[x + y_stride], src[x + pos_0_0 + y_stride_0_1]);
726                 int diff1         = CMP(src[x + y_stride], src[x + pos_1_0 + y_stride_1_1]);
727                 int offset_val    = edge_idx[2 + diff0 + diff1];
728                 dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + sao_offset_val[offset_val]);
729             }
730             y_stride     += stride;
731             y_stride_0_1 += stride;
732             y_stride_1_1 += stride;
733         }
734     }
735
736     {
737         // Restore pixels that can't be modified
738         int save_upper_right = !diag_edge && sao_eo_class == SAO_EO_45D && !borders[1];
739         if(vert_edge && sao_eo_class != SAO_EO_VERT)
740             for(y = init_y+save_upper_right; y< height; y++)
741                 dst[y*stride+width-1] = src[y*stride+width-1];
742         if(horiz_edge && sao_eo_class != SAO_EO_HORIZ)
743             for(x = init_x; x<width-save_upper_right; x++)
744                 dst[x] = src[x];
745         if(diag_edge && sao_eo_class == SAO_EO_45D)
746             dst[width-1] = src[width-1];
747     }
748 #undef CMP
749 }
750
751 static void FUNC(sao_edge_filter_3)(uint8_t *_dst, uint8_t *_src,
752                                     ptrdiff_t _stride, SAOParams *sao,
753                                     int *borders, int _width, int _height,
754                                     int c_idx,
755                                     uint8_t vert_edge, uint8_t horiz_edge, uint8_t diag_edge)
756 {
757     int x, y;
758     pixel *dst = (pixel*)_dst;
759     pixel *src = (pixel*)_src;
760     ptrdiff_t stride = _stride / sizeof(pixel);
761     int chroma = !!c_idx;
762     int *sao_offset_val = sao->offset_val[c_idx];
763     int sao_eo_class    = sao->eo_class[c_idx];
764
765     static const int8_t pos[4][2][2] = {
766         {{ -1,  0}, { 1, 0}}, // horizontal
767         {{  0, -1}, { 0, 1}}, // vertical
768         {{ -1, -1}, { 1, 1}}, // 45 degree
769         {{  1, -1}, {-1, 1}}, // 135 degree
770     };
771     static const uint8_t edge_idx[] = { 1, 2, 0, 3, 4 };
772
773     int init_x = 0, init_y = 0, width = _width, height = _height;
774
775 #define CMP(a, b) ((a) > (b) ? 1 : ((a) == (b) ? 0 : -1))
776
777     init_y = -(4 >> chroma) - 2;
778     init_x = -(8 >> chroma) - 2;
779     width  =  (8 >> chroma) + 2;
780     height =  (4 >> chroma) + 2;
781
782
783     dst = dst + (init_y * stride + init_x);
784     src = src + (init_y * stride + init_x);
785     init_y = init_x = 0;
786
787     {
788         int y_stride     = init_y * stride;
789         int pos_0_0      = pos[sao_eo_class][0][0];
790         int pos_0_1      = pos[sao_eo_class][0][1];
791         int pos_1_0      = pos[sao_eo_class][1][0];
792         int pos_1_1      = pos[sao_eo_class][1][1];
793
794         int y_stride_0_1 = (init_y + pos_0_1) * stride;
795         int y_stride_1_1 = (init_y + pos_1_1) * stride;
796
797         for (y = init_y; y < height; y++) {
798             for (x = init_x; x < width; x++) {
799                 int diff0         = CMP(src[x + y_stride], src[x + pos_0_0 + y_stride_0_1]);
800                 int diff1         = CMP(src[x + y_stride], src[x + pos_1_0 + y_stride_1_1]);
801                 int offset_val    = edge_idx[2 + diff0 + diff1];
802                 dst[x + y_stride] = av_clip_pixel(src[x + y_stride] + sao_offset_val[offset_val]);
803             }
804             y_stride     += stride;
805             y_stride_0_1 += stride;
806             y_stride_1_1 += stride;
807         }
808     }
809
810     {
811         // Restore pixels that can't be modified
812         int save_lower_right = !diag_edge && sao_eo_class == SAO_EO_135D;
813         if(vert_edge && sao_eo_class != SAO_EO_VERT)
814             for(y = init_y; y< height-save_lower_right; y++)
815                 dst[y*stride+width-1] = src[y*stride+width-1];
816         if(horiz_edge && sao_eo_class != SAO_EO_HORIZ)
817             for(x = init_x; x<width-save_lower_right; x++)
818                 dst[(height-1)*stride+x] = src[(height-1)*stride+x];
819         if(diag_edge && sao_eo_class == SAO_EO_135D)
820             dst[stride*(height-1)+width-1] = src[stride*(height-1)+width-1];
821     }
822 #undef CMP
823 }
824
825 #undef SET
826 #undef SCALE
827 #undef ADD_AND_SCALE
828 #undef TR_4
829 #undef TR_4_1
830 #undef TR_4_2
831 #undef TR_8
832 #undef TR_8_1
833 #undef TR_8_2
834 #undef TR_16
835 #undef TR_16_1
836 #undef TR_16_2
837 #undef TR_32
838 #undef TR_32_1
839 #undef TR_32_2
840
841 static void FUNC(put_hevc_qpel_pixels)(int16_t *dst, ptrdiff_t dststride,
842                                        uint8_t *_src, ptrdiff_t _srcstride,
843                                        int width, int height, int16_t* mcbuffer)
844 {
845     int x, y;
846     pixel *src = (pixel*)_src;
847     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
848
849     for (y = 0; y < height; y++) {
850         for (x = 0; x < width; x++)
851             dst[x] = src[x] << (14 - BIT_DEPTH);
852         src += srcstride;
853         dst += dststride;
854     }
855 }
856
857 #define QPEL_FILTER_1(src, stride)                                              \
858     (-src[x-3*stride] + 4*src[x-2*stride] - 10*src[x-stride] + 58*src[x] +      \
859      17*src[x+stride] - 5*src[x+2*stride] + 1*src[x+3*stride])
860 #define QPEL_FILTER_2(src, stride)                                              \
861     (-src[x-3*stride] + 4*src[x-2*stride] - 11*src[x-stride] + 40*src[x] +      \
862      40*src[x+stride] - 11*src[x+2*stride] + 4*src[x+3*stride] - src[x+4*stride])
863 #define QPEL_FILTER_3(src, stride)                                              \
864     (src[x-2*stride] - 5*src[x-stride] + 17*src[x] + 58*src[x+stride]           \
865      - 10*src[x+2*stride] + 4*src[x+3*stride] - src[x+4*stride])
866
867
868 #define PUT_HEVC_QPEL_H(H)                                                     \
869 static void FUNC(put_hevc_qpel_h ## H)(int16_t *dst,  ptrdiff_t dststride,     \
870                                        uint8_t *_src, ptrdiff_t _srcstride,    \
871                                        int width, int height,                  \
872                                        int16_t* mcbuffer)                      \
873 {                                                                              \
874     int x, y;                                                                  \
875     pixel *src = (pixel*)_src;                                                 \
876     ptrdiff_t srcstride = _srcstride / sizeof(pixel);                          \
877                                                                                \
878     for (y = 0; y < height; y++) {                                             \
879         for (x = 0; x < width; x++)                                            \
880             dst[x] = QPEL_FILTER_ ## H (src, 1) >> (BIT_DEPTH - 8);            \
881         src += srcstride;                                                      \
882         dst += dststride;                                                      \
883     }                                                                          \
884 }
885
886 #define PUT_HEVC_QPEL_V(V)                                                     \
887 static void FUNC(put_hevc_qpel_v ## V)(int16_t *dst,  ptrdiff_t dststride,     \
888                                        uint8_t *_src, ptrdiff_t _srcstride,    \
889                                        int width, int height,                  \
890                                        int16_t* mcbuffer)                      \
891 {                                                                              \
892     int x, y;                                                                  \
893     pixel *src = (pixel*)_src;                                                 \
894     ptrdiff_t srcstride = _srcstride / sizeof(pixel);                          \
895                                                                                \
896     for (y = 0; y < height; y++)  {                                            \
897         for (x = 0; x < width; x++)                                            \
898             dst[x] = QPEL_FILTER_ ## V (src, srcstride) >> (BIT_DEPTH - 8);    \
899         src += srcstride;                                                      \
900         dst += dststride;                                                      \
901     }                                                                          \
902 }
903
904 #define PUT_HEVC_QPEL_HV(H, V)                                                       \
905 static void FUNC(put_hevc_qpel_h ## H ## v ## V)(int16_t *dst,  ptrdiff_t dststride, \
906                                                  uint8_t *_src, ptrdiff_t _srcstride,\
907                                                  int width, int height,              \
908                                                  int16_t* mcbuffer)                  \
909 {                                                                                    \
910     int x, y;                                                                        \
911     pixel *src = (pixel*)_src;                                                       \
912     ptrdiff_t srcstride = _srcstride / sizeof(pixel);                                \
913                                                                                      \
914     int16_t tmp_array[(MAX_PB_SIZE + 7)*MAX_PB_SIZE];                                \
915     int16_t *tmp = tmp_array;                                                        \
916                                                                                      \
917     src -= ff_hevc_qpel_extra_before[V] * srcstride;                                 \
918                                                                                      \
919     for (y = 0; y < height + ff_hevc_qpel_extra[V]; y++) {                           \
920         for (x = 0; x < width; x++)                                                  \
921             tmp[x] = QPEL_FILTER_ ## H (src, 1) >> (BIT_DEPTH - 8);                  \
922         src += srcstride;                                                            \
923         tmp += MAX_PB_SIZE;                                                          \
924     }                                                                                \
925                                                                                      \
926     tmp = tmp_array + ff_hevc_qpel_extra_before[V] * MAX_PB_SIZE;                    \
927                                                                                      \
928     for (y = 0; y < height; y++) {                                                   \
929         for (x = 0; x < width; x++)                                                  \
930             dst[x] = QPEL_FILTER_ ## V (tmp, MAX_PB_SIZE) >> 6;                      \
931         tmp += MAX_PB_SIZE;                                                          \
932         dst += dststride;                                                            \
933     }                                                                                \
934 }
935
936 PUT_HEVC_QPEL_H(1)
937 PUT_HEVC_QPEL_H(2)
938 PUT_HEVC_QPEL_H(3)
939 PUT_HEVC_QPEL_V(1)
940 PUT_HEVC_QPEL_V(2)
941 PUT_HEVC_QPEL_V(3)
942 PUT_HEVC_QPEL_HV(1, 1)
943 PUT_HEVC_QPEL_HV(1, 2)
944 PUT_HEVC_QPEL_HV(1, 3)
945 PUT_HEVC_QPEL_HV(2, 1)
946 PUT_HEVC_QPEL_HV(2, 2)
947 PUT_HEVC_QPEL_HV(2, 3)
948 PUT_HEVC_QPEL_HV(3, 1)
949 PUT_HEVC_QPEL_HV(3, 2)
950 PUT_HEVC_QPEL_HV(3, 3)
951
952 static void FUNC(put_hevc_epel_pixels)(int16_t *dst, ptrdiff_t dststride,
953                                        uint8_t *_src, ptrdiff_t _srcstride,
954                                        int width, int height, int mx, int my,
955                                        int16_t* mcbuffer)
956 {
957     int x, y;
958     pixel *src = (pixel*)_src;
959     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
960
961     for (y = 0; y < height; y++) {
962         for (x = 0; x < width; x++) {
963             dst[x] = src[x] << (14 - BIT_DEPTH);
964         }
965         src += srcstride;
966         dst += dststride;
967     }
968 }
969
970 #define EPEL_FILTER(src, stride) \
971     (filter_0*src[x-stride] + filter_1*src[x] + filter_2*src[x+stride] + filter_3*src[x+2*stride])
972
973 static void FUNC(put_hevc_epel_h)(int16_t *dst, ptrdiff_t dststride,
974                                   uint8_t *_src, ptrdiff_t _srcstride,
975                                   int width, int height, int mx, int my,
976                                   int16_t* mcbuffer)
977 {
978     int x, y;
979     pixel *src = (pixel*)_src;
980     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
981     const int8_t *filter = ff_hevc_epel_filters[mx - 1];
982     int8_t filter_0 = filter[0];
983     int8_t filter_1 = filter[1];
984     int8_t filter_2 = filter[2];
985     int8_t filter_3 = filter[3];
986     for (y = 0; y < height; y++) {
987         for (x = 0; x < width; x++) {
988             dst[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8);
989         }
990         src += srcstride;
991         dst += dststride;
992     }
993 }
994
995 static void FUNC(put_hevc_epel_v)(int16_t *dst, ptrdiff_t dststride,
996                                   uint8_t *_src, ptrdiff_t _srcstride,
997                                   int width, int height, int mx, int my,
998                                   int16_t* mcbuffer)
999 {
1000     int x, y;
1001     pixel *src = (pixel*)_src;
1002     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
1003     const int8_t *filter = ff_hevc_epel_filters[my-1];
1004     int8_t filter_0 = filter[0];
1005     int8_t filter_1 = filter[1];
1006     int8_t filter_2 = filter[2];
1007     int8_t filter_3 = filter[3];
1008
1009     for (y = 0; y < height; y++) {
1010         for (x = 0; x < width; x++) {
1011             dst[x] = EPEL_FILTER(src, srcstride) >> (BIT_DEPTH - 8);
1012         }
1013         src += srcstride;
1014         dst += dststride;
1015     }
1016 }
1017
1018 static void FUNC(put_hevc_epel_hv)(int16_t *dst, ptrdiff_t dststride,
1019                                    uint8_t *_src, ptrdiff_t _srcstride,
1020                                    int width, int height, int mx, int my,
1021                                    int16_t* mcbuffer)
1022 {
1023     int x, y;
1024     pixel *src = (pixel*)_src;
1025     ptrdiff_t srcstride = _srcstride / sizeof(pixel);
1026     const int8_t *filter_h = ff_hevc_epel_filters[mx-1];
1027     const int8_t *filter_v = ff_hevc_epel_filters[my-1];
1028     int8_t filter_0 = filter_h[0];
1029     int8_t filter_1 = filter_h[1];
1030     int8_t filter_2 = filter_h[2];
1031     int8_t filter_3 = filter_h[3];
1032     int16_t tmp_array[(MAX_PB_SIZE + 3)*MAX_PB_SIZE];
1033     int16_t *tmp = tmp_array;
1034
1035     src -= EPEL_EXTRA_BEFORE * srcstride;
1036
1037     for (y = 0; y < height + EPEL_EXTRA; y++) {
1038         for (x = 0; x < width; x++) {
1039             tmp[x] = EPEL_FILTER(src, 1) >> (BIT_DEPTH - 8);
1040         }
1041         src += srcstride;
1042         tmp += MAX_PB_SIZE;
1043     }
1044
1045     tmp = tmp_array + EPEL_EXTRA_BEFORE * MAX_PB_SIZE;
1046     filter_0 = filter_v[0];
1047     filter_1 = filter_v[1];
1048     filter_2 = filter_v[2];
1049     filter_3 = filter_v[3];
1050     for (y = 0; y < height; y++) {
1051         for (x = 0; x < width; x++) {
1052             dst[x] = EPEL_FILTER(tmp, MAX_PB_SIZE) >> 6;
1053         }
1054         tmp += MAX_PB_SIZE;
1055         dst += dststride;
1056     }
1057 }
1058
1059 static void FUNC(put_unweighted_pred)(uint8_t *_dst, ptrdiff_t _dststride,
1060                                       int16_t *src, ptrdiff_t srcstride,
1061                                       int width, int height)
1062 {
1063     int x, y;
1064     pixel *dst = (pixel*)_dst;
1065     ptrdiff_t dststride = _dststride / sizeof(pixel);
1066
1067     int shift = 14 - BIT_DEPTH;
1068 #if BIT_DEPTH < 14
1069     int offset = 1 << (shift - 1);
1070 #else
1071     int offset = 0;
1072 #endif
1073     for (y = 0; y < height; y++) {
1074         for (x = 0; x < width; x++) {
1075             dst[x] = av_clip_pixel((src[x] + offset) >> shift);
1076         }
1077         dst += dststride;
1078         src += srcstride;
1079     }
1080 }
1081
1082 static void FUNC(put_weighted_pred_avg)(uint8_t *_dst, ptrdiff_t _dststride,
1083                                         int16_t *src1, int16_t *src2,
1084                                         ptrdiff_t srcstride,
1085                                         int width, int height)
1086 {
1087     int x, y;
1088     pixel *dst = (pixel*)_dst;
1089     ptrdiff_t dststride = _dststride / sizeof(pixel);
1090
1091     int shift = 14 + 1 - BIT_DEPTH;
1092 #if BIT_DEPTH < 14
1093     int offset = 1 << (shift - 1);
1094 #else
1095     int offset = 0;
1096 #endif
1097
1098     for (y = 0; y < height; y++) {
1099         for (x = 0; x < width; x++) {
1100             dst[x] = av_clip_pixel((src1[x] + src2[x] + offset) >> shift);
1101         }
1102         dst  += dststride;
1103         src1 += srcstride;
1104         src2 += srcstride;
1105     }
1106 }
1107
1108 static void FUNC(weighted_pred)(uint8_t denom, int16_t wlxFlag, int16_t olxFlag,
1109                                 uint8_t *_dst, ptrdiff_t _dststride,
1110                                 int16_t *src, ptrdiff_t srcstride,
1111                                 int width, int height)
1112 {
1113     int shift;
1114     int log2Wd;
1115     int wx;
1116     int ox;
1117     int x , y;
1118     int offset;
1119     pixel *dst = (pixel*)_dst;
1120     ptrdiff_t dststride = _dststride / sizeof(pixel);
1121
1122     shift  = 14 - BIT_DEPTH;
1123     log2Wd = denom + shift;
1124     offset = 1 << (log2Wd - 1);
1125     wx = wlxFlag;
1126     ox = olxFlag * (1 << (BIT_DEPTH - 8));
1127
1128     for (y = 0; y < height; y++) {
1129         for (x = 0; x < width; x++) {
1130             if (log2Wd >= 1) {
1131                 dst[x] = av_clip_pixel(((src[x] * wx + offset) >> log2Wd) + ox);
1132             } else {
1133                 dst[x] = av_clip_pixel(src[x] * wx + ox);
1134             }
1135         }
1136         dst  += dststride;
1137         src  += srcstride;
1138     }
1139 }
1140
1141 static void FUNC(weighted_pred_avg)(uint8_t denom, int16_t wl0Flag, int16_t wl1Flag,
1142                                     int16_t ol0Flag, int16_t ol1Flag,
1143                                     uint8_t *_dst, ptrdiff_t _dststride,
1144                                     int16_t *src1, int16_t *src2, ptrdiff_t srcstride,
1145                                     int width, int height)
1146 {
1147     int shift;
1148     int log2Wd;
1149     int w0;
1150     int w1;
1151     int o0;
1152     int o1;
1153     int x , y;
1154     pixel *dst = (pixel*)_dst;
1155     ptrdiff_t dststride = _dststride / sizeof(pixel);
1156
1157     shift  = 14 - BIT_DEPTH;
1158     log2Wd = denom + shift;
1159     w0 = wl0Flag;
1160     w1 = wl1Flag;
1161     o0 = (ol0Flag) * (1 << (BIT_DEPTH - 8));
1162     o1 = (ol1Flag) * (1 << (BIT_DEPTH - 8));
1163
1164     for (y = 0; y < height; y++) {
1165         for (x = 0; x < width; x++) {
1166             dst[x] = av_clip_pixel((src1[x] * w0 + src2[x] * w1 +
1167                                     ((o0 + o1 + 1) << log2Wd)) >> (log2Wd + 1));
1168         }
1169         dst  += dststride;
1170         src1 += srcstride;
1171         src2 += srcstride;
1172     }
1173 }
1174
1175 // line zero
1176 #define P3 pix[-4*xstride]
1177 #define P2 pix[-3*xstride]
1178 #define P1 pix[-2*xstride]
1179 #define P0 pix[-xstride]
1180 #define Q0 pix[0]
1181 #define Q1 pix[xstride]
1182 #define Q2 pix[2*xstride]
1183 #define Q3 pix[3*xstride]
1184
1185 // line three. used only for deblocking decision
1186 #define TP3 pix[-4*xstride+3*ystride]
1187 #define TP2 pix[-3*xstride+3*ystride]
1188 #define TP1 pix[-2*xstride+3*ystride]
1189 #define TP0 pix[-xstride+3*ystride]
1190 #define TQ0 pix[3*ystride]
1191 #define TQ1 pix[xstride+3*ystride]
1192 #define TQ2 pix[2*xstride+3*ystride]
1193 #define TQ3 pix[3*xstride+3*ystride]
1194
1195 static void FUNC(hevc_loop_filter_luma)(uint8_t *_pix, ptrdiff_t _xstride,
1196                                         ptrdiff_t _ystride, int *_beta, int *_tc,
1197                                         uint8_t *_no_p, uint8_t *_no_q)
1198 {
1199     int d, j;
1200     pixel *pix = (pixel*)_pix;
1201     ptrdiff_t xstride = _xstride / sizeof(pixel);
1202     ptrdiff_t ystride = _ystride / sizeof(pixel);
1203
1204     for (j = 0; j < 2; j++) {
1205         const int dp0  = abs(P2 - 2 * P1 +  P0);
1206         const int dq0  = abs(Q2 - 2 * Q1 +  Q0);
1207         const int dp3  = abs(TP2 - 2 * TP1 + TP0);
1208         const int dq3  = abs(TQ2 - 2 * TQ1 + TQ0);
1209         const int d0   = dp0 + dq0;
1210         const int d3   = dp3 + dq3;
1211         int       beta = _beta[j] << (BIT_DEPTH - 8);
1212         const int tc   = _tc[j] << (BIT_DEPTH - 8);
1213         const int no_p = _no_p[j];
1214         const int no_q = _no_q[j];
1215
1216         if (d0 + d3 >= beta /*|| tc <= 0*/) {
1217             pix += 4 * ystride;
1218             continue;
1219         } else {
1220             const int beta_3 = beta >> 3;
1221             const int beta_2 = beta >> 2;
1222             const int tc25 = ((tc * 5 + 1) >> 1);
1223
1224             if (abs( P3 -  P0) + abs( Q3 -  Q0) < beta_3 && abs( P0 -  Q0) < tc25 &&
1225                 abs(TP3 - TP0) + abs(TQ3 - TQ0) < beta_3 && abs(TP0 - TQ0) < tc25 &&
1226                                       (d0 << 1) < beta_2 &&      (d3 << 1) < beta_2) {
1227                 // strong filtering
1228                 const int tc2 = tc << 1;
1229                 for (d = 0; d < 4; d++) {
1230                     const int p3 = P3;
1231                     const int p2 = P2;
1232                     const int p1 = P1;
1233                     const int p0 = P0;
1234                     const int q0 = Q0;
1235                     const int q1 = Q1;
1236                     const int q2 = Q2;
1237                     const int q3 = Q3;
1238                     if (!no_p) {
1239                         P0 = p0 + av_clip((( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3) - p0, -tc2, tc2);
1240                         P1 = p1 + av_clip((( p2 + p1 + p0 + q0 + 2 ) >> 2) - p1, -tc2, tc2);
1241                         P2 = p2 + av_clip((( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3) - p2, -tc2, tc2);
1242                     }
1243                     if (!no_q) {
1244                         Q0 = q0 + av_clip((( p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 ) >> 3) - q0, -tc2, tc2);
1245                         Q1 = q1 + av_clip((( p0 + q0 + q1 + q2 + 2 ) >> 2) - q1, -tc2, tc2);
1246                         Q2 = q2 + av_clip((( 2*q3 + 3*q2 + q1 + q0 + p0 + 4 ) >> 3) - q2, -tc2, tc2);
1247                     }
1248                     pix += ystride;
1249                 }
1250             } else { // normal filtering
1251                 int nd_p = 1;
1252                 int nd_q = 1;
1253                 const int tc_2 = tc >> 1;
1254                 if (dp0 + dp3 < ((beta + (beta >> 1)) >> 3))
1255                     nd_p = 2;
1256                 if (dq0 + dq3 < ((beta + (beta >> 1)) >> 3))
1257                     nd_q = 2;
1258
1259                 for (d = 0; d < 4; d++) {
1260                     const int p2 = P2;
1261                     const int p1 = P1;
1262                     const int p0 = P0;
1263                     const int q0 = Q0;
1264                     const int q1 = Q1;
1265                     const int q2 = Q2;
1266                     int delta0 = (9 * (q0 - p0) - 3 * (q1 - p1) + 8) >> 4;
1267                     if (abs(delta0) < 10 * tc) {
1268                         delta0 = av_clip(delta0, -tc, tc);
1269                         if (!no_p)
1270                             P0 = av_clip_pixel(p0 + delta0);
1271                         if (!no_q)
1272                             Q0 = av_clip_pixel(q0 - delta0);
1273                         if (!no_p && nd_p > 1) {
1274                             const int deltap1 = av_clip((((p2 + p0 + 1) >> 1) - p1 + delta0) >> 1, -tc_2, tc_2);
1275                             P1 = av_clip_pixel(p1 + deltap1);
1276                         }
1277                         if (!no_q && nd_q > 1) {
1278                             const int deltaq1 = av_clip((((q2 + q0 + 1) >> 1) - q1 - delta0) >> 1, -tc_2, tc_2);
1279                             Q1 = av_clip_pixel(q1 + deltaq1);
1280                         }
1281                     }
1282                     pix += ystride;
1283                 }
1284             }
1285         }
1286     }
1287 }
1288
1289 static void FUNC(hevc_loop_filter_chroma)(uint8_t *_pix, ptrdiff_t _xstride,
1290                                           ptrdiff_t _ystride, int *_tc,
1291                                           uint8_t *_no_p, uint8_t *_no_q)
1292 {
1293     int d, j;
1294     int no_p, no_q;
1295     pixel *pix = (pixel*)_pix;
1296     ptrdiff_t xstride = _xstride / sizeof(pixel);
1297     ptrdiff_t ystride = _ystride / sizeof(pixel);
1298
1299     for (j = 0; j < 2; j++) {
1300         const int tc = _tc[j] << (BIT_DEPTH - 8);
1301         if (tc <= 0) {
1302             pix += 4 * ystride;
1303             continue;
1304         }
1305         no_p = _no_p[j];
1306         no_q = _no_q[j];
1307
1308         for (d = 0; d < 4; d++) {
1309             int delta0;
1310             const int p1 = P1;
1311             const int p0 = P0;
1312             const int q0 = Q0;
1313             const int q1 = Q1;
1314             delta0 = av_clip((((q0 - p0) << 2) + p1 - q1 + 4) >> 3, -tc, tc);
1315             if (!no_p)
1316                 P0 = av_clip_pixel(p0 + delta0);
1317             if (!no_q)
1318                 Q0 = av_clip_pixel(q0 - delta0);
1319             pix += ystride;
1320         }
1321     }
1322 }
1323
1324 static void FUNC(hevc_h_loop_filter_chroma)(uint8_t *pix, ptrdiff_t stride,
1325                                             int *tc, uint8_t *no_p, uint8_t *no_q)
1326 {
1327     FUNC(hevc_loop_filter_chroma)(pix, stride, sizeof(pixel), tc, no_p, no_q);
1328 }
1329
1330 static void FUNC(hevc_v_loop_filter_chroma)(uint8_t *pix, ptrdiff_t stride,
1331                                             int *tc, uint8_t *no_p, uint8_t *no_q)
1332 {
1333     FUNC(hevc_loop_filter_chroma)(pix, sizeof(pixel), stride, tc, no_p, no_q);
1334 }
1335
1336 static void FUNC(hevc_h_loop_filter_luma)(uint8_t *pix, ptrdiff_t stride,
1337                                           int *beta, int *tc, uint8_t *no_p,
1338                                           uint8_t *no_q)
1339 {
1340     FUNC(hevc_loop_filter_luma)(pix, stride, sizeof(pixel), beta, tc, no_p, no_q);
1341 }
1342
1343 static void FUNC(hevc_v_loop_filter_luma)(uint8_t *pix, ptrdiff_t stride,
1344                                           int *beta, int *tc, uint8_t *no_p,
1345                                           uint8_t *no_q)
1346 {
1347     FUNC(hevc_loop_filter_luma)(pix, sizeof(pixel), stride, beta, tc, no_p, no_q);
1348 }
1349
1350 #undef P3
1351 #undef P2
1352 #undef P1
1353 #undef P0
1354 #undef Q0
1355 #undef Q1
1356 #undef Q2
1357 #undef Q3
1358
1359 #undef TP3
1360 #undef TP2
1361 #undef TP1
1362 #undef TP0
1363 #undef TQ0
1364 #undef TQ1
1365 #undef TQ2
1366 #undef TQ3