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