1 /******************************************************************************
2 *
3 * Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18 /**
19 *******************************************************************************
20 * @file
21 * ihevcd_intra_pred_mode_prediction.c.c
22 *
23 * @brief
24 * Contains functions for intra pred mode prediction
25 *
26 * @author
27 * Ittiam
28 *
29 * @par List of Functions:
30 * - ihevcd_intra_pred_mode_prediction()
31 *
32 * @remarks
33 * None
34 *
35 *******************************************************************************
36 */
37 /*****************************************************************************/
38 /* File Includes */
39 /*****************************************************************************/
40 #include <stdio.h>
41 #include <stddef.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 #include "ihevc_typedefs.h"
46 #include "iv.h"
47 #include "ivd.h"
48 #include "ihevcd_cxa.h"
49
50 #include "ihevc_defs.h"
51 #include "ihevc_debug.h"
52 #include "ihevc_structs.h"
53 #include "ihevc_macros.h"
54 #include "ihevc_mem_fns.h"
55 #include "ihevc_platform_macros.h"
56
57 #include "ihevcd_defs.h"
58 #include "ihevc_cabac_tables.h"
59 #include "ihevcd_function_selector.h"
60 #include "ihevcd_structs.h"
61 #include "ihevcd_error.h"
62
63 #include "ihevcd_bitstream.h"
64
65
66 /*****************************************************************************/
67 /* Function Prototypes */
68 /*****************************************************************************/
69
70 /*****************************************************************************/
71 /* Availability check is not done inside the function */
72 /* Whenever the top and left are not available, it is assumed that Intra DC */
73 /* mode will initialized in place of non available */
74 /* neighbors */
75 /*****************************************************************************/
76
77 /**
78 *******************************************************************************
79 *
80 * @brief Computes intra prediction mode for a CU
81 *
82 * @par Description
83 * Computes intra prediction mode for a CU
84 *
85 * @param[in,out] ps_cu
86 * Codic unit context
87 *
88 * @param[in] ps_parse
89 * parse context
90 *
91 * @param[in] ps_codec
92 * codec context
93 *
94 * @param[in] log2_cb_size
95 * log of cb size base 2
96 *
97 * @returns none
98 *
99 * @remarks
100 * Availability check is moved to CTB level. If the neighbors are
101 * not available or if the pred mode of neighbor is not MODE_INTRA,
102 * INTRA_DC mode will be updated in top and left buffers.
103 *******************************************************************************
104 */
ihevcd_intra_pred_mode_prediction(codec_t * ps_codec,WORD32 log2_cb_size,WORD32 x0,WORD32 y0)105 void ihevcd_intra_pred_mode_prediction(codec_t *ps_codec,
106 WORD32 log2_cb_size,
107 WORD32 x0,
108 WORD32 y0)
109 {
110 WORD32 i, j, num_pred_blocks;
111 WORD32 available_l, available_t;
112 WORD32 cand_intra_pred_mode_l, cand_intra_pred_mode_t;
113 WORD32 cand_mode_list[3];
114 WORD32 cb_size, block_offset_in_min_pu;
115 UWORD8 *pu1_luma_intra_pred_mode_top;
116 UWORD8 *pu1_luma_intra_pred_mode_left;
117
118 parse_ctxt_t *ps_parse = &ps_codec->s_parse;
119 parse_cu_t *ps_cu = &ps_codec->s_parse.s_cu;
120 sps_t *ps_sps = ps_parse->ps_sps;
121
122
123 available_t = 1;
124 available_l = 1;
125 /* i4_pos_x and i4_pos_y are in minCu units (8x8), convert them to 4x4 units by multiplying by 2 */
126 pu1_luma_intra_pred_mode_top = ps_parse->pu1_luma_intra_pred_mode_top
127 + (ps_cu->i4_pos_x * 2);
128
129 pu1_luma_intra_pred_mode_left = ps_parse->pu1_luma_intra_pred_mode_left
130 + (ps_cu->i4_pos_y * 2);
131
132 /*
133 if(0 == ps_cu->i4_pos_y)
134 {
135 memset(pu1_luma_intra_pred_mode_top, INTRA_DC, 16);
136 }
137
138 if(0 == ps_cu->i4_pos_x)
139 {
140 memset(pu1_luma_intra_pred_mode_left, INTRA_DC, 16);
141 }
142 */
143 if(ps_cu->i4_pos_y)
144 {
145 UWORD8 *pu1_pic_intra_flag = ps_codec->s_parse.pu1_pic_intra_flag;
146 WORD32 top_intra_flag;
147
148 WORD32 numbytes_row = (ps_sps->i2_pic_width_in_luma_samples + 63) / 64;
149 pu1_pic_intra_flag += ((y0 - 8) / 8) * numbytes_row;
150 pu1_pic_intra_flag += (x0 / 64);
151 top_intra_flag = *pu1_pic_intra_flag;
152 top_intra_flag &= (1 << ((x0 / 8) % 8));
153
154 if(0 == top_intra_flag)
155 {
156 available_t = 0;
157 }
158 }
159 else
160 available_t = 0;
161
162
163 if((0 == ps_cu->i4_pos_x) && (((0 == ps_codec->s_parse.i4_ctb_slice_x) && (0 == ps_codec->s_parse.i4_ctb_slice_y)) ||
164 (0 == ps_codec->s_parse.i4_ctb_tile_x)))
165 {
166 available_l = 0;
167 }
168
169 if(available_l)
170 {
171 UWORD8 *pu1_pic_intra_flag = ps_codec->s_parse.pu1_pic_intra_flag;
172 WORD32 left_intra_flag;
173 WORD32 numbytes_row = (ps_sps->i2_pic_width_in_luma_samples + 63) / 64;
174 pu1_pic_intra_flag += (y0 / 8) * numbytes_row;
175 pu1_pic_intra_flag += ((x0 - 8) / 64);
176 left_intra_flag = *pu1_pic_intra_flag;
177 left_intra_flag &= (1 << (((x0 - 8) / 8) % 8));
178
179 if(0 == left_intra_flag)
180 {
181 available_l = 0;
182 }
183 }
184
185 cb_size = (1 << log2_cb_size);
186
187 block_offset_in_min_pu = (cb_size / 2) / MIN_PU_SIZE;
188
189 num_pred_blocks = (ps_cu->i4_part_mode == PART_NxN) ? 2 : 1;
190
191 for(i = 0; i < num_pred_blocks; i++)
192 {
193 WORD32 available_l_tmp;
194 available_l_tmp = available_l;
195 for(j = 0; j < num_pred_blocks; j++)
196 {
197 /* Computing Candidate intra pred mode left */
198 {
199 WORD32 block_offset;
200
201 block_offset = i * block_offset_in_min_pu;
202 cand_intra_pred_mode_l = INTRA_DC;
203 if(available_l_tmp)
204 {
205 cand_intra_pred_mode_l =
206 pu1_luma_intra_pred_mode_left[block_offset];
207 }
208
209 }
210
211 {
212 WORD32 block_offset;
213 block_offset = j * block_offset_in_min_pu;
214 cand_intra_pred_mode_t = INTRA_DC;
215 if(available_t)
216 {
217 cand_intra_pred_mode_t =
218 pu1_luma_intra_pred_mode_top[block_offset];
219 }
220 }
221
222 /* Computing Candidate mode list */
223 if(cand_intra_pred_mode_l == cand_intra_pred_mode_t)
224 {
225 if(cand_intra_pred_mode_l < 2)
226 {
227 cand_mode_list[0] = INTRA_PLANAR;
228 cand_mode_list[1] = INTRA_DC;
229 cand_mode_list[2] = INTRA_ANGULAR(26); /* angular 26 = Vertical */
230 }
231 else
232 {
233 cand_mode_list[0] = cand_intra_pred_mode_l;
234 cand_mode_list[1] = 2
235 + ((cand_intra_pred_mode_l + 29) % 32);
236 cand_mode_list[2] = 2
237 + ((cand_intra_pred_mode_l - 2 + 1) % 32);
238 }
239 }
240 else
241 {
242 cand_mode_list[0] = cand_intra_pred_mode_l;
243 cand_mode_list[1] = cand_intra_pred_mode_t;
244
245 if((cand_intra_pred_mode_l != INTRA_PLANAR)
246 && (cand_intra_pred_mode_t != INTRA_PLANAR))
247 {
248 cand_mode_list[2] = INTRA_PLANAR;
249 }
250 else if((cand_intra_pred_mode_l != INTRA_DC)
251 && (cand_intra_pred_mode_t != INTRA_DC))
252 {
253 cand_mode_list[2] = INTRA_DC;
254 }
255 else
256 {
257 cand_mode_list[2] = INTRA_ANGULAR(26);
258 }
259 }
260
261 /* Computing Intra pred mode */
262 if(ps_cu->ai4_prev_intra_luma_pred_flag[2 * i + j] == 1)
263 {
264 ps_cu->ai4_intra_luma_pred_mode[2 * i + j] =
265 cand_mode_list[ps_cu->ai4_mpm_idx[2 * i + j]];
266 }
267 else
268 {
269 WORD32 intra_pred_mode;
270 /* Arranging cand_mode_list in increasing order */
271 if(cand_mode_list[0] > cand_mode_list[1])
272 {
273 SWAP(cand_mode_list[0], cand_mode_list[1]);
274 }
275 if(cand_mode_list[0] > cand_mode_list[2])
276 {
277 SWAP(cand_mode_list[0], cand_mode_list[2]);
278 }
279 if(cand_mode_list[1] > cand_mode_list[2])
280 {
281 SWAP(cand_mode_list[1], cand_mode_list[2]);
282 }
283
284 intra_pred_mode = ps_cu->ai4_rem_intra_luma_pred_mode[2 * i + j];
285
286 if(intra_pred_mode >= cand_mode_list[0])
287 intra_pred_mode++;
288
289 if(intra_pred_mode >= cand_mode_list[1])
290 intra_pred_mode++;
291
292 if(intra_pred_mode >= cand_mode_list[2])
293 intra_pred_mode++;
294
295 ps_cu->ai4_intra_luma_pred_mode[2 * i + j] = intra_pred_mode;
296 }
297 /* Update Top and Left intra pred mode */
298 {
299 WORD32 intra_pred_mode;
300
301 intra_pred_mode = ps_cu->ai4_intra_luma_pred_mode[2 * i + j];
302
303 ps_codec->s_func_selector.ihevc_memset_fptr(pu1_luma_intra_pred_mode_left + i * block_offset_in_min_pu, intra_pred_mode, (cb_size / num_pred_blocks) / MIN_PU_SIZE);
304 ps_codec->s_func_selector.ihevc_memset_fptr(pu1_luma_intra_pred_mode_top + j * block_offset_in_min_pu, intra_pred_mode, (cb_size / num_pred_blocks) / MIN_PU_SIZE);
305
306 }
307 /* If partition is PART_NxN, then left is available for second column always */
308 available_l_tmp = 1;
309
310 }
311 /* If partition is PART_NxN, then top is available for bottom row always */
312 available_t = 1;
313 }
314
315 /* In case it is PART_2Nx2N partition, replicate intra pred mode in other three entries */
316 if(ps_cu->i4_part_mode == PART_2Nx2N)
317 {
318 ps_cu->ai4_intra_luma_pred_mode[1] = ps_cu->ai4_intra_luma_pred_mode[0];
319 ps_cu->ai4_intra_luma_pred_mode[2] = ps_cu->ai4_intra_luma_pred_mode[0];
320 ps_cu->ai4_intra_luma_pred_mode[3] = ps_cu->ai4_intra_luma_pred_mode[0];
321 }
322 }
323
324