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_fmt_conv.c 22 * 23 * @brief 24 * Contains functions for format conversion or frame copy of output buffer 25 * 26 * @author 27 * Harish 28 * 29 * @par List of Functions: 30 * 31 * @remarks 32 * None 33 * 34 ******************************************************************************* 35 */ 36 /*****************************************************************************/ 37 /* File Includes */ 38 /*****************************************************************************/ 39 #include <stdio.h> 40 #include <stddef.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <assert.h> 44 45 #include "ihevc_typedefs.h" 46 #include "iv.h" 47 #include "ivd.h" 48 #include "ihevcd_cxa.h" 49 #include "ithread.h" 50 51 #include "ihevc_defs.h" 52 #include "ihevc_debug.h" 53 #include "ihevc_structs.h" 54 #include "ihevc_macros.h" 55 #include "ihevc_platform_macros.h" 56 #include "ihevc_cabac_tables.h" 57 #include "ihevc_disp_mgr.h" 58 59 #include "ihevcd_defs.h" 60 #include "ihevcd_function_selector.h" 61 #include "ihevcd_structs.h" 62 #include "ihevcd_error.h" 63 #include "ihevcd_nal.h" 64 #include "ihevcd_bitstream.h" 65 #include "ihevcd_fmt_conv.h" 66 #include "ihevcd_profile.h" 67 68 /** 69 ******************************************************************************* 70 * 71 * @brief Function used from copying a 420SP buffer 72 * 73 * @par Description 74 * Function used from copying a 420SP buffer 75 * 76 * @param[in] pu1_y_src 77 * Input Y pointer 78 * 79 * @param[in] pu1_uv_src 80 * Input UV pointer (UV is interleaved either in UV or VU format) 81 * 82 * @param[in] pu1_y_dst 83 * Output Y pointer 84 * 85 * @param[in] pu1_uv_dst 86 * Output UV pointer (UV is interleaved in the same format as that of input) 87 * 88 * @param[in] wd 89 * Width 90 * 91 * @param[in] ht 92 * Height 93 * 94 * @param[in] src_y_strd 95 * Input Y Stride 96 * 97 * @param[in] src_uv_strd 98 * Input UV stride 99 * 100 * @param[in] dst_y_strd 101 * Output Y stride 102 * 103 * @param[in] dst_uv_strd 104 * Output UV stride 105 * 106 * @returns None 107 * 108 * @remarks In case there is a need to perform partial frame copy then 109 * by passion appropriate source and destination pointers and appropriate 110 * values for wd and ht it can be done 111 * 112 ******************************************************************************* 113 */ 114 void ihevcd_fmt_conv_420sp_to_rgb565(UWORD8 *pu1_y_src, 115 UWORD8 *pu1_uv_src, 116 UWORD16 *pu2_rgb_dst, 117 WORD32 wd, 118 WORD32 ht, 119 WORD32 src_y_strd, 120 WORD32 src_uv_strd, 121 WORD32 dst_strd, 122 WORD32 is_u_first) 123 { 124 125 126 WORD16 i2_r, i2_g, i2_b; 127 UWORD32 u4_r, u4_g, u4_b; 128 WORD16 i2_i, i2_j; 129 UWORD8 *pu1_y_src_nxt; 130 UWORD16 *pu2_rgb_dst_NextRow; 131 132 UWORD8 *pu1_u_src, *pu1_v_src; 133 134 if(is_u_first) 135 { 136 pu1_u_src = (UWORD8 *)pu1_uv_src; 137 pu1_v_src = (UWORD8 *)pu1_uv_src + 1; 138 } 139 else 140 { 141 pu1_u_src = (UWORD8 *)pu1_uv_src + 1; 142 pu1_v_src = (UWORD8 *)pu1_uv_src; 143 } 144 145 pu1_y_src_nxt = pu1_y_src + src_y_strd; 146 pu2_rgb_dst_NextRow = pu2_rgb_dst + dst_strd; 147 148 for(i2_i = 0; i2_i < (ht >> 1); i2_i++) 149 { 150 for(i2_j = (wd >> 1); i2_j > 0; i2_j--) 151 { 152 i2_b = ((*pu1_u_src - 128) * COEFF4 >> 13); 153 i2_g = ((*pu1_u_src - 128) * COEFF2 + (*pu1_v_src - 128) * COEFF3) >> 13; 154 i2_r = ((*pu1_v_src - 128) * COEFF1) >> 13; 155 156 pu1_u_src += 2; 157 pu1_v_src += 2; 158 /* pixel 0 */ 159 /* B */ 160 u4_b = CLIP_U8(*pu1_y_src + i2_b); 161 u4_b >>= 3; 162 /* G */ 163 u4_g = CLIP_U8(*pu1_y_src + i2_g); 164 u4_g >>= 2; 165 /* R */ 166 u4_r = CLIP_U8(*pu1_y_src + i2_r); 167 u4_r >>= 3; 168 169 pu1_y_src++; 170 *pu2_rgb_dst++ = ((u4_r << 11) | (u4_g << 5) | u4_b); 171 172 /* pixel 1 */ 173 /* B */ 174 u4_b = CLIP_U8(*pu1_y_src + i2_b); 175 u4_b >>= 3; 176 /* G */ 177 u4_g = CLIP_U8(*pu1_y_src + i2_g); 178 u4_g >>= 2; 179 /* R */ 180 u4_r = CLIP_U8(*pu1_y_src + i2_r); 181 u4_r >>= 3; 182 183 pu1_y_src++; 184 *pu2_rgb_dst++ = ((u4_r << 11) | (u4_g << 5) | u4_b); 185 186 /* pixel 2 */ 187 /* B */ 188 u4_b = CLIP_U8(*pu1_y_src_nxt + i2_b); 189 u4_b >>= 3; 190 /* G */ 191 u4_g = CLIP_U8(*pu1_y_src_nxt + i2_g); 192 u4_g >>= 2; 193 /* R */ 194 u4_r = CLIP_U8(*pu1_y_src_nxt + i2_r); 195 u4_r >>= 3; 196 197 pu1_y_src_nxt++; 198 *pu2_rgb_dst_NextRow++ = ((u4_r << 11) | (u4_g << 5) | u4_b); 199 200 /* pixel 3 */ 201 /* B */ 202 u4_b = CLIP_U8(*pu1_y_src_nxt + i2_b); 203 u4_b >>= 3; 204 /* G */ 205 u4_g = CLIP_U8(*pu1_y_src_nxt + i2_g); 206 u4_g >>= 2; 207 /* R */ 208 u4_r = CLIP_U8(*pu1_y_src_nxt + i2_r); 209 u4_r >>= 3; 210 211 pu1_y_src_nxt++; 212 *pu2_rgb_dst_NextRow++ = ((u4_r << 11) | (u4_g << 5) | u4_b); 213 214 } 215 216 pu1_u_src = pu1_u_src + src_uv_strd - wd; 217 pu1_v_src = pu1_v_src + src_uv_strd - wd; 218 219 pu1_y_src = pu1_y_src + (src_y_strd << 1) - wd; 220 pu1_y_src_nxt = pu1_y_src_nxt + (src_y_strd << 1) - wd; 221 222 pu2_rgb_dst = pu2_rgb_dst_NextRow - wd + dst_strd; 223 pu2_rgb_dst_NextRow = pu2_rgb_dst_NextRow + (dst_strd << 1) - wd; 224 } 225 226 227 } 228 229 void ihevcd_fmt_conv_420sp_to_rgba8888(UWORD8 *pu1_y_src, 230 UWORD8 *pu1_uv_src, 231 UWORD32 *pu4_rgba_dst, 232 WORD32 wd, 233 WORD32 ht, 234 WORD32 src_y_strd, 235 WORD32 src_uv_strd, 236 WORD32 dst_strd, 237 WORD32 is_u_first) 238 { 239 240 241 WORD16 i2_r, i2_g, i2_b; 242 UWORD32 u4_r, u4_g, u4_b; 243 WORD16 i2_i, i2_j; 244 UWORD8 *pu1_y_src_nxt; 245 UWORD32 *pu4_rgba_dst_NextRow; 246 247 UWORD8 *pu1_u_src, *pu1_v_src; 248 249 if(is_u_first) 250 { 251 pu1_u_src = (UWORD8 *)pu1_uv_src; 252 pu1_v_src = (UWORD8 *)pu1_uv_src + 1; 253 } 254 else 255 { 256 pu1_u_src = (UWORD8 *)pu1_uv_src + 1; 257 pu1_v_src = (UWORD8 *)pu1_uv_src; 258 } 259 260 pu1_y_src_nxt = pu1_y_src + src_y_strd; 261 pu4_rgba_dst_NextRow = pu4_rgba_dst + dst_strd; 262 263 for(i2_i = 0; i2_i < (ht >> 1); i2_i++) 264 { 265 for(i2_j = (wd >> 1); i2_j > 0; i2_j--) 266 { 267 i2_b = ((*pu1_u_src - 128) * COEFF4 >> 13); 268 i2_g = ((*pu1_u_src - 128) * COEFF2 + (*pu1_v_src - 128) * COEFF3) >> 13; 269 i2_r = ((*pu1_v_src - 128) * COEFF1) >> 13; 270 271 pu1_u_src += 2; 272 pu1_v_src += 2; 273 /* pixel 0 */ 274 /* B */ 275 u4_b = CLIP_U8(*pu1_y_src + i2_b); 276 /* G */ 277 u4_g = CLIP_U8(*pu1_y_src + i2_g); 278 /* R */ 279 u4_r = CLIP_U8(*pu1_y_src + i2_r); 280 281 pu1_y_src++; 282 *pu4_rgba_dst++ = ((u4_r << 16) | (u4_g << 8) | (u4_b << 0)); 283 284 /* pixel 1 */ 285 /* B */ 286 u4_b = CLIP_U8(*pu1_y_src + i2_b); 287 /* G */ 288 u4_g = CLIP_U8(*pu1_y_src + i2_g); 289 /* R */ 290 u4_r = CLIP_U8(*pu1_y_src + i2_r); 291 292 pu1_y_src++; 293 *pu4_rgba_dst++ = ((u4_r << 16) | (u4_g << 8) | (u4_b << 0)); 294 295 /* pixel 2 */ 296 /* B */ 297 u4_b = CLIP_U8(*pu1_y_src_nxt + i2_b); 298 /* G */ 299 u4_g = CLIP_U8(*pu1_y_src_nxt + i2_g); 300 /* R */ 301 u4_r = CLIP_U8(*pu1_y_src_nxt + i2_r); 302 303 pu1_y_src_nxt++; 304 *pu4_rgba_dst_NextRow++ = ((u4_r << 16) | (u4_g << 8) | (u4_b << 0)); 305 306 /* pixel 3 */ 307 /* B */ 308 u4_b = CLIP_U8(*pu1_y_src_nxt + i2_b); 309 /* G */ 310 u4_g = CLIP_U8(*pu1_y_src_nxt + i2_g); 311 /* R */ 312 u4_r = CLIP_U8(*pu1_y_src_nxt + i2_r); 313 314 pu1_y_src_nxt++; 315 *pu4_rgba_dst_NextRow++ = ((u4_r << 16) | (u4_g << 8) | (u4_b << 0)); 316 317 } 318 319 pu1_u_src = pu1_u_src + src_uv_strd - wd; 320 pu1_v_src = pu1_v_src + src_uv_strd - wd; 321 322 pu1_y_src = pu1_y_src + (src_y_strd << 1) - wd; 323 pu1_y_src_nxt = pu1_y_src_nxt + (src_y_strd << 1) - wd; 324 325 pu4_rgba_dst = pu4_rgba_dst_NextRow - wd + dst_strd; 326 pu4_rgba_dst_NextRow = pu4_rgba_dst_NextRow + (dst_strd << 1) - wd; 327 } 328 329 330 } 331 332 /** 333 ******************************************************************************* 334 * 335 * @brief Function used from copying a 420SP buffer 336 * 337 * @par Description 338 * Function used from copying a 420SP buffer 339 * 340 * @param[in] pu1_y_src 341 * Input Y pointer 342 * 343 * @param[in] pu1_uv_src 344 * Input UV pointer (UV is interleaved either in UV or VU format) 345 * 346 * @param[in] pu1_y_dst 347 * Output Y pointer 348 * 349 * @param[in] pu1_uv_dst 350 * Output UV pointer (UV is interleaved in the same format as that of input) 351 * 352 * @param[in] wd 353 * Width 354 * 355 * @param[in] ht 356 * Height 357 * 358 * @param[in] src_y_strd 359 * Input Y Stride 360 * 361 * @param[in] src_uv_strd 362 * Input UV stride 363 * 364 * @param[in] dst_y_strd 365 * Output Y stride 366 * 367 * @param[in] dst_uv_strd 368 * Output UV stride 369 * 370 * @returns None 371 * 372 * @remarks In case there is a need to perform partial frame copy then 373 * by passion appropriate source and destination pointers and appropriate 374 * values for wd and ht it can be done 375 * 376 ******************************************************************************* 377 */ 378 379 void ihevcd_fmt_conv_420sp_to_420sp(UWORD8 *pu1_y_src, 380 UWORD8 *pu1_uv_src, 381 UWORD8 *pu1_y_dst, 382 UWORD8 *pu1_uv_dst, 383 WORD32 wd, 384 WORD32 ht, 385 WORD32 src_y_strd, 386 WORD32 src_uv_strd, 387 WORD32 dst_y_strd, 388 WORD32 dst_uv_strd) 389 { 390 UWORD8 *pu1_src, *pu1_dst; 391 WORD32 num_rows, num_cols, src_strd, dst_strd; 392 WORD32 i; 393 394 /* copy luma */ 395 pu1_src = (UWORD8 *)pu1_y_src; 396 pu1_dst = (UWORD8 *)pu1_y_dst; 397 398 num_rows = ht; 399 num_cols = wd; 400 401 src_strd = src_y_strd; 402 dst_strd = dst_y_strd; 403 404 for(i = 0; i < num_rows; i++) 405 { 406 memcpy(pu1_dst, pu1_src, num_cols); 407 pu1_dst += dst_strd; 408 pu1_src += src_strd; 409 } 410 411 /* copy U and V */ 412 pu1_src = (UWORD8 *)pu1_uv_src; 413 pu1_dst = (UWORD8 *)pu1_uv_dst; 414 415 num_rows = ht >> 1; 416 num_cols = wd; 417 418 src_strd = src_uv_strd; 419 dst_strd = dst_uv_strd; 420 421 for(i = 0; i < num_rows; i++) 422 { 423 memcpy(pu1_dst, pu1_src, num_cols); 424 pu1_dst += dst_strd; 425 pu1_src += src_strd; 426 } 427 return; 428 } 429 430 431 432 /** 433 ******************************************************************************* 434 * 435 * @brief Function used from copying a 420SP buffer 436 * 437 * @par Description 438 * Function used from copying a 420SP buffer 439 * 440 * @param[in] pu1_y_src 441 * Input Y pointer 442 * 443 * @param[in] pu1_uv_src 444 * Input UV pointer (UV is interleaved either in UV or VU format) 445 * 446 * @param[in] pu1_y_dst 447 * Output Y pointer 448 * 449 * @param[in] pu1_uv_dst 450 * Output UV pointer (UV is interleaved in the same format as that of input) 451 * 452 * @param[in] wd 453 * Width 454 * 455 * @param[in] ht 456 * Height 457 * 458 * @param[in] src_y_strd 459 * Input Y Stride 460 * 461 * @param[in] src_uv_strd 462 * Input UV stride 463 * 464 * @param[in] dst_y_strd 465 * Output Y stride 466 * 467 * @param[in] dst_uv_strd 468 * Output UV stride 469 * 470 * @returns None 471 * 472 * @remarks In case there is a need to perform partial frame copy then 473 * by passion appropriate source and destination pointers and appropriate 474 * values for wd and ht it can be done 475 * 476 ******************************************************************************* 477 */ 478 void ihevcd_fmt_conv_420sp_to_420sp_swap_uv(UWORD8 *pu1_y_src, 479 UWORD8 *pu1_uv_src, 480 UWORD8 *pu1_y_dst, 481 UWORD8 *pu1_uv_dst, 482 WORD32 wd, 483 WORD32 ht, 484 WORD32 src_y_strd, 485 WORD32 src_uv_strd, 486 WORD32 dst_y_strd, 487 WORD32 dst_uv_strd) 488 { 489 UWORD8 *pu1_src, *pu1_dst; 490 WORD32 num_rows, num_cols, src_strd, dst_strd; 491 WORD32 i; 492 493 /* copy luma */ 494 pu1_src = (UWORD8 *)pu1_y_src; 495 pu1_dst = (UWORD8 *)pu1_y_dst; 496 497 num_rows = ht; 498 num_cols = wd; 499 500 src_strd = src_y_strd; 501 dst_strd = dst_y_strd; 502 503 for(i = 0; i < num_rows; i++) 504 { 505 memcpy(pu1_dst, pu1_src, num_cols); 506 pu1_dst += dst_strd; 507 pu1_src += src_strd; 508 } 509 510 /* copy U and V */ 511 pu1_src = (UWORD8 *)pu1_uv_src; 512 pu1_dst = (UWORD8 *)pu1_uv_dst; 513 514 num_rows = ht >> 1; 515 num_cols = wd; 516 517 src_strd = src_uv_strd; 518 dst_strd = dst_uv_strd; 519 520 for(i = 0; i < num_rows; i++) 521 { 522 WORD32 j; 523 for(j = 0; j < num_cols; j += 2) 524 { 525 pu1_dst[j + 0] = pu1_src[j + 1]; 526 pu1_dst[j + 1] = pu1_src[j + 0]; 527 } 528 pu1_dst += dst_strd; 529 pu1_src += src_strd; 530 } 531 return; 532 } 533 /** 534 ******************************************************************************* 535 * 536 * @brief Function used from copying a 420SP buffer 537 * 538 * @par Description 539 * Function used from copying a 420SP buffer 540 * 541 * @param[in] pu1_y_src 542 * Input Y pointer 543 * 544 * @param[in] pu1_uv_src 545 * Input UV pointer (UV is interleaved either in UV or VU format) 546 * 547 * @param[in] pu1_y_dst 548 * Output Y pointer 549 * 550 * @param[in] pu1_u_dst 551 * Output U pointer 552 * 553 * @param[in] pu1_v_dst 554 * Output V pointer 555 * 556 * @param[in] wd 557 * Width 558 * 559 * @param[in] ht 560 * Height 561 * 562 * @param[in] src_y_strd 563 * Input Y Stride 564 * 565 * @param[in] src_uv_strd 566 * Input UV stride 567 * 568 * @param[in] dst_y_strd 569 * Output Y stride 570 * 571 * @param[in] dst_uv_strd 572 * Output UV stride 573 * 574 * @param[in] is_u_first 575 * Flag to indicate if U is the first byte in input chroma part 576 * 577 * @returns none 578 * 579 * @remarks In case there is a need to perform partial frame copy then 580 * by passion appropriate source and destination pointers and appropriate 581 * values for wd and ht it can be done 582 * 583 ******************************************************************************* 584 */ 585 586 587 void ihevcd_fmt_conv_420sp_to_420p(UWORD8 *pu1_y_src, 588 UWORD8 *pu1_uv_src, 589 UWORD8 *pu1_y_dst, 590 UWORD8 *pu1_u_dst, 591 UWORD8 *pu1_v_dst, 592 WORD32 wd, 593 WORD32 ht, 594 WORD32 src_y_strd, 595 WORD32 src_uv_strd, 596 WORD32 dst_y_strd, 597 WORD32 dst_uv_strd, 598 WORD32 is_u_first, 599 WORD32 disable_luma_copy) 600 { 601 UWORD8 *pu1_src, *pu1_dst; 602 UWORD8 *pu1_u_src, *pu1_v_src; 603 WORD32 num_rows, num_cols, src_strd, dst_strd; 604 WORD32 i, j; 605 606 if(0 == disable_luma_copy) 607 { 608 /* copy luma */ 609 pu1_src = (UWORD8 *)pu1_y_src; 610 pu1_dst = (UWORD8 *)pu1_y_dst; 611 612 num_rows = ht; 613 num_cols = wd; 614 615 src_strd = src_y_strd; 616 dst_strd = dst_y_strd; 617 618 for(i = 0; i < num_rows; i++) 619 { 620 memcpy(pu1_dst, pu1_src, num_cols); 621 pu1_dst += dst_strd; 622 pu1_src += src_strd; 623 } 624 } 625 /* de-interleave U and V and copy to destination */ 626 if(is_u_first) 627 { 628 pu1_u_src = (UWORD8 *)pu1_uv_src; 629 pu1_v_src = (UWORD8 *)pu1_uv_src + 1; 630 } 631 else 632 { 633 pu1_u_src = (UWORD8 *)pu1_uv_src + 1; 634 pu1_v_src = (UWORD8 *)pu1_uv_src; 635 } 636 637 638 num_rows = ht >> 1; 639 num_cols = wd >> 1; 640 641 src_strd = src_uv_strd; 642 dst_strd = dst_uv_strd; 643 644 for(i = 0; i < num_rows; i++) 645 { 646 for(j = 0; j < num_cols; j++) 647 { 648 pu1_u_dst[j] = pu1_u_src[j * 2]; 649 pu1_v_dst[j] = pu1_v_src[j * 2]; 650 } 651 652 pu1_u_dst += dst_strd; 653 pu1_v_dst += dst_strd; 654 pu1_u_src += src_strd; 655 pu1_v_src += src_strd; 656 } 657 return; 658 } 659 660 661 662 /** 663 ******************************************************************************* 664 * 665 * @brief Function used from format conversion or frame copy 666 * 667 * @par Description 668 * Function used from copying or converting a reference frame to display buffer 669 * in non shared mode 670 * 671 * @param[in] pu1_y_dst 672 * Output Y pointer 673 * 674 * @param[in] pu1_u_dst 675 * Output U/UV pointer ( UV is interleaved in the same format as that of input) 676 * 677 * @param[in] pu1_v_dst 678 * Output V pointer ( used in 420P output case) 679 * 680 * @param[in] blocking 681 * To indicate whether format conversion should wait till frame is reconstructed 682 * and then return after complete copy is done. To be set to 1 when called at the 683 * end of frame processing and set to 0 when called between frame processing modules 684 * in order to utilize available MCPS 685 * 686 * @returns Error from IHEVCD_ERROR_T 687 * 688 ******************************************************************************* 689 */ 690 IHEVCD_ERROR_T ihevcd_fmt_conv(codec_t *ps_codec, 691 process_ctxt_t *ps_proc, 692 UWORD8 *pu1_y_dst, 693 UWORD8 *pu1_u_dst, 694 UWORD8 *pu1_v_dst, 695 WORD32 cur_row, 696 WORD32 num_rows) 697 { 698 IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS; 699 pic_buf_t *ps_disp_pic; 700 UWORD8 *pu1_y_src, *pu1_uv_src; 701 UWORD8 *pu1_y_dst_tmp, *pu1_uv_dst_tmp; 702 UWORD8 *pu1_u_dst_tmp, *pu1_v_dst_tmp; 703 UWORD16 *pu2_rgb_dst_tmp; 704 UWORD32 *pu4_rgb_dst_tmp; 705 WORD32 is_u_first; 706 UWORD8 *pu1_luma; 707 UWORD8 *pu1_chroma; 708 sps_t *ps_sps; 709 WORD32 disable_luma_copy; 710 WORD32 crop_unit_x, crop_unit_y; 711 712 if(0 == num_rows) 713 return ret; 714 715 /* In case processing is disabled, then no need to format convert/copy */ 716 PROFILE_DISABLE_FMT_CONV(); 717 ps_sps = ps_proc->ps_sps; 718 719 crop_unit_x = 1; 720 crop_unit_y = 1; 721 722 if(CHROMA_FMT_IDC_YUV420 == ps_sps->i1_chroma_format_idc) 723 { 724 crop_unit_x = 2; 725 crop_unit_y = 2; 726 } 727 728 ps_disp_pic = ps_codec->ps_disp_buf; 729 pu1_luma = ps_disp_pic->pu1_luma; 730 pu1_chroma = ps_disp_pic->pu1_chroma; 731 732 733 /* Take care of cropping */ 734 pu1_luma += ps_codec->i4_strd * ps_sps->i2_pic_crop_top_offset * crop_unit_y + ps_sps->i2_pic_crop_left_offset * crop_unit_x; 735 736 /* Left offset is multiplied by 2 because buffer is UV interleaved */ 737 pu1_chroma += ps_codec->i4_strd * ps_sps->i2_pic_crop_top_offset + ps_sps->i2_pic_crop_left_offset * 2; 738 739 740 is_u_first = (IV_YUV_420SP_UV == ps_codec->e_ref_chroma_fmt) ? 1 : 0; 741 742 /* In case of 420P output luma copy is disabled for shared mode */ 743 disable_luma_copy = 0; 744 if(1 == ps_codec->i4_share_disp_buf) 745 { 746 disable_luma_copy = 1; 747 } 748 749 750 751 { 752 pu1_y_src = pu1_luma + cur_row * ps_codec->i4_strd; 753 pu1_uv_src = pu1_chroma + (cur_row / 2) * ps_codec->i4_strd; 754 755 /* In case of shared mode, with 420P output, get chroma destination */ 756 if((1 == ps_codec->i4_share_disp_buf) && (IV_YUV_420P == ps_codec->e_chroma_fmt)) 757 { 758 WORD32 i; 759 for(i = 0; i < ps_codec->i4_share_disp_buf_cnt; i++) 760 { 761 WORD32 diff = ps_disp_pic->pu1_luma - ps_codec->s_disp_buffer[i].pu1_bufs[0]; 762 if(diff == (ps_codec->i4_strd * PAD_TOP + PAD_LEFT)) 763 { 764 pu1_u_dst = ps_codec->s_disp_buffer[i].pu1_bufs[1]; 765 pu1_u_dst += (ps_codec->i4_strd * PAD_TOP) / 4 + (PAD_LEFT / 2); 766 767 pu1_v_dst = ps_codec->s_disp_buffer[i].pu1_bufs[2]; 768 pu1_v_dst += (ps_codec->i4_strd * PAD_TOP) / 4 + (PAD_LEFT / 2); 769 break; 770 } 771 } 772 } 773 pu2_rgb_dst_tmp = (UWORD16 *)pu1_y_dst; 774 pu2_rgb_dst_tmp += cur_row * ps_codec->i4_disp_strd; 775 pu4_rgb_dst_tmp = (UWORD32 *)pu1_y_dst; 776 pu4_rgb_dst_tmp += cur_row * ps_codec->i4_disp_strd; 777 pu1_y_dst_tmp = pu1_y_dst + cur_row * ps_codec->i4_disp_strd; 778 pu1_uv_dst_tmp = pu1_u_dst + (cur_row / 2) * ps_codec->i4_disp_strd; 779 pu1_u_dst_tmp = pu1_u_dst + (cur_row / 2) * ps_codec->i4_disp_strd / 2; 780 pu1_v_dst_tmp = pu1_v_dst + (cur_row / 2) * ps_codec->i4_disp_strd / 2; 781 782 /* In case of multi threaded implementation, format conversion might be called 783 * before reconstruction is completed. If the frame being converted/copied 784 * is same as the frame being reconstructed, 785 * Check how many rows can be format converted 786 * Convert those many rows and then check for remaining rows and so on 787 */ 788 789 if((0 == ps_codec->i4_flush_mode) && (ps_codec->i4_disp_buf_id == ps_proc->i4_cur_pic_buf_id) && (1 < ps_codec->i4_num_cores)) 790 { 791 WORD32 idx; 792 UWORD8 *pu1_buf; 793 WORD32 status; 794 WORD32 last_row = cur_row + num_rows; 795 WORD32 last_ctb_y; 796 UWORD32 ctb_in_row; 797 798 while(1) 799 { 800 last_row = cur_row + MAX(num_rows, (1 << ps_sps->i1_log2_ctb_size)) + 801 ps_sps->i2_pic_crop_top_offset * crop_unit_y; 802 last_ctb_y = (last_row >> ps_sps->i1_log2_ctb_size) - 1; 803 /* Since deblocking works with a shift of -4, -4 ,wait till next CTB row is processed */ 804 last_ctb_y++; 805 /* In case of a conformance window, an extra wait of one row might be needed */ 806 last_ctb_y++; 807 last_ctb_y = MIN(last_ctb_y, (ps_sps->i2_pic_ht_in_ctb - 1)); 808 809 idx = (last_ctb_y * ps_sps->i2_pic_wd_in_ctb); 810 811 /*Check if the row below is completely processed before proceeding with format conversion*/ 812 status = 1; 813 for(ctb_in_row = 0; (WORD32)ctb_in_row < ps_sps->i2_pic_wd_in_ctb; ctb_in_row++) 814 { 815 pu1_buf = (ps_codec->pu1_proc_map + idx + ctb_in_row); 816 status &= *pu1_buf; 817 } 818 819 if(status) 820 { 821 break; 822 } 823 else 824 { 825 ithread_yield(); 826 } 827 } 828 } 829 830 831 if((IV_YUV_420SP_UV == ps_codec->e_chroma_fmt) || (IV_YUV_420SP_VU == ps_codec->e_chroma_fmt)) 832 { 833 834 ps_codec->s_func_selector.ihevcd_fmt_conv_420sp_to_420sp_fptr(pu1_y_src, pu1_uv_src, 835 pu1_y_dst_tmp, pu1_uv_dst_tmp, 836 ps_codec->i4_disp_wd, 837 num_rows, 838 ps_codec->i4_strd, 839 ps_codec->i4_strd, 840 ps_codec->i4_disp_strd, 841 ps_codec->i4_disp_strd); 842 } 843 else if(IV_YUV_420P == ps_codec->e_chroma_fmt) 844 { 845 846 if(0 == disable_luma_copy) 847 { 848 // copy luma 849 WORD32 i; 850 WORD32 num_cols = ps_codec->i4_disp_wd; 851 852 for(i = 0; i < num_rows; i++) 853 { 854 memcpy(pu1_y_dst_tmp, pu1_y_src, num_cols); 855 pu1_y_dst_tmp += ps_codec->i4_disp_strd; 856 pu1_y_src += ps_codec->i4_strd; 857 } 858 859 disable_luma_copy = 1; 860 } 861 862 ps_codec->s_func_selector.ihevcd_fmt_conv_420sp_to_420p_fptr(pu1_y_src, pu1_uv_src, 863 pu1_y_dst_tmp, pu1_u_dst_tmp, pu1_v_dst_tmp, 864 ps_codec->i4_disp_wd, 865 num_rows, 866 ps_codec->i4_strd, 867 ps_codec->i4_strd, 868 ps_codec->i4_disp_strd, 869 (ps_codec->i4_disp_strd / 2), 870 is_u_first, 871 disable_luma_copy); 872 873 } 874 else if(IV_RGB_565 == ps_codec->e_chroma_fmt) 875 { 876 877 ps_codec->s_func_selector.ihevcd_fmt_conv_420sp_to_rgb565_fptr(pu1_y_src, pu1_uv_src, 878 pu2_rgb_dst_tmp, 879 ps_codec->i4_disp_wd, 880 num_rows, 881 ps_codec->i4_strd, 882 ps_codec->i4_strd, 883 ps_codec->i4_disp_strd, 884 is_u_first); 885 886 } 887 else if(IV_RGBA_8888 == ps_codec->e_chroma_fmt) 888 { 889 ASSERT(is_u_first == 1); 890 891 ps_codec->s_func_selector.ihevcd_fmt_conv_420sp_to_rgba8888_fptr(pu1_y_src, 892 pu1_uv_src, 893 pu4_rgb_dst_tmp, 894 ps_codec->i4_disp_wd, 895 num_rows, 896 ps_codec->i4_strd, 897 ps_codec->i4_strd, 898 ps_codec->i4_disp_strd, 899 is_u_first); 900 901 } 902 903 904 905 } 906 return (ret); 907 } 908 909