1 /****************************************************************************** 2 * 3 * Copyright (C) 2015 The Android Open Source Project 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 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore 19 */ 20 /** 21 ******************************************************************************* 22 * @file 23 * ih264_chroma_intra_pred_filters.c 24 * 25 * @brief 26 * Contains function definitions for chroma intra prediction filters 27 * 28 * @author 29 * Ittiam 30 * 31 * @par List of Functions: 32 * -ih264_intra_pred_chroma_8x8_mode_dc 33 * -ih264_intra_pred_chroma_8x8_mode_horz 34 * -ih264_intra_pred_chroma_8x8_mode_vert 35 * -ih264_intra_pred_chroma_8x8_mode_plane 36 * 37 * @remarks 38 * None 39 * 40 ******************************************************************************* 41 */ 42 43 /*****************************************************************************/ 44 /* File Includes */ 45 /*****************************************************************************/ 46 47 /* System include files */ 48 #include <stdio.h> 49 #include <stddef.h> 50 #include <string.h> 51 52 /* User include files */ 53 #include "ih264_defs.h" 54 #include "ih264_typedefs.h" 55 #include "ih264_macros.h" 56 #include "ih264_platform_macros.h" 57 #include "ih264_intra_pred_filters.h" 58 59 /* Global variables used only in assembly files*/ 60 const WORD8 ih264_gai1_intrapred_chroma_plane_coeffs1[] = 61 { 0x01,0x00,0x01,0x00, 62 0x02,0x00,0x02,0x00, 63 0x03,0x00,0x03,0x00, 64 0x04,0x00,0x04,0x00 65 }; 66 const WORD8 ih264_gai1_intrapred_chroma_plane_coeffs2[] = 67 { 0xfd,0xff,0xfe,0xff, 68 0xff,0xff,0x00,0x00, 69 0x01,0x00,0x02,0x00, 70 0x03,0x00,0x04,0x00, 71 }; 72 73 /*****************************************************************************/ 74 /* Chroma Intra prediction 8x8 filters */ 75 /*****************************************************************************/ 76 77 /** 78 ******************************************************************************* 79 * 80 * ih264_intra_pred_chroma_8x8_mode_dc 81 * 82 * @brief 83 * Perform Intra prediction for chroma_8x8 mode:DC 84 * 85 * @par Description: 86 * Perform Intra prediction for chroma_8x8 mode:DC ,described in sec 8.3.4.1 87 * 88 * @param[in] pu1_src 89 * UWORD8 pointer to the source containing alternate U and V samples 90 * 91 * @param[out] pu1_dst 92 * UWORD8 pointer to the destination with alternate U and V samples 93 * 94 * @param[in] src_strd 95 * integer source stride 96 * 97 * @param[in] dst_strd 98 * integer destination stride 99 * 100 ** @param[in] ngbr_avail 101 * availability of neighbouring pixels 102 * 103 * @returns 104 * 105 * @remarks 106 * None 107 * 108 ****************************************************************************** 109 */ 110 void ih264_intra_pred_chroma_8x8_mode_dc(UWORD8 *pu1_src, 111 UWORD8 *pu1_dst, 112 WORD32 src_strd, 113 WORD32 dst_strd, 114 WORD32 ngbr_avail) 115 { 116 WORD32 left_avail, left_avail1, left_avail2; /* availability of left predictors (only for DC) */ 117 WORD32 top_avail; /* availability of top predictors (only for DC) */ 118 UWORD8 *pu1_left = NULL; /* Pointer to start of left predictors */ 119 UWORD8 *pu1_top = NULL; /* Pointer to start of top predictors */ 120 121 /* temporary variables to store accumulated first left half,second left half, 122 * first top half,second top half of U and V values*/ 123 WORD32 val_u_l1 = 0, val_u_l2 = 0, val_u_t1 = 0, val_u_t2 = 0; 124 WORD32 val_v_l1 = 0, val_v_l2 = 0, val_v_t1 = 0, val_v_t2 = 0; 125 126 WORD32 val_u1 = 0, val_u2 = 0, val_v1 = 0, val_v2 = 0; 127 128 WORD32 col, row; /*loop variables*/ 129 UNUSED(src_strd); 130 131 left_avail = ngbr_avail & 0x11; 132 left_avail1 = ngbr_avail & 1; 133 left_avail2 = (ngbr_avail >> 4) & 1; 134 top_avail = (ngbr_avail >> 2) & 1; 135 136 pu1_top = pu1_src + 2 * BLK8x8SIZE + 2; 137 pu1_left = pu1_src + 2 * BLK8x8SIZE - 2; 138 139 if(left_avail1) 140 { /* First 4x4 block*/ 141 val_u_l1 += *pu1_left; 142 val_v_l1 += *(pu1_left + 1); 143 pu1_left -= 2; 144 val_u_l1 += *pu1_left; 145 val_v_l1 += *(pu1_left + 1); 146 pu1_left -= 2; 147 val_u_l1 += *pu1_left; 148 val_v_l1 += *(pu1_left + 1); 149 pu1_left -= 2; 150 val_u_l1 += *pu1_left + 2; 151 val_v_l1 += *(pu1_left + 1) + 2; 152 pu1_left -= 2; 153 } 154 else 155 pu1_left -= 2 * 4; 156 157 if(left_avail2) 158 { 159 /* Second 4x4 block*/ 160 val_u_l2 += *pu1_left; 161 val_v_l2 += *(pu1_left + 1); 162 pu1_left -= 2; 163 val_u_l2 += *pu1_left; 164 val_v_l2 += *(pu1_left + 1); 165 pu1_left -= 2; 166 val_u_l2 += *pu1_left; 167 val_v_l2 += *(pu1_left + 1); 168 pu1_left -= 2; 169 val_u_l2 += *pu1_left + 2; 170 val_v_l2 += *(pu1_left + 1) + 2; 171 pu1_left -= 2; 172 } 173 else 174 pu1_left -= 2 * 4; 175 176 if(top_avail) 177 { 178 val_u_t1 += *pu1_top + *(pu1_top + 2) + *(pu1_top + 4) 179 + *(pu1_top + 6) + 2; 180 val_u_t2 += *(pu1_top + 8) + *(pu1_top + 10) + *(pu1_top + 12) 181 + *(pu1_top + 14) + 2; 182 val_v_t1 += *(pu1_top + 1) + *(pu1_top + 3) + *(pu1_top + 5) 183 + *(pu1_top + 7) + 2; 184 val_v_t2 += *(pu1_top + 9) + *(pu1_top + 11) + *(pu1_top + 13) 185 + *(pu1_top + 15) + 2; 186 } 187 188 if(left_avail + top_avail) 189 { 190 val_u1 = (left_avail1 + top_avail) ? 191 ((val_u_l1 + val_u_t1) 192 >> (1 + left_avail1 + top_avail)) :128; 193 val_v1 = (left_avail1 + top_avail) ? 194 ((val_v_l1 + val_v_t1) 195 >> (1 + left_avail1 + top_avail)) :128; 196 if(top_avail) 197 { 198 val_u2 = val_u_t2 >> 2; 199 val_v2 = val_v_t2 >> 2; 200 } 201 else if(left_avail1) 202 { 203 val_u2 = val_u_l1 >> 2; 204 val_v2 = val_v_l1 >> 2; 205 } 206 else 207 { 208 val_u2 = val_v2 = 128; 209 } 210 211 for(row = 0; row < 4; row++) 212 { 213 /*top left 4x4 block*/ 214 for(col = 0; col < 8; col += 2) 215 { 216 *(pu1_dst + row * dst_strd + col) = val_u1; 217 *(pu1_dst + row * dst_strd + col + 1) = val_v1; 218 } 219 /*top right 4x4 block*/ 220 for(col = 8; col < 16; col += 2) 221 { 222 *(pu1_dst + row * dst_strd + col) = val_u2; 223 *(pu1_dst + row * dst_strd + col + 1) = val_v2; 224 } 225 } 226 227 if(left_avail2) 228 { 229 val_u1 = val_u_l2 >> 2; 230 val_v1 = val_v_l2 >> 2; 231 } 232 else if(top_avail) 233 { 234 val_u1 = val_u_t1 >> 2; 235 val_v1 = val_v_t1 >> 2; 236 } 237 else 238 { 239 val_u1 = val_v1 = 128; 240 } 241 val_u2 = (left_avail2 + top_avail) ? 242 ((val_u_l2 + val_u_t2) 243 >> (1 + left_avail2 + top_avail)) : 128; 244 val_v2 = (left_avail2 + top_avail) ? 245 ((val_v_l2 + val_v_t2) 246 >> (1 + left_avail2 + top_avail)) : 128; 247 248 for(row = 4; row < 8; row++) 249 { /*bottom left 4x4 block*/ 250 for(col = 0; col < 8; col += 2) 251 { 252 *(pu1_dst + row * dst_strd + col) = val_u1; 253 *(pu1_dst + row * dst_strd + col + 1) = val_v1; 254 } 255 /*bottom right 4x4 block*/ 256 for(col = 8; col < 16; col += 2) 257 { 258 *(pu1_dst + row * dst_strd + col) = val_u2; 259 *(pu1_dst + row * dst_strd + col + 1) = val_v2; 260 } 261 } 262 } 263 else 264 { 265 /* Both left and top are unavailable, set the block to 128 */ 266 for(row = 0; row < 8; row++) 267 { 268 memset(pu1_dst + row * dst_strd, 128, 8 * sizeof(UWORD16)); 269 } 270 } 271 } 272 273 /** 274 ******************************************************************************* 275 * 276 *ih264_intra_pred_chroma_8x8_mode_horz 277 * 278 * @brief 279 * Perform Intra prediction for chroma_8x8 mode:Horizontal 280 * 281 * @par Description: 282 * Perform Intra prediction for chroma_8x8 mode:Horizontal ,described in sec 8.3.4.2 283 * 284 * @param[in] pu1_src 285 * UWORD8 pointer to the source containing alternate U and V samples 286 * 287 * @param[out] pu1_dst 288 * UWORD8 pointer to the destination with alternate U and V samples 289 * 290 * @param[in] src_strd 291 * integer source stride 292 * 293 * @param[in] dst_strd 294 * integer destination stride 295 * 296 * @param[in] ngbr_avail 297 * availability of neighbouring pixels(Not used in this function) 298 * 299 * @returns 300 * 301 * @remarks 302 * None 303 * 304 ****************************************************************************** 305 */ 306 void ih264_intra_pred_chroma_8x8_mode_horz(UWORD8 *pu1_src, 307 UWORD8 *pu1_dst, 308 WORD32 src_strd, 309 WORD32 dst_strd, 310 WORD32 ngbr_avail) 311 { 312 313 UWORD8 *pu1_left = NULL; /* Pointer to start of top predictors */ 314 WORD32 rows, cols; /* loop variables*/ 315 UNUSED(src_strd); 316 UNUSED(ngbr_avail); 317 pu1_left = pu1_src + 2 * BLK8x8SIZE - 2; 318 for(rows = 0; rows < 8; rows++) 319 { 320 for(cols = 0; cols < 16; cols += 2) 321 { 322 *(pu1_dst + rows * dst_strd + cols) = *pu1_left; 323 324 *(pu1_dst + rows * dst_strd + cols + 1) = *(pu1_left + 1); 325 } 326 pu1_left -= 2; 327 } 328 329 } 330 331 /** 332 ******************************************************************************* 333 * 334 *ih264_intra_pred_chroma_8x8_mode_vert 335 * 336 * @brief 337 * Perform Intra prediction for chroma_8x8 mode:vertical 338 * 339 * @par Description: 340 * Perform Intra prediction for chroma_8x8 mode:vertical ,described in sec 8.3.4.3 341 * 342 * @param[in] pu1_src 343 * UWORD8 pointer to the source containing alternate U and V samples 344 * 345 * @param[out] pu1_dst 346 * UWORD8 pointer to the destination with alternate U and V samples 347 * 348 * @param[in] src_strd 349 * integer source stride 350 * 351 * @param[in] dst_strd 352 * integer destination stride 353 * 354 * @param[in] ngbr_avail 355 * availability of neighbouring pixels(Not used in this function) 356 * 357 * @returns 358 * 359 * @remarks 360 * None 361 * 362 ******************************************************************************* 363 */ 364 void ih264_intra_pred_chroma_8x8_mode_vert(UWORD8 *pu1_src, 365 UWORD8 *pu1_dst, 366 WORD32 src_strd, 367 WORD32 dst_strd, 368 WORD32 ngbr_avail) 369 { 370 371 UWORD8 *pu1_top = NULL; /* Pointer to start of top predictors */ 372 WORD32 row;/*loop variable*/ 373 UNUSED(src_strd); 374 UNUSED(ngbr_avail); 375 pu1_top = pu1_src + 2 * BLK8x8SIZE + 2; 376 377 /* 8 bytes are copied from src to dst */ 378 for(row = 0; row < 2; row++) 379 { 380 memcpy(pu1_dst, pu1_top, 16); 381 382 pu1_dst += dst_strd; 383 memcpy(pu1_dst, pu1_top, 16); 384 385 pu1_dst += dst_strd; 386 memcpy(pu1_dst, pu1_top, 16); 387 388 pu1_dst += dst_strd; 389 memcpy(pu1_dst, pu1_top, 16); 390 391 pu1_dst += dst_strd; 392 } 393 } 394 395 /** 396 ******************************************************************************* 397 * 398 * ih264_intra_pred_chroma_8x8_mode_plane 399 * 400 * @brief 401 * Perform Intra prediction for chroma_8x8 mode:PLANE 402 * 403 * @par Description: 404 * Perform Intra prediction for chroma_8x8 mode:PLANE ,described in sec 8.3.4.4 405 * 406 * @param[in] pu1_src 407 * UWORD8 pointer to the source containing alternate U and V samples 408 * 409 * @param[out] pu1_dst 410 * UWORD8 pointer to the destination with alternate U and V samples 411 * 412 * @param[in] src_strd 413 * integer source stride 414 * 415 * @param[in] dst_strd 416 * integer destination stride 417 * 418 * @param[in] ngbr_avail 419 * availability of neighbouring pixels(Not used in this function) 420 * 421 * @returns 422 * 423 * @remarks 424 * None 425 * 426 ****************************************************************************** 427 */ 428 void ih264_intra_pred_chroma_8x8_mode_plane(UWORD8 *pu1_src, 429 UWORD8 *pu1_dst, 430 WORD32 src_strd, 431 WORD32 dst_strd, 432 WORD32 ngbr_avail) 433 { 434 435 UWORD8 *pu1_left = NULL; /* Pointer to start of left predictors */ 436 UWORD8 *pu1_top = NULL; /* Pointer to start of top predictors */ 437 WORD32 val = 0; 438 WORD32 rows, cols; /* loop variables*/ 439 WORD32 a_u, b_u, c_u, h_u, v_u; /* Implementing section 8.3.4.4 . The variables represent the corresponding variables in the section*/ 440 WORD32 a_v, b_v, c_v, h_v, v_v; 441 UNUSED(src_strd); 442 UNUSED(ngbr_avail); 443 a_u = b_u = c_u = h_u = v_u = 0; 444 a_v = b_v = c_v = h_v = v_v = 0; 445 /* As chroma format 4:2:0 is used,xCF = 4 * ( chroma_format_idc = = 3 ) = 0 and 446 yCF = 4 * ( chroma_format_idc != 1 ) = 0 */ 447 pu1_top = pu1_src + 2 * BLK8x8SIZE + 2; 448 pu1_left = pu1_src + 2 * BLK8x8SIZE - 2; 449 /* Implementing section 8.3.4.4 */ 450 for(cols = 0; cols < 4; cols++) 451 { 452 h_u += (cols + 1) * (pu1_top[8 + 2 * cols] - pu1_top[4 - 2 * cols]);/*section 8.3.4.4 equation (8-144)*/ 453 h_v += (cols + 1) * (pu1_top[8 + 2 * cols + 1] - pu1_top[4 - 2 * cols+ 1]); 454 455 v_u += (cols + 1) * (pu1_left[(4 + cols) * (-2)] - pu1_left[(2 - cols) * (-2)]); 456 v_v += (cols + 1) * (pu1_left[(4 + cols) * (-2) + 1] - pu1_left[(2 - cols) * (-2) + 1]);/*section 8.3.4.4 equation (8-145)*/ 457 } 458 a_u = 16 * (pu1_left[7 * (-2)] + pu1_top[14]); 459 a_v = 16 * (pu1_left[7 * (-2) + 1] + pu1_top[15]);/*section 8.3.3.4 equation (8-141)*/ 460 b_u = (34 * h_u + 32) >> 6;/*section 8.3.3.4 equation (8-142)*/ 461 b_v = (34 * h_v + 32) >> 6;/*section 8.3.3.4 equation (8-142)*/ 462 c_u = (34 * v_u + 32) >> 6;/*section 8.3.3.4 equation (8-143)*/ 463 c_v = (34 * v_v + 32) >> 6;/*section 8.3.3.4 equation (8-143)*/ 464 465 for(rows = 0; rows < 8; rows++) 466 { 467 for(cols = 0; cols < 8; cols++) 468 { 469 val = (a_u + b_u * (cols - 3) + c_u * (rows - 3) );/*section 8.3.4.4 equation (8-140)*/ 470 val = (val + 16) >> 5; 471 *(pu1_dst + rows * dst_strd + 2 * cols) = CLIP_U8(val); 472 val = (a_v + b_v * (cols - 3) + c_v * (rows - 3) );/*section 8.3.4.4 equation (8-140)*/ 473 val = (val + 16) >> 5; 474 *(pu1_dst + rows * dst_strd + 2 * cols + 1) = CLIP_U8(val); 475 } 476 } 477 } 478 479