1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * HEVC video decoder
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * Copyright (C) 2012 - 2013 Guillaume Martres
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * This file is part of FFmpeg.
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
12cabdff1aSopenharmony_ci *
13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16cabdff1aSopenharmony_ci * Lesser General Public License for more details.
17cabdff1aSopenharmony_ci *
18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21cabdff1aSopenharmony_ci */
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_ci#include "libavutil/pixdesc.h"
24cabdff1aSopenharmony_ci
25cabdff1aSopenharmony_ci#include "bit_depth_template.c"
26cabdff1aSopenharmony_ci#include "hevcpred.h"
27cabdff1aSopenharmony_ci
28cabdff1aSopenharmony_ci#define POS(x, y) src[(x) + stride * (y)]
29cabdff1aSopenharmony_ci
30cabdff1aSopenharmony_cistatic av_always_inline void FUNC(intra_pred)(HEVCContext *s, int x0, int y0,
31cabdff1aSopenharmony_ci                                              int log2_size, int c_idx)
32cabdff1aSopenharmony_ci{
33cabdff1aSopenharmony_ci#define PU(x) \
34cabdff1aSopenharmony_ci    ((x) >> s->ps.sps->log2_min_pu_size)
35cabdff1aSopenharmony_ci#define MVF(x, y) \
36cabdff1aSopenharmony_ci    (s->ref->tab_mvf[(x) + (y) * min_pu_width])
37cabdff1aSopenharmony_ci#define MVF_PU(x, y) \
38cabdff1aSopenharmony_ci    MVF(PU(x0 + ((x) * (1 << hshift))), PU(y0 + ((y) * (1 << vshift))))
39cabdff1aSopenharmony_ci#define IS_INTRA(x, y) \
40cabdff1aSopenharmony_ci    (MVF_PU(x, y).pred_flag == PF_INTRA)
41cabdff1aSopenharmony_ci#define MIN_TB_ADDR_ZS(x, y) \
42cabdff1aSopenharmony_ci    s->ps.pps->min_tb_addr_zs[(y) * (s->ps.sps->tb_mask+2) + (x)]
43cabdff1aSopenharmony_ci#define EXTEND(ptr, val, len)         \
44cabdff1aSopenharmony_cido {                                  \
45cabdff1aSopenharmony_ci    pixel4 pix = PIXEL_SPLAT_X4(val); \
46cabdff1aSopenharmony_ci    for (i = 0; i < (len); i += 4)    \
47cabdff1aSopenharmony_ci        AV_WN4P(ptr + i, pix);        \
48cabdff1aSopenharmony_ci} while (0)
49cabdff1aSopenharmony_ci
50cabdff1aSopenharmony_ci#define EXTEND_RIGHT_CIP(ptr, start, length)                                   \
51cabdff1aSopenharmony_ci        for (i = start; i < (start) + (length); i += 4)                        \
52cabdff1aSopenharmony_ci            if (!IS_INTRA(i, -1))                                              \
53cabdff1aSopenharmony_ci                AV_WN4P(&ptr[i], a);                                           \
54cabdff1aSopenharmony_ci            else                                                               \
55cabdff1aSopenharmony_ci                a = PIXEL_SPLAT_X4(ptr[i+3])
56cabdff1aSopenharmony_ci#define EXTEND_LEFT_CIP(ptr, start, length) \
57cabdff1aSopenharmony_ci        for (i = start; i > (start) - (length); i--) \
58cabdff1aSopenharmony_ci            if (!IS_INTRA(i - 1, -1)) \
59cabdff1aSopenharmony_ci                ptr[i - 1] = ptr[i]
60cabdff1aSopenharmony_ci#define EXTEND_UP_CIP(ptr, start, length)                                      \
61cabdff1aSopenharmony_ci        for (i = (start); i > (start) - (length); i -= 4)                      \
62cabdff1aSopenharmony_ci            if (!IS_INTRA(-1, i - 3))                                          \
63cabdff1aSopenharmony_ci                AV_WN4P(&ptr[i - 3], a);                                       \
64cabdff1aSopenharmony_ci            else                                                               \
65cabdff1aSopenharmony_ci                a = PIXEL_SPLAT_X4(ptr[i - 3])
66cabdff1aSopenharmony_ci#define EXTEND_DOWN_CIP(ptr, start, length)                                    \
67cabdff1aSopenharmony_ci        for (i = start; i < (start) + (length); i += 4)                        \
68cabdff1aSopenharmony_ci            if (!IS_INTRA(-1, i))                                              \
69cabdff1aSopenharmony_ci                AV_WN4P(&ptr[i], a);                                           \
70cabdff1aSopenharmony_ci            else                                                               \
71cabdff1aSopenharmony_ci                a = PIXEL_SPLAT_X4(ptr[i + 3])
72cabdff1aSopenharmony_ci
73cabdff1aSopenharmony_ci    HEVCLocalContext *lc = s->HEVClc;
74cabdff1aSopenharmony_ci    int i;
75cabdff1aSopenharmony_ci    int hshift = s->ps.sps->hshift[c_idx];
76cabdff1aSopenharmony_ci    int vshift = s->ps.sps->vshift[c_idx];
77cabdff1aSopenharmony_ci    int size = (1 << log2_size);
78cabdff1aSopenharmony_ci    int size_in_luma_h = size << hshift;
79cabdff1aSopenharmony_ci    int size_in_tbs_h  = size_in_luma_h >> s->ps.sps->log2_min_tb_size;
80cabdff1aSopenharmony_ci    int size_in_luma_v = size << vshift;
81cabdff1aSopenharmony_ci    int size_in_tbs_v  = size_in_luma_v >> s->ps.sps->log2_min_tb_size;
82cabdff1aSopenharmony_ci    int x = x0 >> hshift;
83cabdff1aSopenharmony_ci    int y = y0 >> vshift;
84cabdff1aSopenharmony_ci    int x_tb = (x0 >> s->ps.sps->log2_min_tb_size) & s->ps.sps->tb_mask;
85cabdff1aSopenharmony_ci    int y_tb = (y0 >> s->ps.sps->log2_min_tb_size) & s->ps.sps->tb_mask;
86cabdff1aSopenharmony_ci    int spin = c_idx && !size_in_tbs_v && ((2 * y0) & (1 << s->ps.sps->log2_min_tb_size));
87cabdff1aSopenharmony_ci
88cabdff1aSopenharmony_ci    int cur_tb_addr = MIN_TB_ADDR_ZS(x_tb, y_tb);
89cabdff1aSopenharmony_ci
90cabdff1aSopenharmony_ci    ptrdiff_t stride = s->frame->linesize[c_idx] / sizeof(pixel);
91cabdff1aSopenharmony_ci    pixel *src = (pixel*)s->frame->data[c_idx] + x + y * stride;
92cabdff1aSopenharmony_ci
93cabdff1aSopenharmony_ci    int min_pu_width = s->ps.sps->min_pu_width;
94cabdff1aSopenharmony_ci
95cabdff1aSopenharmony_ci    enum IntraPredMode mode = c_idx ? lc->tu.intra_pred_mode_c :
96cabdff1aSopenharmony_ci                              lc->tu.intra_pred_mode;
97cabdff1aSopenharmony_ci    pixel4 a;
98cabdff1aSopenharmony_ci    pixel  left_array[2 * MAX_TB_SIZE + 1];
99cabdff1aSopenharmony_ci    pixel  filtered_left_array[2 * MAX_TB_SIZE + 1];
100cabdff1aSopenharmony_ci    pixel  top_array[2 * MAX_TB_SIZE + 1];
101cabdff1aSopenharmony_ci    pixel  filtered_top_array[2 * MAX_TB_SIZE + 1];
102cabdff1aSopenharmony_ci
103cabdff1aSopenharmony_ci    pixel  *left          = left_array + 1;
104cabdff1aSopenharmony_ci    pixel  *top           = top_array  + 1;
105cabdff1aSopenharmony_ci    pixel  *filtered_left = filtered_left_array + 1;
106cabdff1aSopenharmony_ci    pixel  *filtered_top  = filtered_top_array  + 1;
107cabdff1aSopenharmony_ci    int cand_bottom_left = lc->na.cand_bottom_left && cur_tb_addr > MIN_TB_ADDR_ZS( x_tb - 1, (y_tb + size_in_tbs_v + spin) & s->ps.sps->tb_mask);
108cabdff1aSopenharmony_ci    int cand_left        = lc->na.cand_left;
109cabdff1aSopenharmony_ci    int cand_up_left     = lc->na.cand_up_left;
110cabdff1aSopenharmony_ci    int cand_up          = lc->na.cand_up;
111cabdff1aSopenharmony_ci    int cand_up_right    = lc->na.cand_up_right && !spin && cur_tb_addr > MIN_TB_ADDR_ZS((x_tb + size_in_tbs_h) & s->ps.sps->tb_mask, y_tb - 1);
112cabdff1aSopenharmony_ci
113cabdff1aSopenharmony_ci    int bottom_left_size = (FFMIN(y0 + 2 * size_in_luma_v, s->ps.sps->height) -
114cabdff1aSopenharmony_ci                           (y0 + size_in_luma_v)) >> vshift;
115cabdff1aSopenharmony_ci    int top_right_size   = (FFMIN(x0 + 2 * size_in_luma_h, s->ps.sps->width) -
116cabdff1aSopenharmony_ci                           (x0 + size_in_luma_h)) >> hshift;
117cabdff1aSopenharmony_ci
118cabdff1aSopenharmony_ci    if (s->ps.pps->constrained_intra_pred_flag == 1) {
119cabdff1aSopenharmony_ci        int size_in_luma_pu_v = PU(size_in_luma_v);
120cabdff1aSopenharmony_ci        int size_in_luma_pu_h = PU(size_in_luma_h);
121cabdff1aSopenharmony_ci        int on_pu_edge_x    = !av_mod_uintp2(x0, s->ps.sps->log2_min_pu_size);
122cabdff1aSopenharmony_ci        int on_pu_edge_y    = !av_mod_uintp2(y0, s->ps.sps->log2_min_pu_size);
123cabdff1aSopenharmony_ci        if (!size_in_luma_pu_h)
124cabdff1aSopenharmony_ci            size_in_luma_pu_h++;
125cabdff1aSopenharmony_ci        if (cand_bottom_left == 1 && on_pu_edge_x) {
126cabdff1aSopenharmony_ci            int x_left_pu   = PU(x0 - 1);
127cabdff1aSopenharmony_ci            int y_bottom_pu = PU(y0 + size_in_luma_v);
128cabdff1aSopenharmony_ci            int max = FFMIN(size_in_luma_pu_v, s->ps.sps->min_pu_height - y_bottom_pu);
129cabdff1aSopenharmony_ci            cand_bottom_left = 0;
130cabdff1aSopenharmony_ci            for (i = 0; i < max; i += 2)
131cabdff1aSopenharmony_ci                cand_bottom_left |= (MVF(x_left_pu, y_bottom_pu + i).pred_flag == PF_INTRA);
132cabdff1aSopenharmony_ci        }
133cabdff1aSopenharmony_ci        if (cand_left == 1 && on_pu_edge_x) {
134cabdff1aSopenharmony_ci            int x_left_pu   = PU(x0 - 1);
135cabdff1aSopenharmony_ci            int y_left_pu   = PU(y0);
136cabdff1aSopenharmony_ci            int max = FFMIN(size_in_luma_pu_v, s->ps.sps->min_pu_height - y_left_pu);
137cabdff1aSopenharmony_ci            cand_left = 0;
138cabdff1aSopenharmony_ci            for (i = 0; i < max; i += 2)
139cabdff1aSopenharmony_ci                cand_left |= (MVF(x_left_pu, y_left_pu + i).pred_flag == PF_INTRA);
140cabdff1aSopenharmony_ci        }
141cabdff1aSopenharmony_ci        if (cand_up_left == 1) {
142cabdff1aSopenharmony_ci            int x_left_pu   = PU(x0 - 1);
143cabdff1aSopenharmony_ci            int y_top_pu    = PU(y0 - 1);
144cabdff1aSopenharmony_ci            cand_up_left = MVF(x_left_pu, y_top_pu).pred_flag == PF_INTRA;
145cabdff1aSopenharmony_ci        }
146cabdff1aSopenharmony_ci        if (cand_up == 1 && on_pu_edge_y) {
147cabdff1aSopenharmony_ci            int x_top_pu    = PU(x0);
148cabdff1aSopenharmony_ci            int y_top_pu    = PU(y0 - 1);
149cabdff1aSopenharmony_ci            int max = FFMIN(size_in_luma_pu_h, s->ps.sps->min_pu_width - x_top_pu);
150cabdff1aSopenharmony_ci            cand_up = 0;
151cabdff1aSopenharmony_ci            for (i = 0; i < max; i += 2)
152cabdff1aSopenharmony_ci                cand_up |= (MVF(x_top_pu + i, y_top_pu).pred_flag == PF_INTRA);
153cabdff1aSopenharmony_ci        }
154cabdff1aSopenharmony_ci        if (cand_up_right == 1 && on_pu_edge_y) {
155cabdff1aSopenharmony_ci            int y_top_pu    = PU(y0 - 1);
156cabdff1aSopenharmony_ci            int x_right_pu  = PU(x0 + size_in_luma_h);
157cabdff1aSopenharmony_ci            int max = FFMIN(size_in_luma_pu_h, s->ps.sps->min_pu_width - x_right_pu);
158cabdff1aSopenharmony_ci            cand_up_right = 0;
159cabdff1aSopenharmony_ci            for (i = 0; i < max; i += 2)
160cabdff1aSopenharmony_ci                cand_up_right |= (MVF(x_right_pu + i, y_top_pu).pred_flag == PF_INTRA);
161cabdff1aSopenharmony_ci        }
162cabdff1aSopenharmony_ci        memset(left, 128, 2 * MAX_TB_SIZE*sizeof(pixel));
163cabdff1aSopenharmony_ci        memset(top , 128, 2 * MAX_TB_SIZE*sizeof(pixel));
164cabdff1aSopenharmony_ci        top[-1] = 128;
165cabdff1aSopenharmony_ci    }
166cabdff1aSopenharmony_ci    if (cand_up_left) {
167cabdff1aSopenharmony_ci        left[-1] = POS(-1, -1);
168cabdff1aSopenharmony_ci        top[-1]  = left[-1];
169cabdff1aSopenharmony_ci    }
170cabdff1aSopenharmony_ci    if (cand_up)
171cabdff1aSopenharmony_ci        memcpy(top, src - stride, size * sizeof(pixel));
172cabdff1aSopenharmony_ci    if (cand_up_right) {
173cabdff1aSopenharmony_ci        memcpy(top + size, src - stride + size, size * sizeof(pixel));
174cabdff1aSopenharmony_ci        EXTEND(top + size + top_right_size, POS(size + top_right_size - 1, -1),
175cabdff1aSopenharmony_ci               size - top_right_size);
176cabdff1aSopenharmony_ci    }
177cabdff1aSopenharmony_ci    if (cand_left)
178cabdff1aSopenharmony_ci        for (i = 0; i < size; i++)
179cabdff1aSopenharmony_ci            left[i] = POS(-1, i);
180cabdff1aSopenharmony_ci    if (cand_bottom_left) {
181cabdff1aSopenharmony_ci        for (i = size; i < size + bottom_left_size; i++)
182cabdff1aSopenharmony_ci            left[i] = POS(-1, i);
183cabdff1aSopenharmony_ci        EXTEND(left + size + bottom_left_size, POS(-1, size + bottom_left_size - 1),
184cabdff1aSopenharmony_ci               size - bottom_left_size);
185cabdff1aSopenharmony_ci    }
186cabdff1aSopenharmony_ci
187cabdff1aSopenharmony_ci    if (s->ps.pps->constrained_intra_pred_flag == 1) {
188cabdff1aSopenharmony_ci        if (cand_bottom_left || cand_left || cand_up_left || cand_up || cand_up_right) {
189cabdff1aSopenharmony_ci            int size_max_x = x0 + ((2 * size) << hshift) < s->ps.sps->width ?
190cabdff1aSopenharmony_ci                                    2 * size : (s->ps.sps->width - x0) >> hshift;
191cabdff1aSopenharmony_ci            int size_max_y = y0 + ((2 * size) << vshift) < s->ps.sps->height ?
192cabdff1aSopenharmony_ci                                    2 * size : (s->ps.sps->height - y0) >> vshift;
193cabdff1aSopenharmony_ci            int j = size + (cand_bottom_left? bottom_left_size: 0) -1;
194cabdff1aSopenharmony_ci            if (!cand_up_right) {
195cabdff1aSopenharmony_ci                size_max_x = x0 + ((size) << hshift) < s->ps.sps->width ?
196cabdff1aSopenharmony_ci                                                    size : (s->ps.sps->width - x0) >> hshift;
197cabdff1aSopenharmony_ci            }
198cabdff1aSopenharmony_ci            if (!cand_bottom_left) {
199cabdff1aSopenharmony_ci                size_max_y = y0 + (( size) << vshift) < s->ps.sps->height ?
200cabdff1aSopenharmony_ci                                                     size : (s->ps.sps->height - y0) >> vshift;
201cabdff1aSopenharmony_ci            }
202cabdff1aSopenharmony_ci            if (cand_bottom_left || cand_left || cand_up_left) {
203cabdff1aSopenharmony_ci                while (j > -1 && !IS_INTRA(-1, j))
204cabdff1aSopenharmony_ci                    j--;
205cabdff1aSopenharmony_ci                if (!IS_INTRA(-1, j)) {
206cabdff1aSopenharmony_ci                    j = 0;
207cabdff1aSopenharmony_ci                    while (j < size_max_x && !IS_INTRA(j, -1))
208cabdff1aSopenharmony_ci                        j++;
209cabdff1aSopenharmony_ci                    EXTEND_LEFT_CIP(top, j, j + 1);
210cabdff1aSopenharmony_ci                    left[-1] = top[-1];
211cabdff1aSopenharmony_ci                }
212cabdff1aSopenharmony_ci            } else {
213cabdff1aSopenharmony_ci                j = 0;
214cabdff1aSopenharmony_ci                while (j < size_max_x && !IS_INTRA(j, -1))
215cabdff1aSopenharmony_ci                    j++;
216cabdff1aSopenharmony_ci                if (j > 0)
217cabdff1aSopenharmony_ci                    if (cand_up_left) {
218cabdff1aSopenharmony_ci                        EXTEND_LEFT_CIP(top, j, j + 1);
219cabdff1aSopenharmony_ci                    } else {
220cabdff1aSopenharmony_ci                        EXTEND_LEFT_CIP(top, j, j);
221cabdff1aSopenharmony_ci                        top[-1] = top[0];
222cabdff1aSopenharmony_ci                    }
223cabdff1aSopenharmony_ci                left[-1] = top[-1];
224cabdff1aSopenharmony_ci            }
225cabdff1aSopenharmony_ci            left[-1] = top[-1];
226cabdff1aSopenharmony_ci            if (cand_bottom_left || cand_left) {
227cabdff1aSopenharmony_ci                a = PIXEL_SPLAT_X4(left[-1]);
228cabdff1aSopenharmony_ci                EXTEND_DOWN_CIP(left, 0, size_max_y);
229cabdff1aSopenharmony_ci            }
230cabdff1aSopenharmony_ci            if (!cand_left)
231cabdff1aSopenharmony_ci                EXTEND(left, left[-1], size);
232cabdff1aSopenharmony_ci            if (!cand_bottom_left)
233cabdff1aSopenharmony_ci                EXTEND(left + size, left[size - 1], size);
234cabdff1aSopenharmony_ci            if (x0 != 0 && y0 != 0) {
235cabdff1aSopenharmony_ci                a = PIXEL_SPLAT_X4(left[size_max_y - 1]);
236cabdff1aSopenharmony_ci                EXTEND_UP_CIP(left, size_max_y - 1, size_max_y);
237cabdff1aSopenharmony_ci                if (!IS_INTRA(-1, - 1))
238cabdff1aSopenharmony_ci                    left[-1] = left[0];
239cabdff1aSopenharmony_ci            } else if (x0 == 0) {
240cabdff1aSopenharmony_ci                EXTEND(left, 0, size_max_y);
241cabdff1aSopenharmony_ci            } else {
242cabdff1aSopenharmony_ci                a = PIXEL_SPLAT_X4(left[size_max_y - 1]);
243cabdff1aSopenharmony_ci                EXTEND_UP_CIP(left, size_max_y - 1, size_max_y);
244cabdff1aSopenharmony_ci            }
245cabdff1aSopenharmony_ci            top[-1] = left[-1];
246cabdff1aSopenharmony_ci            if (y0 != 0) {
247cabdff1aSopenharmony_ci                a = PIXEL_SPLAT_X4(left[-1]);
248cabdff1aSopenharmony_ci                EXTEND_RIGHT_CIP(top, 0, size_max_x);
249cabdff1aSopenharmony_ci            }
250cabdff1aSopenharmony_ci        }
251cabdff1aSopenharmony_ci    }
252cabdff1aSopenharmony_ci    // Infer the unavailable samples
253cabdff1aSopenharmony_ci    if (!cand_bottom_left) {
254cabdff1aSopenharmony_ci        if (cand_left) {
255cabdff1aSopenharmony_ci            EXTEND(left + size, left[size - 1], size);
256cabdff1aSopenharmony_ci        } else if (cand_up_left) {
257cabdff1aSopenharmony_ci            EXTEND(left, left[-1], 2 * size);
258cabdff1aSopenharmony_ci            cand_left = 1;
259cabdff1aSopenharmony_ci        } else if (cand_up) {
260cabdff1aSopenharmony_ci            left[-1] = top[0];
261cabdff1aSopenharmony_ci            EXTEND(left, left[-1], 2 * size);
262cabdff1aSopenharmony_ci            cand_up_left = 1;
263cabdff1aSopenharmony_ci            cand_left    = 1;
264cabdff1aSopenharmony_ci        } else if (cand_up_right) {
265cabdff1aSopenharmony_ci            EXTEND(top, top[size], size);
266cabdff1aSopenharmony_ci            left[-1] = top[size];
267cabdff1aSopenharmony_ci            EXTEND(left, left[-1], 2 * size);
268cabdff1aSopenharmony_ci            cand_up      = 1;
269cabdff1aSopenharmony_ci            cand_up_left = 1;
270cabdff1aSopenharmony_ci            cand_left    = 1;
271cabdff1aSopenharmony_ci        } else { // No samples available
272cabdff1aSopenharmony_ci            left[-1] = (1 << (BIT_DEPTH - 1));
273cabdff1aSopenharmony_ci            EXTEND(top,  left[-1], 2 * size);
274cabdff1aSopenharmony_ci            EXTEND(left, left[-1], 2 * size);
275cabdff1aSopenharmony_ci        }
276cabdff1aSopenharmony_ci    }
277cabdff1aSopenharmony_ci
278cabdff1aSopenharmony_ci    if (!cand_left)
279cabdff1aSopenharmony_ci        EXTEND(left, left[size], size);
280cabdff1aSopenharmony_ci    if (!cand_up_left) {
281cabdff1aSopenharmony_ci        left[-1] = left[0];
282cabdff1aSopenharmony_ci    }
283cabdff1aSopenharmony_ci    if (!cand_up)
284cabdff1aSopenharmony_ci        EXTEND(top, left[-1], size);
285cabdff1aSopenharmony_ci    if (!cand_up_right)
286cabdff1aSopenharmony_ci        EXTEND(top + size, top[size - 1], size);
287cabdff1aSopenharmony_ci
288cabdff1aSopenharmony_ci    top[-1] = left[-1];
289cabdff1aSopenharmony_ci
290cabdff1aSopenharmony_ci    // Filtering process
291cabdff1aSopenharmony_ci    if (!s->ps.sps->intra_smoothing_disabled_flag && (c_idx == 0  || s->ps.sps->chroma_format_idc == 3)) {
292cabdff1aSopenharmony_ci        if (mode != INTRA_DC && size != 4){
293cabdff1aSopenharmony_ci            int intra_hor_ver_dist_thresh[] = { 7, 1, 0 };
294cabdff1aSopenharmony_ci            int min_dist_vert_hor = FFMIN(FFABS((int)(mode - 26U)),
295cabdff1aSopenharmony_ci                                          FFABS((int)(mode - 10U)));
296cabdff1aSopenharmony_ci            if (min_dist_vert_hor > intra_hor_ver_dist_thresh[log2_size - 3]) {
297cabdff1aSopenharmony_ci                int threshold = 1 << (BIT_DEPTH - 5);
298cabdff1aSopenharmony_ci                if (s->ps.sps->sps_strong_intra_smoothing_enable_flag && c_idx == 0 &&
299cabdff1aSopenharmony_ci                    log2_size == 5 &&
300cabdff1aSopenharmony_ci                    FFABS(top[-1]  + top[63]  - 2 * top[31])  < threshold &&
301cabdff1aSopenharmony_ci                    FFABS(left[-1] + left[63] - 2 * left[31]) < threshold) {
302cabdff1aSopenharmony_ci                    // We can't just overwrite values in top because it could be
303cabdff1aSopenharmony_ci                    // a pointer into src
304cabdff1aSopenharmony_ci                    filtered_top[-1] = top[-1];
305cabdff1aSopenharmony_ci                    filtered_top[63] = top[63];
306cabdff1aSopenharmony_ci                    for (i = 0; i < 63; i++)
307cabdff1aSopenharmony_ci                        filtered_top[i] = ((64 - (i + 1)) * top[-1] +
308cabdff1aSopenharmony_ci                                           (i + 1)  * top[63] + 32) >> 6;
309cabdff1aSopenharmony_ci                    for (i = 0; i < 63; i++)
310cabdff1aSopenharmony_ci                        left[i] = ((64 - (i + 1)) * left[-1] +
311cabdff1aSopenharmony_ci                                   (i + 1)  * left[63] + 32) >> 6;
312cabdff1aSopenharmony_ci                    top = filtered_top;
313cabdff1aSopenharmony_ci                } else {
314cabdff1aSopenharmony_ci                    filtered_left[2 * size - 1] = left[2 * size - 1];
315cabdff1aSopenharmony_ci                    filtered_top[2 * size - 1]  = top[2 * size - 1];
316cabdff1aSopenharmony_ci                    for (i = 2 * size - 2; i >= 0; i--)
317cabdff1aSopenharmony_ci                        filtered_left[i] = (left[i + 1] + 2 * left[i] +
318cabdff1aSopenharmony_ci                                            left[i - 1] + 2) >> 2;
319cabdff1aSopenharmony_ci                    filtered_top[-1]  =
320cabdff1aSopenharmony_ci                    filtered_left[-1] = (left[0] + 2 * left[-1] + top[0] + 2) >> 2;
321cabdff1aSopenharmony_ci                    for (i = 2 * size - 2; i >= 0; i--)
322cabdff1aSopenharmony_ci                        filtered_top[i] = (top[i + 1] + 2 * top[i] +
323cabdff1aSopenharmony_ci                                           top[i - 1] + 2) >> 2;
324cabdff1aSopenharmony_ci                    left = filtered_left;
325cabdff1aSopenharmony_ci                    top  = filtered_top;
326cabdff1aSopenharmony_ci                }
327cabdff1aSopenharmony_ci            }
328cabdff1aSopenharmony_ci        }
329cabdff1aSopenharmony_ci    }
330cabdff1aSopenharmony_ci
331cabdff1aSopenharmony_ci    switch (mode) {
332cabdff1aSopenharmony_ci    case INTRA_PLANAR:
333cabdff1aSopenharmony_ci        s->hpc.pred_planar[log2_size - 2]((uint8_t *)src, (uint8_t *)top,
334cabdff1aSopenharmony_ci                                          (uint8_t *)left, stride);
335cabdff1aSopenharmony_ci        break;
336cabdff1aSopenharmony_ci    case INTRA_DC:
337cabdff1aSopenharmony_ci        s->hpc.pred_dc((uint8_t *)src, (uint8_t *)top,
338cabdff1aSopenharmony_ci                       (uint8_t *)left, stride, log2_size, c_idx);
339cabdff1aSopenharmony_ci        break;
340cabdff1aSopenharmony_ci    default:
341cabdff1aSopenharmony_ci        s->hpc.pred_angular[log2_size - 2]((uint8_t *)src, (uint8_t *)top,
342cabdff1aSopenharmony_ci                                           (uint8_t *)left, stride, c_idx,
343cabdff1aSopenharmony_ci                                           mode);
344cabdff1aSopenharmony_ci        break;
345cabdff1aSopenharmony_ci    }
346cabdff1aSopenharmony_ci}
347cabdff1aSopenharmony_ci
348cabdff1aSopenharmony_ci#define INTRA_PRED(size)                                                            \
349cabdff1aSopenharmony_cistatic void FUNC(intra_pred_ ## size)(HEVCContext *s, int x0, int y0, int c_idx)    \
350cabdff1aSopenharmony_ci{                                                                                   \
351cabdff1aSopenharmony_ci    FUNC(intra_pred)(s, x0, y0, size, c_idx);                                       \
352cabdff1aSopenharmony_ci}
353cabdff1aSopenharmony_ci
354cabdff1aSopenharmony_ciINTRA_PRED(2)
355cabdff1aSopenharmony_ciINTRA_PRED(3)
356cabdff1aSopenharmony_ciINTRA_PRED(4)
357cabdff1aSopenharmony_ciINTRA_PRED(5)
358cabdff1aSopenharmony_ci
359cabdff1aSopenharmony_ci#undef INTRA_PRED
360cabdff1aSopenharmony_ci
361cabdff1aSopenharmony_cistatic av_always_inline void FUNC(pred_planar)(uint8_t *_src, const uint8_t *_top,
362cabdff1aSopenharmony_ci                                  const uint8_t *_left, ptrdiff_t stride,
363cabdff1aSopenharmony_ci                                  int trafo_size)
364cabdff1aSopenharmony_ci{
365cabdff1aSopenharmony_ci    int x, y;
366cabdff1aSopenharmony_ci    pixel *src        = (pixel *)_src;
367cabdff1aSopenharmony_ci    const pixel *top  = (const pixel *)_top;
368cabdff1aSopenharmony_ci    const pixel *left = (const pixel *)_left;
369cabdff1aSopenharmony_ci    int size = 1 << trafo_size;
370cabdff1aSopenharmony_ci    for (y = 0; y < size; y++)
371cabdff1aSopenharmony_ci        for (x = 0; x < size; x++)
372cabdff1aSopenharmony_ci            POS(x, y) = ((size - 1 - x) * left[y] + (x + 1) * top[size]  +
373cabdff1aSopenharmony_ci                         (size - 1 - y) * top[x]  + (y + 1) * left[size] + size) >> (trafo_size + 1);
374cabdff1aSopenharmony_ci}
375cabdff1aSopenharmony_ci
376cabdff1aSopenharmony_ci#define PRED_PLANAR(size)\
377cabdff1aSopenharmony_cistatic void FUNC(pred_planar_ ## size)(uint8_t *src, const uint8_t *top,        \
378cabdff1aSopenharmony_ci                                       const uint8_t *left, ptrdiff_t stride)   \
379cabdff1aSopenharmony_ci{                                                                               \
380cabdff1aSopenharmony_ci    FUNC(pred_planar)(src, top, left, stride, size + 2);                        \
381cabdff1aSopenharmony_ci}
382cabdff1aSopenharmony_ci
383cabdff1aSopenharmony_ciPRED_PLANAR(0)
384cabdff1aSopenharmony_ciPRED_PLANAR(1)
385cabdff1aSopenharmony_ciPRED_PLANAR(2)
386cabdff1aSopenharmony_ciPRED_PLANAR(3)
387cabdff1aSopenharmony_ci
388cabdff1aSopenharmony_ci#undef PRED_PLANAR
389cabdff1aSopenharmony_ci
390cabdff1aSopenharmony_cistatic void FUNC(pred_dc)(uint8_t *_src, const uint8_t *_top,
391cabdff1aSopenharmony_ci                          const uint8_t *_left,
392cabdff1aSopenharmony_ci                          ptrdiff_t stride, int log2_size, int c_idx)
393cabdff1aSopenharmony_ci{
394cabdff1aSopenharmony_ci    int i, j, x, y;
395cabdff1aSopenharmony_ci    int size          = (1 << log2_size);
396cabdff1aSopenharmony_ci    pixel *src        = (pixel *)_src;
397cabdff1aSopenharmony_ci    const pixel *top  = (const pixel *)_top;
398cabdff1aSopenharmony_ci    const pixel *left = (const pixel *)_left;
399cabdff1aSopenharmony_ci    int dc            = size;
400cabdff1aSopenharmony_ci    pixel4 a;
401cabdff1aSopenharmony_ci    for (i = 0; i < size; i++)
402cabdff1aSopenharmony_ci        dc += left[i] + top[i];
403cabdff1aSopenharmony_ci
404cabdff1aSopenharmony_ci    dc >>= log2_size + 1;
405cabdff1aSopenharmony_ci
406cabdff1aSopenharmony_ci    a = PIXEL_SPLAT_X4(dc);
407cabdff1aSopenharmony_ci
408cabdff1aSopenharmony_ci    for (i = 0; i < size; i++)
409cabdff1aSopenharmony_ci        for (j = 0; j < size; j+=4)
410cabdff1aSopenharmony_ci            AV_WN4P(&POS(j, i), a);
411cabdff1aSopenharmony_ci
412cabdff1aSopenharmony_ci    if (c_idx == 0 && size < 32) {
413cabdff1aSopenharmony_ci        POS(0, 0) = (left[0] + 2 * dc + top[0] + 2) >> 2;
414cabdff1aSopenharmony_ci        for (x = 1; x < size; x++)
415cabdff1aSopenharmony_ci            POS(x, 0) = (top[x] + 3 * dc + 2) >> 2;
416cabdff1aSopenharmony_ci        for (y = 1; y < size; y++)
417cabdff1aSopenharmony_ci            POS(0, y) = (left[y] + 3 * dc + 2) >> 2;
418cabdff1aSopenharmony_ci    }
419cabdff1aSopenharmony_ci}
420cabdff1aSopenharmony_ci
421cabdff1aSopenharmony_cistatic av_always_inline void FUNC(pred_angular)(uint8_t *_src,
422cabdff1aSopenharmony_ci                                                const uint8_t *_top,
423cabdff1aSopenharmony_ci                                                const uint8_t *_left,
424cabdff1aSopenharmony_ci                                                ptrdiff_t stride, int c_idx,
425cabdff1aSopenharmony_ci                                                int mode, int size)
426cabdff1aSopenharmony_ci{
427cabdff1aSopenharmony_ci    int x, y;
428cabdff1aSopenharmony_ci    pixel *src        = (pixel *)_src;
429cabdff1aSopenharmony_ci    const pixel *top  = (const pixel *)_top;
430cabdff1aSopenharmony_ci    const pixel *left = (const pixel *)_left;
431cabdff1aSopenharmony_ci
432cabdff1aSopenharmony_ci    static const int intra_pred_angle[] = {
433cabdff1aSopenharmony_ci         32,  26,  21,  17, 13,  9,  5, 2, 0, -2, -5, -9, -13, -17, -21, -26, -32,
434cabdff1aSopenharmony_ci        -26, -21, -17, -13, -9, -5, -2, 0, 2,  5,  9, 13,  17,  21,  26,  32
435cabdff1aSopenharmony_ci    };
436cabdff1aSopenharmony_ci    static const int inv_angle[] = {
437cabdff1aSopenharmony_ci        -4096, -1638, -910, -630, -482, -390, -315, -256, -315, -390, -482,
438cabdff1aSopenharmony_ci        -630, -910, -1638, -4096
439cabdff1aSopenharmony_ci    };
440cabdff1aSopenharmony_ci
441cabdff1aSopenharmony_ci    int angle = intra_pred_angle[mode - 2];
442cabdff1aSopenharmony_ci    pixel ref_array[3 * MAX_TB_SIZE + 4];
443cabdff1aSopenharmony_ci    pixel *ref_tmp = ref_array + size;
444cabdff1aSopenharmony_ci    const pixel *ref;
445cabdff1aSopenharmony_ci    int last = (size * angle) >> 5;
446cabdff1aSopenharmony_ci
447cabdff1aSopenharmony_ci    if (mode >= 18) {
448cabdff1aSopenharmony_ci        ref = top - 1;
449cabdff1aSopenharmony_ci        if (angle < 0 && last < -1) {
450cabdff1aSopenharmony_ci            for (x = 0; x <= size; x += 4)
451cabdff1aSopenharmony_ci                AV_WN4P(&ref_tmp[x], AV_RN4P(&top[x - 1]));
452cabdff1aSopenharmony_ci            for (x = last; x <= -1; x++)
453cabdff1aSopenharmony_ci                ref_tmp[x] = left[-1 + ((x * inv_angle[mode - 11] + 128) >> 8)];
454cabdff1aSopenharmony_ci            ref = ref_tmp;
455cabdff1aSopenharmony_ci        }
456cabdff1aSopenharmony_ci
457cabdff1aSopenharmony_ci        for (y = 0; y < size; y++) {
458cabdff1aSopenharmony_ci            int idx  = ((y + 1) * angle) >> 5;
459cabdff1aSopenharmony_ci            int fact = ((y + 1) * angle) & 31;
460cabdff1aSopenharmony_ci            if (fact) {
461cabdff1aSopenharmony_ci                for (x = 0; x < size; x += 4) {
462cabdff1aSopenharmony_ci                    POS(x    , y) = ((32 - fact) * ref[x + idx + 1] +
463cabdff1aSopenharmony_ci                                           fact  * ref[x + idx + 2] + 16) >> 5;
464cabdff1aSopenharmony_ci                    POS(x + 1, y) = ((32 - fact) * ref[x + 1 + idx + 1] +
465cabdff1aSopenharmony_ci                                           fact  * ref[x + 1 + idx + 2] + 16) >> 5;
466cabdff1aSopenharmony_ci                    POS(x + 2, y) = ((32 - fact) * ref[x + 2 + idx + 1] +
467cabdff1aSopenharmony_ci                                           fact  * ref[x + 2 + idx + 2] + 16) >> 5;
468cabdff1aSopenharmony_ci                    POS(x + 3, y) = ((32 - fact) * ref[x + 3 + idx + 1] +
469cabdff1aSopenharmony_ci                                           fact  * ref[x + 3 + idx + 2] + 16) >> 5;
470cabdff1aSopenharmony_ci                }
471cabdff1aSopenharmony_ci            } else {
472cabdff1aSopenharmony_ci                for (x = 0; x < size; x += 4)
473cabdff1aSopenharmony_ci                    AV_WN4P(&POS(x, y), AV_RN4P(&ref[x + idx + 1]));
474cabdff1aSopenharmony_ci            }
475cabdff1aSopenharmony_ci        }
476cabdff1aSopenharmony_ci        if (mode == 26 && c_idx == 0 && size < 32) {
477cabdff1aSopenharmony_ci            for (y = 0; y < size; y++)
478cabdff1aSopenharmony_ci                POS(0, y) = av_clip_pixel(top[0] + ((left[y] - left[-1]) >> 1));
479cabdff1aSopenharmony_ci        }
480cabdff1aSopenharmony_ci    } else {
481cabdff1aSopenharmony_ci        ref = left - 1;
482cabdff1aSopenharmony_ci        if (angle < 0 && last < -1) {
483cabdff1aSopenharmony_ci            for (x = 0; x <= size; x += 4)
484cabdff1aSopenharmony_ci                AV_WN4P(&ref_tmp[x], AV_RN4P(&left[x - 1]));
485cabdff1aSopenharmony_ci            for (x = last; x <= -1; x++)
486cabdff1aSopenharmony_ci                ref_tmp[x] = top[-1 + ((x * inv_angle[mode - 11] + 128) >> 8)];
487cabdff1aSopenharmony_ci            ref = ref_tmp;
488cabdff1aSopenharmony_ci        }
489cabdff1aSopenharmony_ci
490cabdff1aSopenharmony_ci        for (x = 0; x < size; x++) {
491cabdff1aSopenharmony_ci            int idx  = ((x + 1) * angle) >> 5;
492cabdff1aSopenharmony_ci            int fact = ((x + 1) * angle) & 31;
493cabdff1aSopenharmony_ci            if (fact) {
494cabdff1aSopenharmony_ci                for (y = 0; y < size; y++) {
495cabdff1aSopenharmony_ci                    POS(x, y) = ((32 - fact) * ref[y + idx + 1] +
496cabdff1aSopenharmony_ci                                       fact  * ref[y + idx + 2] + 16) >> 5;
497cabdff1aSopenharmony_ci                }
498cabdff1aSopenharmony_ci            } else {
499cabdff1aSopenharmony_ci                for (y = 0; y < size; y++)
500cabdff1aSopenharmony_ci                    POS(x, y) = ref[y + idx + 1];
501cabdff1aSopenharmony_ci            }
502cabdff1aSopenharmony_ci        }
503cabdff1aSopenharmony_ci        if (mode == 10 && c_idx == 0 && size < 32) {
504cabdff1aSopenharmony_ci            for (x = 0; x < size; x += 4) {
505cabdff1aSopenharmony_ci                POS(x,     0) = av_clip_pixel(left[0] + ((top[x    ] - top[-1]) >> 1));
506cabdff1aSopenharmony_ci                POS(x + 1, 0) = av_clip_pixel(left[0] + ((top[x + 1] - top[-1]) >> 1));
507cabdff1aSopenharmony_ci                POS(x + 2, 0) = av_clip_pixel(left[0] + ((top[x + 2] - top[-1]) >> 1));
508cabdff1aSopenharmony_ci                POS(x + 3, 0) = av_clip_pixel(left[0] + ((top[x + 3] - top[-1]) >> 1));
509cabdff1aSopenharmony_ci            }
510cabdff1aSopenharmony_ci        }
511cabdff1aSopenharmony_ci    }
512cabdff1aSopenharmony_ci}
513cabdff1aSopenharmony_ci
514cabdff1aSopenharmony_cistatic void FUNC(pred_angular_0)(uint8_t *src, const uint8_t *top,
515cabdff1aSopenharmony_ci                                 const uint8_t *left,
516cabdff1aSopenharmony_ci                                 ptrdiff_t stride, int c_idx, int mode)
517cabdff1aSopenharmony_ci{
518cabdff1aSopenharmony_ci    FUNC(pred_angular)(src, top, left, stride, c_idx, mode, 1 << 2);
519cabdff1aSopenharmony_ci}
520cabdff1aSopenharmony_ci
521cabdff1aSopenharmony_cistatic void FUNC(pred_angular_1)(uint8_t *src, const uint8_t *top,
522cabdff1aSopenharmony_ci                                 const uint8_t *left,
523cabdff1aSopenharmony_ci                                 ptrdiff_t stride, int c_idx, int mode)
524cabdff1aSopenharmony_ci{
525cabdff1aSopenharmony_ci    FUNC(pred_angular)(src, top, left, stride, c_idx, mode, 1 << 3);
526cabdff1aSopenharmony_ci}
527cabdff1aSopenharmony_ci
528cabdff1aSopenharmony_cistatic void FUNC(pred_angular_2)(uint8_t *src, const uint8_t *top,
529cabdff1aSopenharmony_ci                                 const uint8_t *left,
530cabdff1aSopenharmony_ci                                 ptrdiff_t stride, int c_idx, int mode)
531cabdff1aSopenharmony_ci{
532cabdff1aSopenharmony_ci    FUNC(pred_angular)(src, top, left, stride, c_idx, mode, 1 << 4);
533cabdff1aSopenharmony_ci}
534cabdff1aSopenharmony_ci
535cabdff1aSopenharmony_cistatic void FUNC(pred_angular_3)(uint8_t *src, const uint8_t *top,
536cabdff1aSopenharmony_ci                                 const uint8_t *left,
537cabdff1aSopenharmony_ci                                 ptrdiff_t stride, int c_idx, int mode)
538cabdff1aSopenharmony_ci{
539cabdff1aSopenharmony_ci    FUNC(pred_angular)(src, top, left, stride, c_idx, mode, 1 << 5);
540cabdff1aSopenharmony_ci}
541cabdff1aSopenharmony_ci
542cabdff1aSopenharmony_ci#undef EXTEND_LEFT_CIP
543cabdff1aSopenharmony_ci#undef EXTEND_RIGHT_CIP
544cabdff1aSopenharmony_ci#undef EXTEND_UP_CIP
545cabdff1aSopenharmony_ci#undef EXTEND_DOWN_CIP
546cabdff1aSopenharmony_ci#undef IS_INTRA
547cabdff1aSopenharmony_ci#undef MVF_PU
548cabdff1aSopenharmony_ci#undef MVF
549cabdff1aSopenharmony_ci#undef PU
550cabdff1aSopenharmony_ci#undef EXTEND
551cabdff1aSopenharmony_ci#undef MIN_TB_ADDR_ZS
552cabdff1aSopenharmony_ci#undef POS
553