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 * ihevc_chroma_intra_pred_filters.c 22 * 23 * @brief 24 * Contains function Definition for intra prediction interpolation filters 25 * 26 * 27 * @author 28 * Ittiam 29 * 30 * @par List of Functions: 31 * ihevc_intra_pred_chroma_planar() 32 * 33 * ihevc_intra_pred_chroma_dc() 34 * 35 * ihevc_intra_pred_chroma_horz() 36 * 37 * ihevc_intra_pred_chroma_ver() 38 * 39 * ihevc_intra_pred_chroma_mode2() 40 * 41 * ihevc_intra_pred_chroma_mode_18_34() 42 * 43 * ihevc_intra_pred_chroma_mode_3_to_9() 44 * 45 * ihevc_intra_pred_chroma_mode_11_to_17() 46 * 47 * ihevc_intra_pred_chroma_mode_19_to_25() 48 * 49 * ihevc_intra_pred_chroma_mode_27_to_33() 50 * 51 * ihevc_intra_pred_chroma_ref_substitution() 52 * 53 * 54 * @remarks 55 * None 56 * 57 ******************************************************************************* 58 */ 59 60 61 /*****************************************************************************/ 62 /* File Includes */ 63 /*****************************************************************************/ 64 65 #include "ihevc_typedefs.h" 66 #include "ihevc_macros.h" 67 #include "ihevc_func_selector.h" 68 #include "ihevc_platform_macros.h" 69 #include "ihevc_intra_pred.h" 70 #include "ihevc_mem_fns.h" 71 #include "ihevc_chroma_intra_pred.h" 72 #include "ihevc_common_tables.h" 73 74 75 /****************************************************************************/ 76 /* Constant Macros */ 77 /****************************************************************************/ 78 #define MAX_CU_SIZE 64 79 #define BIT_DEPTH 8 80 #define T32_4NT 128 81 #define T16_4NT 64 82 #define T16C_4NT 64 83 #define T8C_4NT 32 84 /****************************************************************************/ 85 /* Function Macros */ 86 /****************************************************************************/ 87 88 #define GET_BIT(y,x) ((y) & (1 << x)) && (1 << x) 89 90 91 /*****************************************************************************/ 92 /* Function Definition */ 93 /*****************************************************************************/ 94 95 /** 96 ******************************************************************************* 97 * 98 * @brief 99 * Reference substitution process for samples unavailable for prediction 100 * Refer to section 8.4.4.2.2 101 * 102 * @par Description: 103 * 104 * 105 * @param[in] pu1_top_left 106 * UWORD8 pointer to the top-left 107 * 108 * @param[in] pu1_top 109 * UWORD8 pointer to the top 110 * 111 * @param[in] pu1_left 112 * UWORD8 pointer to the left 113 * 114 * @param[in] src_strd 115 * WORD32 Source stride 116 * 117 * @param[in] nbr_flags 118 * WORD32 neighbor availability flags 119 * 120 * @param[in] nt 121 * WORD32 transform Block size 122 * 123 * @param[in] dst_strd 124 * WORD32 Destination stride 125 * 126 * @returns 127 * 128 * @remarks 129 * None 130 * 131 ******************************************************************************* 132 */ 133 134 135 void ihevc_intra_pred_chroma_ref_substitution(UWORD8 *pu1_top_left, 136 UWORD8 *pu1_top, 137 UWORD8 *pu1_left, 138 WORD32 src_strd, 139 WORD32 nt, 140 WORD32 nbr_flags, 141 UWORD8 *pu1_dst, 142 WORD32 dst_strd) 143 { 144 UWORD8 pu1_ref_u, pu1_ref_v; 145 WORD32 dc_val, i, j; 146 WORD32 total_samples = (4 * nt) + 1; 147 WORD32 get_bits; 148 WORD32 next; 149 WORD32 bot_left, left, top, tp_right, tp_left; 150 WORD32 idx, nbr_id_from_bl, frwd_nbr_flag; 151 WORD32 a_nbr_flag[5]; 152 UNUSED(dst_strd); 153 /* Neighbor Flag Structure*/ 154 /* WORD32 nbr_flags MSB-->LSB TOP LEFT | TOP-RIGHT | TOP | LEFT | BOTTOM LEFT*/ 155 /* (1 bit) (4 bits) (4 bits) (4 bits) (4 bits) */ 156 157 if(nbr_flags == 0) 158 { 159 /* If no neighbor flags are present, fill the neighbor samples with DC value */ 160 /*dc_val = 1 << (BIT_DEPTH - 1);*/ 161 dc_val = 1 << (8 - 1); 162 for(i = 0; i < (2 * total_samples); i++) 163 { 164 pu1_dst[i] = dc_val; 165 } 166 } 167 else 168 { 169 /* Else fill the corresponding samples */ 170 171 /* Check for the neighbors availibility */ 172 tp_left = (nbr_flags & 0x10000); 173 tp_right = (nbr_flags & 0x0f000); 174 top = (nbr_flags & 0x00f00); 175 left = (nbr_flags & 0x000f0); 176 bot_left = (nbr_flags & 0x0000f); 177 178 /* Fill nbrs depending on avalibility */ 179 /* Top -Left nbrs */ 180 if(0 != tp_left) 181 { 182 pu1_dst[(4 * nt)] = *pu1_top_left; // U top-left sample 183 pu1_dst[(4 * nt) + 1] = *(pu1_top_left + 1); // V top-left sample 184 } 185 /* Left nbrs */ 186 if(0 != left) 187 { 188 for(i = 0, j = 0; i < (2 * nt); i += 2) 189 { 190 pu1_dst[(4 * nt) - 2 - i] = pu1_left[j * src_strd]; // U left samples 191 pu1_dst[(4 * nt) - 1 - i] = pu1_left[(j * src_strd) + 1]; // V left samples 192 j++; 193 } 194 } 195 /* Bottom - Left nbrs */ 196 if(0 != bot_left) 197 { 198 for(i = (2 * nt), j = nt; i < (4 * nt); i += 2) 199 { 200 pu1_dst[(4 * nt) - 2 - i] = pu1_left[j * src_strd]; // U left samples 201 pu1_dst[(4 * nt) - 1 - i] = pu1_left[(j * src_strd) + 1]; // V left samples 202 j++; 203 } 204 } 205 /* Top nbrs */ 206 if(0 != top) 207 { 208 ihevc_memcpy_mul_8(&pu1_dst[(4 * nt) + 2], pu1_top, 2 * nt); 209 // U-V interleaved Top-top right samples 210 } 211 212 /* Top - Right nbrs */ 213 if(0 != tp_right) 214 { 215 ihevc_memcpy_mul_8(&pu1_dst[(4 * nt) + 2 + 2 * nt], pu1_top + 2 * nt, 2 * nt); 216 // U-V interleaved Top-top right samples 217 } 218 219 if(nt == 4) 220 { 221 /* 1 bit extraction for all the neighboring blocks */ 222 tp_left = (nbr_flags & 0x10000) >> 16; 223 bot_left = (nbr_flags & 0x8) >> 3; 224 left = (nbr_flags & 0x80) >> 7; 225 top = (nbr_flags & 0x100) >> 8; 226 tp_right = (nbr_flags & 0x1000) >> 12; 227 228 next = 1; 229 a_nbr_flag[0] = bot_left; 230 a_nbr_flag[1] = left; 231 a_nbr_flag[2] = tp_left; 232 a_nbr_flag[3] = top; 233 a_nbr_flag[4] = tp_right; 234 235 /* If bottom -left is not available, reverse substitution process*/ 236 if(bot_left == 0) 237 { 238 /* Check for the 1st available sample from bottom-left*/ 239 while(!a_nbr_flag[next]) 240 next++; 241 242 /* If Left, top-left are available*/ 243 if(next <= 2) 244 { 245 UWORD16 *pu2_dst; 246 idx = (nt * next); 247 pu2_dst = (UWORD16 *)&pu1_dst[2 * idx]; 248 ihevc_memset_16bit((UWORD16 *)pu1_dst, pu2_dst[0], idx); 249 } 250 else /* If top, top-right are available */ 251 { 252 UWORD16 *pu2_dst; 253 /* Idx is changed to copy 1 pixel value for top-left ,if top-left is not available*/ 254 idx = (nt * (next - 1)) + 1; 255 pu2_dst = (UWORD16 *)&pu1_dst[2 * idx]; 256 ihevc_memset_16bit((UWORD16 *)pu1_dst, pu2_dst[0], idx); 257 } 258 } 259 260 if(left == 0) 261 { 262 UWORD16 *pu2_dst = (UWORD16 *)&pu1_dst[(2 * nt) - 2]; 263 ihevc_memset_16bit((UWORD16 *)&pu1_dst[(2 * nt)], pu2_dst[0], nt); 264 265 266 } 267 if(tp_left == 0) 268 { 269 pu1_dst[4 * nt] = pu1_dst[(4 * nt) - 2]; 270 pu1_dst[(4 * nt) + 1] = pu1_dst[(4 * nt) - 1]; 271 } 272 if(top == 0) 273 { 274 UWORD16 *pu2_dst = (UWORD16 *)&pu1_dst[(4 * nt)]; 275 ihevc_memset_16bit((UWORD16 *)&pu1_dst[(4 * nt) + 2], pu2_dst[0], nt); 276 277 278 } 279 if(tp_right == 0) 280 { 281 UWORD16 *pu2_dst = (UWORD16 *)&pu1_dst[(6 * nt)]; 282 ihevc_memset_16bit((UWORD16 *)&pu1_dst[(6 * nt) + 2], pu2_dst[0], nt); 283 284 285 } 286 } 287 else if(nt == 8) 288 { 289 WORD32 nbr_flags_temp = 0; 290 nbr_flags_temp = ((nbr_flags & 0xC) >> 2) + ((nbr_flags & 0xC0) >> 4) 291 + ((nbr_flags & 0x300) >> 4) 292 + ((nbr_flags & 0x3000) >> 6) 293 + ((nbr_flags & 0x10000) >> 8); 294 295 /* compute trailing zeors based on nbr_flag for substitution process of below left see section .*/ 296 /* as each bit in nbr flags corresponds to 8 pels for bot_left, left, top and topright but 1 pel for topleft */ 297 { 298 nbr_id_from_bl = look_up_trailing_zeros(nbr_flags_temp & 0XF) * 4; /* for bottom left and left */ 299 if(nbr_id_from_bl == 32) 300 nbr_id_from_bl = 16; 301 if(nbr_id_from_bl == 16) 302 { 303 /* for top left : 1 pel per nbr bit */ 304 if(!((nbr_flags_temp >> 8) & 0x1)) 305 { 306 nbr_id_from_bl++; 307 nbr_id_from_bl += look_up_trailing_zeros((nbr_flags_temp >> 4) & 0xF) * 4; /* top and top right; 8 pels per nbr bit */ 308 309 } 310 } 311 /* Reverse Substitution Process*/ 312 if(nbr_id_from_bl) 313 { 314 /* Replicate the bottom-left and subsequent unavailable pixels with the 1st available pixel above */ 315 pu1_ref_u = pu1_dst[2 * nbr_id_from_bl]; 316 pu1_ref_v = pu1_dst[(2 * nbr_id_from_bl) + 1]; 317 for(i = 2 * (nbr_id_from_bl - 1); i >= 0; i -= 2) 318 { 319 pu1_dst[i] = pu1_ref_u; 320 pu1_dst[i + 1] = pu1_ref_v; 321 } 322 } 323 } 324 325 /* for the loop of 4*Nt+1 pixels (excluding pixels computed from reverse substitution) */ 326 while(nbr_id_from_bl < ((T8C_4NT)+1)) 327 { 328 /* To Obtain the next unavailable idx flag after reverse neighbor substitution */ 329 /* Divide by 8 to obtain the original index */ 330 frwd_nbr_flag = (nbr_id_from_bl >> 2); /*+ (nbr_id_from_bl & 0x1);*/ 331 332 /* The Top-left flag is at the last bit location of nbr_flags*/ 333 if(nbr_id_from_bl == (T8C_4NT / 2)) 334 { 335 get_bits = GET_BIT(nbr_flags_temp, 8); 336 337 /* only pel substitution for TL */ 338 if(!get_bits) 339 { 340 pu1_dst[2 * nbr_id_from_bl] = pu1_dst[(2 * nbr_id_from_bl) - 2]; 341 pu1_dst[(2 * nbr_id_from_bl) + 1] = pu1_dst[(2 * nbr_id_from_bl) - 1]; 342 } 343 } 344 else 345 { 346 get_bits = GET_BIT(nbr_flags_temp, frwd_nbr_flag); 347 if(!get_bits) 348 { 349 UWORD16 *pu2_dst; 350 /* 8 pel substitution (other than TL) */ 351 pu2_dst = (UWORD16 *)&pu1_dst[(2 * nbr_id_from_bl) - 2]; 352 ihevc_memset_16bit((UWORD16 *)(pu1_dst + (2 * nbr_id_from_bl)), pu2_dst[0], 4); 353 } 354 355 } 356 nbr_id_from_bl += (nbr_id_from_bl == (T8C_4NT / 2)) ? 1 : 4; 357 } 358 359 } 360 else if(nt == 16) 361 { 362 /* compute trailing ones based on mbr_flag for substitution process of below left see section .*/ 363 /* as each bit in nbr flags corresponds to 4 pels for bot_left, left, top and topright but 1 pel for topleft */ 364 { 365 nbr_id_from_bl = look_up_trailing_zeros((nbr_flags & 0XFF)) * 4; /* for bottom left and left */ 366 367 if(nbr_id_from_bl == 32) 368 { 369 /* for top left : 1 pel per nbr bit */ 370 if(!((nbr_flags >> 16) & 0x1)) 371 { 372 /* top left not available */ 373 nbr_id_from_bl++; 374 /* top and top right; 4 pels per nbr bit */ 375 nbr_id_from_bl += look_up_trailing_zeros((nbr_flags >> 8) & 0xFF) * 4; 376 } 377 } 378 /* Reverse Substitution Process*/ 379 if(nbr_id_from_bl) 380 { 381 /* Replicate the bottom-left and subsequent unavailable pixels with the 1st available pixel above */ 382 pu1_ref_u = pu1_dst[2 * nbr_id_from_bl]; 383 pu1_ref_v = pu1_dst[2 * nbr_id_from_bl + 1]; 384 for(i = (2 * (nbr_id_from_bl - 1)); i >= 0; i -= 2) 385 { 386 pu1_dst[i] = pu1_ref_u; 387 pu1_dst[i + 1] = pu1_ref_v; 388 } 389 } 390 } 391 392 /* for the loop of 4*Nt+1 pixels (excluding pixels computed from reverse substitution) */ 393 while(nbr_id_from_bl < ((T16C_4NT)+1)) 394 { 395 /* To Obtain the next unavailable idx flag after reverse neighbor substitution */ 396 /* Devide by 4 to obtain the original index */ 397 frwd_nbr_flag = (nbr_id_from_bl >> 2); /*+ (nbr_id_from_bl & 0x1);*/ 398 399 /* The Top-left flag is at the last bit location of nbr_flags*/ 400 if(nbr_id_from_bl == (T16C_4NT / 2)) 401 { 402 get_bits = GET_BIT(nbr_flags, 16); 403 /* only pel substitution for TL */ 404 if(!get_bits) 405 { 406 pu1_dst[2 * nbr_id_from_bl] = pu1_dst[(2 * nbr_id_from_bl) - 2]; 407 pu1_dst[(2 * nbr_id_from_bl) + 1] = pu1_dst[(2 * nbr_id_from_bl) - 1]; 408 } 409 } 410 else 411 { 412 get_bits = GET_BIT(nbr_flags, frwd_nbr_flag); 413 if(!get_bits) 414 { 415 UWORD16 *pu2_dst; 416 /* 4 pel substitution (other than TL) */ 417 pu2_dst = (UWORD16 *)&pu1_dst[(2 * nbr_id_from_bl) - 2]; 418 ihevc_memset_16bit((UWORD16 *)(pu1_dst + (2 * nbr_id_from_bl)), pu2_dst[0], 4); 419 } 420 421 } 422 nbr_id_from_bl += (nbr_id_from_bl == (T16C_4NT / 2)) ? 1 : 4; 423 } 424 } 425 } 426 } 427 428 429 /** 430 ******************************************************************************* 431 * 432 * @brief 433 * Planar Intraprediction with reference neighboring samples location 434 * pointed by 'pu1_ref' to the TU block location pointed by 'pu1_dst' Refer 435 * to section 8.4.4.2.4 in the standard 436 * 437 * @par Description: 438 * 439 * 440 * @param[in] pu1_src 441 * UWORD8 pointer to the source 442 * 443 * @param[in] pu1_dst 444 * UWORD8 pointer to the destination 445 * 446 * @param[in] src_strd 447 * integer source stride 448 * 449 * @param[in] dst_strd 450 * integer destination stride 451 * 452 * @param[in] nt 453 * integer Transform Block size 454 * 455 * @param[in] mode 456 * integer intraprediction mode 457 * 458 * @returns 459 * 460 * @remarks 461 * None 462 * 463 ******************************************************************************* 464 */ 465 466 467 void ihevc_intra_pred_chroma_planar(UWORD8 *pu1_ref, 468 WORD32 src_strd, 469 UWORD8 *pu1_dst, 470 WORD32 dst_strd, 471 WORD32 nt, 472 WORD32 mode) 473 { 474 475 WORD32 row, col; 476 WORD32 log2nt = 5; 477 WORD32 two_nt, three_nt; 478 UNUSED(src_strd); 479 UNUSED(mode); 480 switch(nt) 481 { 482 case 16: 483 log2nt = 4; 484 break; 485 case 8: 486 log2nt = 3; 487 break; 488 case 4: 489 log2nt = 2; 490 break; 491 default: 492 break; 493 } 494 two_nt = 2 * nt; 495 three_nt = 3 * nt; 496 /* Planar filtering */ 497 for(row = 0; row < nt; row++) 498 { 499 for(col = 0; col < (2 * nt); col += 2) 500 { 501 pu1_dst[row * dst_strd + col] = ((nt - 1 - col / 2) 502 * pu1_ref[2 * (two_nt - 1 - row)] 503 + (col / 2 + 1) * pu1_ref[2 * (three_nt + 1)] 504 + (nt - 1 - row) * pu1_ref[2 * (two_nt + 1) + col] 505 + (row + 1) * pu1_ref[2 * (nt - 1)] + nt) >> (log2nt + 1); 506 507 pu1_dst[row * dst_strd + col + 1] = ((nt - 1 - col / 2) 508 * pu1_ref[2 * (two_nt - 1 - row) + 1] 509 + (col / 2 + 1) * pu1_ref[2 * (three_nt + 1) + 1] 510 + (nt - 1 - row) * pu1_ref[2 * (two_nt + 1) + col + 1] 511 + (row + 1) * pu1_ref[2 * (nt - 1) + 1] + nt) >> (log2nt + 1); 512 } 513 } 514 } 515 516 517 /** 518 ******************************************************************************* 519 * 520 * @brief 521 * Intraprediction for DC mode with reference neighboring samples location 522 * pointed by 'pu1_ref' to the TU block location pointed by 'pu1_dst' Refer 523 * to section 8.4.4.2.5 in the standard 524 * 525 * @par Description: 526 * 527 * 528 * @param[in] pu1_src 529 * UWORD8 pointer to the source 530 * 531 * @param[in] pu1_dst 532 * UWORD8 pointer to the destination 533 * 534 * @param[in] src_strd 535 * integer source stride 536 * 537 * @param[in] dst_strd 538 * integer destination stride 539 * 540 * @param[in] nt 541 * integer Transform Block size (Chroma) 542 * 543 * @param[in] mode 544 * integer intraprediction mode 545 * 546 * @returns 547 * 548 * @remarks 549 * None 550 * 551 ******************************************************************************* 552 */ 553 554 555 void ihevc_intra_pred_chroma_dc(UWORD8 *pu1_ref, 556 WORD32 src_strd, 557 UWORD8 *pu1_dst, 558 WORD32 dst_strd, 559 WORD32 nt, 560 WORD32 mode) 561 { 562 563 WORD32 acc_dc_u, acc_dc_v; 564 WORD32 dc_val_u, dc_val_v; 565 WORD32 i; 566 WORD32 row, col; 567 WORD32 log2nt = 5; 568 UNUSED(mode); 569 UNUSED(src_strd); 570 switch(nt) 571 { 572 case 32: 573 log2nt = 5; 574 break; 575 case 16: 576 log2nt = 4; 577 break; 578 case 8: 579 log2nt = 3; 580 break; 581 case 4: 582 log2nt = 2; 583 break; 584 default: 585 break; 586 } 587 588 589 acc_dc_u = 0; 590 acc_dc_v = 0; 591 /* Calculate DC value for the transform block */ 592 for(i = (2 * nt); i < (4 * nt); i += 2) 593 { 594 acc_dc_u += pu1_ref[i]; 595 acc_dc_v += pu1_ref[i + 1]; 596 } 597 for(i = ((4 * nt) + 2); i < ((6 * nt) + 2); i += 2) 598 { 599 acc_dc_u += pu1_ref[i]; 600 acc_dc_v += pu1_ref[i + 1]; 601 } 602 603 604 dc_val_u = (acc_dc_u + nt) >> (log2nt + 1); 605 dc_val_v = (acc_dc_v + nt) >> (log2nt + 1); 606 607 608 /* Fill the remaining rows with DC value*/ 609 for(row = 0; row < nt; row++) 610 { 611 for(col = 0; col < (2 * nt); col += 2) 612 { 613 pu1_dst[(row * dst_strd) + col] = dc_val_u; 614 pu1_dst[(row * dst_strd) + col + 1] = dc_val_v; 615 } 616 } 617 618 } 619 620 621 /** 622 ******************************************************************************* 623 * 624 * @brief 625 * Horizontal intraprediction(mode 10) with reference samples location 626 * pointed by 'pu1_ref' to the TU block location pointed by 'pu1_dst' Refer 627 * to section 8.4.4.2.6 in the standard (Special case) 628 * 629 * @par Description: 630 * 631 * 632 * @param[in] pu1_src 633 * UWORD8 pointer to the source 634 * 635 * @param[in] pu1_dst 636 * UWORD8 pointer to the destination 637 * 638 * @param[in] src_strd 639 * integer source stride 640 * 641 * @param[in] dst_strd 642 * integer destination stride 643 * 644 * @param[in] nt 645 * integer Transform Block size 646 * 647 * @param[in] mode 648 * integer intraprediction mode 649 * 650 * @returns 651 * 652 * @remarks 653 * None 654 * 655 ******************************************************************************* 656 */ 657 658 659 void ihevc_intra_pred_chroma_horz(UWORD8 *pu1_ref, 660 WORD32 src_strd, 661 UWORD8 *pu1_dst, 662 WORD32 dst_strd, 663 WORD32 nt, 664 WORD32 mode) 665 { 666 667 WORD32 row, col; 668 UNUSED(mode); 669 UNUSED(src_strd); 670 /* Replication to next rows*/ 671 for(row = 0; row < nt; row++) 672 { 673 for(col = 0; col < (2 * nt); col += 2) 674 { 675 pu1_dst[(row * dst_strd) + col] = pu1_ref[(4 * nt) - 2 - 2 * row]; 676 pu1_dst[(row * dst_strd) + col + 1] = pu1_ref[(4 * nt) - 1 - 2 * row]; 677 } 678 } 679 } 680 681 682 683 /** 684 ******************************************************************************* 685 * 686 * @brief 687 * Horizontal intraprediction with reference neighboring samples location 688 * pointed by 'pu1_ref' to the TU block location pointed by 'pu1_dst' Refer 689 * to section 8.4.4.2.6 in the standard (Special case) 690 * 691 * @par Description: 692 * 693 * 694 * @param[in] pu1_src 695 * UWORD8 pointer to the source 696 * 697 * @param[in] pu1_dst 698 * UWORD8 pointer to the destination 699 * 700 * @param[in] src_strd 701 * integer source stride 702 * 703 * @param[in] dst_strd 704 * integer destination stride 705 * 706 * @param[in] nt 707 * integer Transform Block size 708 * 709 * @param[in] mode 710 * integer intraprediction mode 711 * 712 * @returns 713 * 714 * @remarks 715 * None 716 * 717 ******************************************************************************* 718 */ 719 720 721 void ihevc_intra_pred_chroma_ver(UWORD8 *pu1_ref, 722 WORD32 src_strd, 723 UWORD8 *pu1_dst, 724 WORD32 dst_strd, 725 WORD32 nt, 726 WORD32 mode) 727 { 728 WORD32 row, col; 729 UNUSED(mode); 730 UNUSED(src_strd); 731 /* Replication to next columns*/ 732 for(row = 0; row < nt; row++) 733 { 734 for(col = 0; col < (2 * nt); col += 2) 735 { 736 pu1_dst[(row * dst_strd) + col] = pu1_ref[(4 * nt) + 2 + col]; 737 pu1_dst[(row * dst_strd) + col + 1] = pu1_ref[(4 * nt) + 3 + col]; 738 } 739 } 740 } 741 742 743 /** 744 ******************************************************************************* 745 * 746 * @brief 747 * Intraprediction for mode 2 (sw angle) with reference neighboring samples 748 * location pointed by 'pu1_ref' to the TU block location pointed by 749 * 'pu1_dst' Refer to section 8.4.4.2.6 in the standard 750 * 751 * @par Description: 752 * 753 * 754 * @param[in] pu1_src 755 * UWORD8 pointer to the source 756 * 757 * @param[in] pu1_dst 758 * UWORD8 pointer to the destination 759 * 760 * @param[in] src_strd 761 * integer source stride 762 * 763 * @param[in] dst_strd 764 * integer destination stride 765 * 766 * @param[in] nt 767 * integer Transform Block size 768 * 769 * @param[in] mode 770 * integer intraprediction mode 771 * 772 * @returns 773 * 774 * @remarks 775 * None 776 * 777 ******************************************************************************* 778 */ 779 780 781 void ihevc_intra_pred_chroma_mode2(UWORD8 *pu1_ref, 782 WORD32 src_strd, 783 UWORD8 *pu1_dst, 784 WORD32 dst_strd, 785 WORD32 nt, 786 WORD32 mode) 787 { 788 WORD32 row, col; 789 790 WORD32 intra_pred_ang = 32; 791 WORD32 idx_u, idx_v; 792 UNUSED(src_strd); 793 UNUSED(mode); 794 /* For the angle 45, replication is done from the corresponding angle */ 795 /* intra_pred_ang = tan(angle) in q5 format */ 796 for(col = 0; col < (2 * nt); col += 2) 797 { 798 idx_u = ((col + 1) * intra_pred_ang) >> 5; /* Use idx++ */ 799 idx_v = (((col + 1) + 1) * intra_pred_ang) >> 5; /* Use idx++ */ 800 for(row = 0; row < nt; row++) 801 { 802 pu1_dst[col + (row * dst_strd)] = pu1_ref[(4 * nt) - 2 * row - idx_u - 3]; 803 pu1_dst[(col + 1) + (row * dst_strd)] = pu1_ref[(4 * nt) - 2 * row - idx_v - 1]; 804 } 805 } 806 807 } 808 809 810 /** 811 ******************************************************************************* 812 * 813 * @brief 814 * Intraprediction for mode 34 (ne angle) and mode 18 (nw angle) with 815 * reference neighboring samples location pointed by 'pu1_ref' to the TU 816 * block location pointed by 'pu1_dst' 817 * 818 * @par Description: 819 * 820 * 821 * @param[in] pu1_src 822 * UWORD8 pointer to the source 823 * 824 * @param[in] pu1_dst 825 * UWORD8 pointer to the destination 826 * 827 * @param[in] src_strd 828 * integer source stride 829 * 830 * @param[in] dst_strd 831 * integer destination stride 832 * 833 * @param[in] nt 834 * integer Transform Block size 835 * 836 * @param[in] mode 837 * integer intraprediction mode 838 * 839 * @returns 840 * 841 * @remarks 842 * None 843 * 844 ******************************************************************************* 845 */ 846 847 848 void ihevc_intra_pred_chroma_mode_18_34(UWORD8 *pu1_ref, 849 WORD32 src_strd, 850 UWORD8 *pu1_dst, 851 WORD32 dst_strd, 852 WORD32 nt, 853 WORD32 mode) 854 { 855 WORD32 row, col; 856 WORD32 intra_pred_ang; 857 WORD32 idx = 0; 858 UNUSED(src_strd); 859 intra_pred_ang = 32; /*Default value*/ 860 /* For mode 18, angle is -45degree */ 861 if(mode == 18) 862 intra_pred_ang = -32; 863 /* For mode 34, angle is 45degree */ 864 else if(mode == 34) 865 intra_pred_ang = 32; 866 /* For the angle 45 and -45, replication is done from the corresponding angle */ 867 /* No interpolation is done for 45 degree*/ 868 for(row = 0; row < nt; row++) 869 { 870 idx = ((row + 1) * intra_pred_ang) >> 5; 871 872 for(col = 0; col < (2 * nt); col += 2) 873 { 874 pu1_dst[col + (row * dst_strd)] = pu1_ref[(4 * nt) + col + 2 * idx + 2]; 875 pu1_dst[(col + 1) + (row * dst_strd)] = pu1_ref[(4 * nt) + (col + 1) + 2 * idx + 2]; 876 } 877 878 } 879 880 } 881 882 883 /** 884 ******************************************************************************* 885 * 886 * @brief 887 * Intraprediction for mode 3 to 9 (positive angle, horizontal mode ) with 888 * reference neighboring samples location pointed by 'pu1_ref' to the TU 889 * block location pointed by 'pu1_dst' 890 * 891 * @par Description: 892 * 893 * 894 * @param[in] pu1_src 895 * UWORD8 pointer to the source 896 * 897 * @param[in] pu1_dst 898 * UWORD8 pointer to the destination 899 * 900 * @param[in] src_strd 901 * integer source stride 902 * 903 * @param[in] dst_strd 904 * integer destination stride 905 * 906 * @param[in] nt 907 * integer Transform Block size 908 * 909 * @param[in] mode 910 * integer intraprediction mode 911 * 912 * @returns 913 * 914 * @remarks 915 * None 916 * 917 ******************************************************************************* 918 */ 919 920 921 void ihevc_intra_pred_chroma_mode_3_to_9(UWORD8 *pu1_ref, 922 WORD32 src_strd, 923 UWORD8 *pu1_dst, 924 WORD32 dst_strd, 925 WORD32 nt, 926 WORD32 mode) 927 { 928 WORD32 row, col; 929 930 WORD32 intra_pred_ang; 931 WORD32 idx_u, ref_main_idx_u; 932 WORD32 idx_v, ref_main_idx_v; 933 WORD32 pos_u, fract_u; 934 WORD32 pos_v, fract_v; 935 UNUSED(src_strd); 936 /* Intra Pred Angle according to the mode */ 937 intra_pred_ang = gai4_ihevc_ang_table[mode]; 938 939 /* For the angles other then 45 degree, interpolation btw 2 neighboring */ 940 /* samples dependent on distance to obtain destination sample */ 941 942 for(col = 0; col < (2 * nt); col += 2) 943 { 944 pos_u = ((col / 2 + 1) * intra_pred_ang); 945 pos_v = ((col / 2 + 1) * intra_pred_ang); 946 947 idx_u = pos_u >> 5; 948 fract_u = pos_u & (31); 949 950 idx_v = pos_v >> 5; 951 fract_v = pos_v & (31); 952 // Do linear filtering 953 for(row = 0; row < nt; row++) 954 { 955 ref_main_idx_u = (4 * nt) - 2 * row - 2 * idx_u - 2; 956 ref_main_idx_v = (4 * nt) - 2 * row - 2 * idx_v - 1; 957 958 pu1_dst[col + (row * dst_strd)] = (((32 - fract_u) 959 * pu1_ref[ref_main_idx_u] 960 + fract_u * pu1_ref[ref_main_idx_u - 2] + 16) >> 5); 961 962 pu1_dst[(col + 1) + (row * dst_strd)] = (((32 - fract_v) 963 * pu1_ref[ref_main_idx_v] 964 + fract_v * pu1_ref[ref_main_idx_v - 2] + 16) >> 5); 965 } 966 967 } 968 969 } 970 971 972 /** 973 ******************************************************************************* 974 * 975 * @brief 976 * Intraprediction for mode 11 to 17 (negative angle, horizontal mode ) 977 * with reference neighboring samples location pointed by 'pu1_ref' to the 978 * TU block location pointed by 'pu1_dst' 979 * 980 * @par Description: 981 * 982 * 983 * @param[in] pu1_src 984 * UWORD8 pointer to the source 985 * 986 * @param[in] pu1_dst 987 * UWORD8 pointer to the destination 988 * 989 * @param[in] src_strd 990 * integer source stride 991 * 992 * @param[in] dst_strd 993 * integer destination stride 994 * 995 * @param[in] nt 996 * integer Transform Block size 997 * 998 * @param[in] mode 999 * integer intraprediction mode 1000 * 1001 * @returns 1002 * 1003 * @remarks 1004 * None 1005 * 1006 ******************************************************************************* 1007 */ 1008 1009 1010 void ihevc_intra_pred_chroma_mode_11_to_17(UWORD8 *pu1_ref, 1011 WORD32 src_strd, 1012 UWORD8 *pu1_dst, 1013 WORD32 dst_strd, 1014 WORD32 nt, 1015 WORD32 mode) 1016 { 1017 /* This function and ihevc_intra_pred_CHROMA_mode_19_to_25 are same except*/ 1018 /* for ref main & side samples assignment,can be combined for */ 1019 /* optimzation*/ 1020 1021 WORD32 row, col, k; 1022 WORD32 intra_pred_ang, inv_ang, inv_ang_sum; 1023 WORD32 idx_u, idx_v, ref_main_idx_u, ref_main_idx_v, ref_idx; 1024 WORD32 pos_u, pos_v, fract_u, fract_v; 1025 1026 UWORD8 ref_temp[2 * MAX_CU_SIZE + 2]; 1027 UWORD8 *ref_main; 1028 UNUSED(src_strd); 1029 inv_ang_sum = 128; 1030 1031 intra_pred_ang = gai4_ihevc_ang_table[mode]; 1032 1033 inv_ang = gai4_ihevc_inv_ang_table[mode - 11]; 1034 /* Intermediate reference samples for negative angle modes */ 1035 /* This have to be removed during optimization*/ 1036 1037 /* For horizontal modes, (ref main = ref left) (ref side = ref above) */ 1038 1039 1040 ref_main = ref_temp + 2 * nt; 1041 for(k = 0; k < (2 * (nt + 1)); k += 2) 1042 { 1043 ref_temp[k + (2 * (nt - 1))] = pu1_ref[(4 * nt) - k]; 1044 ref_temp[k + 1 + (2 * (nt - 1))] = pu1_ref[(4 * nt) - k + 1]; 1045 } 1046 1047 ref_main = ref_temp + (2 * (nt - 1)); 1048 ref_idx = (nt * intra_pred_ang) >> 5; 1049 1050 /* SIMD Optimization can be done using look-up table for the loop */ 1051 /* For negative angled derive the main reference samples from side */ 1052 /* reference samples refer to section 8.4.4.2.6 */ 1053 for(k = -2; k > (2 * ref_idx); k -= 2) 1054 { 1055 inv_ang_sum += inv_ang; 1056 ref_main[k] = pu1_ref[(4 * nt) + ((inv_ang_sum >> 8) << 1)]; 1057 ref_main[k + 1] = pu1_ref[((4 * nt) + 1) + ((inv_ang_sum >> 8) << 1)]; 1058 } 1059 1060 /* For the angles other then 45 degree, interpolation btw 2 neighboring */ 1061 /* samples dependent on distance to obtain destination sample */ 1062 for(col = 0; col < (2 * nt); col += 2) 1063 { 1064 pos_u = ((col / 2 + 1) * intra_pred_ang); 1065 pos_v = ((col / 2 + 1) * intra_pred_ang); 1066 idx_u = pos_u >> 5; 1067 idx_v = pos_v >> 5; 1068 fract_u = pos_u & (31); 1069 fract_v = pos_v & (31); 1070 1071 // Do linear filtering 1072 for(row = 0; row < nt; row++) 1073 { 1074 ref_main_idx_u = 2 * (row + idx_u + 1); 1075 ref_main_idx_v = 2 * (row + idx_v + 1) + 1; 1076 1077 pu1_dst[col + (dst_strd * row)] = (UWORD8)(((32 - fract_u) 1078 * ref_main[ref_main_idx_u] 1079 + fract_u * ref_main[ref_main_idx_u + 2] + 16) >> 5); 1080 pu1_dst[(col + 1) + (dst_strd * row)] = (UWORD8)(((32 - fract_v) 1081 * ref_main[ref_main_idx_v] 1082 + fract_v * ref_main[ref_main_idx_v + 2] + 16) >> 5); 1083 1084 } 1085 1086 } 1087 1088 } 1089 1090 1091 1092 /** 1093 ******************************************************************************* 1094 * 1095 * @brief 1096 * Intraprediction for mode 19 to 25 (negative angle, vertical mode ) with 1097 * reference neighboring samples location pointed by 'pu1_ref' to the TU 1098 * block location pointed by 'pu1_dst' 1099 * 1100 * @par Description: 1101 * 1102 * 1103 * @param[in] pu1_src 1104 * UWORD8 pointer to the source 1105 * 1106 * @param[in] pu1_dst 1107 * UWORD8 pointer to the destination 1108 * 1109 * @param[in] src_strd 1110 * integer source stride 1111 * 1112 * @param[in] dst_strd 1113 * integer destination stride 1114 * 1115 * @param[in] nt 1116 * integer Transform Block size 1117 * 1118 * @param[in] mode 1119 * integer intraprediction mode 1120 * 1121 * @returns 1122 * 1123 * @remarks 1124 * None 1125 * 1126 ******************************************************************************* 1127 */ 1128 1129 1130 void ihevc_intra_pred_chroma_mode_19_to_25(UWORD8 *pu1_ref, 1131 WORD32 src_strd, 1132 UWORD8 *pu1_dst, 1133 WORD32 dst_strd, 1134 WORD32 nt, 1135 WORD32 mode) 1136 { 1137 1138 WORD32 row, col, k; 1139 WORD32 intra_pred_ang, idx; 1140 WORD32 inv_ang, inv_ang_sum, pos, fract; 1141 WORD32 ref_main_idx_u, ref_main_idx_v, ref_idx; 1142 UWORD8 ref_temp[(2 * MAX_CU_SIZE) + 2]; 1143 UWORD8 *ref_main; 1144 UNUSED(src_strd); 1145 1146 1147 intra_pred_ang = gai4_ihevc_ang_table_chroma[mode]; 1148 inv_ang = gai4_ihevc_inv_ang_table_chroma[mode - 12]; 1149 1150 /* Intermediate reference samples for negative angle modes */ 1151 /* This have to be removed during optimization*/ 1152 /* For horizontal modes, (ref main = ref above) (ref side = ref left) */ 1153 ref_main = ref_temp + 2 * nt; 1154 for(k = 0; k < (2 * (nt + 1)); k += 2) 1155 { 1156 ref_temp[k + (2 * (nt - 1))] = pu1_ref[(4 * nt) + k]; 1157 ref_temp[k + 1 + (2 * (nt - 1))] = pu1_ref[(4 * nt) + k + 1]; 1158 } 1159 1160 1161 ref_idx = (nt * intra_pred_ang) >> 5; 1162 inv_ang_sum = 128; 1163 ref_main = ref_temp + (2 * (nt - 1)); 1164 /* SIMD Optimization can be done using look-up table for the loop */ 1165 /* For negative angled derive the main reference samples from side */ 1166 /* reference samples refer to section 8.4.4.2.6 */ 1167 for(k = -2; k > (2 * ref_idx); k -= 2) 1168 { 1169 inv_ang_sum += inv_ang; 1170 ref_main[k] = pu1_ref[(4 * nt) - (inv_ang_sum >> 8) * 2]; 1171 ref_main[k + 1] = pu1_ref[((4 * nt) + 1) - (inv_ang_sum >> 8) * 2]; 1172 } 1173 1174 for(row = 0; row < nt; row++) 1175 { 1176 pos = ((row + 1) * intra_pred_ang); 1177 idx = pos >> 5; 1178 fract = pos & (31); 1179 1180 // Do linear filtering 1181 for(col = 0; col < (2 * nt); col += 2) 1182 { 1183 ref_main_idx_u = col + 2 * idx + 2; 1184 ref_main_idx_v = (col + 1) + 2 * idx + 2; 1185 pu1_dst[(row * dst_strd) + col] = (UWORD8)(((32 - fract) 1186 * ref_main[ref_main_idx_u] 1187 + fract * ref_main[ref_main_idx_u + 2] + 16) >> 5); 1188 pu1_dst[(row * dst_strd) + (col + 1)] = (UWORD8)(((32 - fract) 1189 * ref_main[ref_main_idx_v] 1190 + fract * ref_main[ref_main_idx_v + 2] + 16) >> 5); 1191 1192 } 1193 1194 } 1195 1196 } 1197 1198 1199 1200 /** 1201 ******************************************************************************* 1202 * 1203 * @brief 1204 * Intraprediction for mode 27 to 33 (positive angle, vertical mode ) with 1205 * reference neighboring samples location pointed by 'pu1_ref' to the TU 1206 * block location pointed by 'pu1_dst' 1207 * 1208 * @par Description: 1209 * 1210 * 1211 * @param[in] pu1_src 1212 * UWORD8 pointer to the source 1213 * 1214 * @param[in] pu1_dst 1215 * UWORD8 pointer to the destination 1216 * 1217 * @param[in] src_strd 1218 * integer source stride 1219 * 1220 * @param[in] dst_strd 1221 * integer destination stride 1222 * 1223 * @param[in] nt 1224 * integer Transform Block size 1225 * 1226 * @param[in] mode 1227 * integer intraprediction mode 1228 * 1229 * @returns 1230 * 1231 * @remarks 1232 * None 1233 * 1234 ******************************************************************************* 1235 */ 1236 1237 1238 void ihevc_intra_pred_chroma_mode_27_to_33(UWORD8 *pu1_ref, 1239 WORD32 src_strd, 1240 UWORD8 *pu1_dst, 1241 WORD32 dst_strd, 1242 WORD32 nt, 1243 WORD32 mode) 1244 { 1245 WORD32 row, col; 1246 WORD32 pos, fract; 1247 WORD32 intra_pred_ang; 1248 WORD32 idx, ref_main_idx_u, ref_main_idx_v; 1249 UNUSED(src_strd); 1250 1251 1252 intra_pred_ang = gai4_ihevc_ang_table_chroma[mode]; 1253 1254 for(row = 0; row < nt; row++) 1255 { 1256 pos = ((row + 1) * intra_pred_ang); 1257 idx = pos >> 5; 1258 fract = pos & (31); 1259 1260 1261 // Do linear filtering 1262 for(col = 0; col < (2 * nt); col += 2) 1263 { 1264 ref_main_idx_u = (4 * nt) + col + 2 * idx + 2; 1265 ref_main_idx_v = (4 * nt) + (col + 1) + 2 * idx + 2; 1266 pu1_dst[col + (row * dst_strd)] = (((32 - fract) 1267 * pu1_ref[ref_main_idx_u] 1268 + fract * pu1_ref[ref_main_idx_u + 2] + 16) >> 5); 1269 pu1_dst[(col + 1) + (row * dst_strd)] = (((32 - fract) 1270 * pu1_ref[ref_main_idx_v] 1271 + fract * pu1_ref[ref_main_idx_v + 2] + 16) >> 5); 1272 1273 } 1274 } 1275 1276 } 1277 1278