1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 /* 19 ------------------------------------------------------------------------------ 20 INPUT AND OUTPUT DEFINITIONS 21 22 Inputs: 23 video = pointer to structure of type VideoDecData 24 25 Local Stores/Buffers/Pointers Needed: 26 roundtab16 = rounding table 27 28 Global Stores/Buffers/Pointers Needed: 29 None 30 31 Outputs: 32 None 33 34 Pointers and Buffers Modified: 35 video->currVop->yChan contents are the newly calculated luminance 36 data 37 video->currVop->uChan contents are the newly calculated chrominance 38 b data 39 video->currVop->vChan contents are the newly calculated chrominance 40 r data 41 video->pstprcTypCur contents are the updated semaphore propagation 42 values 43 44 Local Stores Modified: 45 None 46 47 Global Stores Modified: 48 None 49 50 ------------------------------------------------------------------------------ 51 FUNCTION DESCRIPTION 52 53 This function performs high level motion compensation on the luminance and 54 chrominance data. It sets up all the parameters required by the functions 55 that perform luminance and chrominance prediction and it initializes the 56 pointer to the post processing semaphores of a given block. It also checks 57 the motion compensation mode in order to determine which luminance or 58 chrominance prediction functions to call and determines how the post 59 processing semaphores are updated. 60 61 */ 62 63 64 /*---------------------------------------------------------------------------- 65 ; INCLUDES 66 ----------------------------------------------------------------------------*/ 67 #include "mp4dec_lib.h" 68 #include "motion_comp.h" 69 /*---------------------------------------------------------------------------- 70 ; MACROS 71 ; Define module specific macros here 72 ----------------------------------------------------------------------------*/ 73 74 75 /*---------------------------------------------------------------------------- 76 ; DEFINES 77 ; Include all pre-processor statements here. Include conditional 78 ; compile variables also. 79 ----------------------------------------------------------------------------*/ 80 81 82 /*---------------------------------------------------------------------------- 83 ; LOCAL FUNCTION DEFINITIONS 84 ; Function Prototype declaration 85 ----------------------------------------------------------------------------*/ 86 87 88 /*---------------------------------------------------------------------------- 89 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS 90 ; Variable declaration - defined here and used outside this module 91 ----------------------------------------------------------------------------*/ 92 /* 09/29/2000 bring this from mp4def.h */ 93 // const static int roundtab4[] = {0,1,1,1}; 94 // const static int roundtab8[] = {0,0,1,1,1,1,1,2}; 95 /*** 10/30 for TPS */ 96 // const static int roundtab12[] = {0,0,0,1,1,1,1,1,1,1,2,2}; 97 /* 10/30 for TPS ***/ 98 const static int roundtab16[] = {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2}; 99 100 101 /*---------------------------------------------------------------------------- 102 ; EXTERNAL FUNCTION REFERENCES 103 ; Declare functions defined elsewhere and referenced in this module 104 ----------------------------------------------------------------------------*/ 105 106 /*---------------------------------------------------------------------------- 107 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES 108 ; Declare variables used in this module but defined elsewhere 109 ----------------------------------------------------------------------------*/ 110 111 112 /*---------------------------------------------------------------------------- 113 ; FUNCTION CODE 114 ----------------------------------------------------------------------------*/ 115 116 /** modified 3 August 2005 to do prediction and put the results in 117 video->mblock->pred_block, no adding with residue */ 118 119 void MBMotionComp( 120 VideoDecData *video, 121 int CBP 122 ) 123 { 124 125 /*---------------------------------------------------------------------------- 126 ; Define all local variables 127 ----------------------------------------------------------------------------*/ 128 /* Previous Video Object Plane */ 129 Vop *prev = video->prevVop; 130 131 /* Current Macroblock (MB) in the VOP */ 132 int mbnum = video->mbnum; 133 134 /* Number of MB per data row */ 135 int MB_in_width = video->nMBPerRow; 136 int ypos, xpos; 137 PIXEL *c_comp, *c_prev; 138 PIXEL *cu_comp, *cu_prev; 139 PIXEL *cv_comp, *cv_prev; 140 int height, width, pred_width; 141 int imv, mvwidth; 142 int32 offset; 143 uint8 mode; 144 uint8 *pred_block, *pred; 145 146 /* Motion vector (dx,dy) in half-pel resolution */ 147 int dx, dy; 148 149 MOT px[4], py[4]; 150 int xpred, ypred; 151 int xsum; 152 int round1; 153 #ifdef PV_POSTPROC_ON // 2/14/2001 154 /* Total number of pixels in the VOL */ 155 int32 size = (int32) video->nTotalMB << 8; 156 uint8 *pp_dec_y, *pp_dec_u; 157 int ll[4]; 158 int tmp = 0; 159 uint8 msk_deblock = 0; 160 #endif 161 /*---------------------------------------------------------------------------- 162 ; Function body here 163 ----------------------------------------------------------------------------*/ 164 /* Set rounding type */ 165 /* change from array to single 09/29/2000 */ 166 round1 = (int)(1 - video->currVop->roundingType); 167 168 /* width of luminance data in pixels (y axis) */ 169 width = video->width; 170 171 /* heigth of luminance data in pixels (x axis) */ 172 height = video->height; 173 174 /* number of blocks per row */ 175 mvwidth = MB_in_width << 1; 176 177 /* starting y position in current MB; origin of MB */ 178 ypos = video->mbnum_row << 4 ; 179 /* starting x position in current MB; origin of MB */ 180 xpos = video->mbnum_col << 4 ; 181 182 /* offset to (x,y) position in current luminance MB */ 183 /* in pixel resolution */ 184 /* ypos*width -> row, +x -> column */ 185 offset = (int32)ypos * width + xpos; 186 187 /* get mode for current MB */ 188 mode = video->headerInfo.Mode[mbnum]; 189 190 /* block index */ 191 /* imv = (xpos/8) + ((ypos/8) * mvwidth) */ 192 imv = (offset >> 6) - (xpos >> 6) + (xpos >> 3); 193 if (mode & INTER_1VMASK) 194 { 195 dx = px[0] = px[1] = px[2] = px[3] = video->motX[imv]; 196 dy = py[0] = py[1] = py[2] = py[3] = video->motY[imv]; 197 if ((dx & 3) == 0) 198 { 199 dx = dx >> 1; 200 } 201 else 202 { 203 /* x component of MV is or'ed for rounding (?) */ 204 dx = (dx >> 1) | 1; 205 } 206 207 /* y component of motion vector; divide by 2 for to */ 208 /* convert to full-pel resolution. */ 209 if ((dy & 3) == 0) 210 { 211 dy = dy >> 1; 212 } 213 else 214 { 215 /* y component of MV is or'ed for rounding (?) */ 216 dy = (dy >> 1) | 1; 217 } 218 } 219 else 220 { 221 px[0] = video->motX[imv]; 222 px[1] = video->motX[imv+1]; 223 px[2] = video->motX[imv+mvwidth]; 224 px[3] = video->motX[imv+mvwidth+1]; 225 xsum = px[0] + px[1] + px[2] + px[3]; 226 dx = PV_SIGN(xsum) * (roundtab16[(PV_ABS(xsum)) & 0xF] + 227 (((PV_ABS(xsum)) >> 4) << 1)); 228 py[0] = video->motY[imv]; 229 py[1] = video->motY[imv+1]; 230 py[2] = video->motY[imv+mvwidth]; 231 py[3] = video->motY[imv+mvwidth+1]; 232 xsum = py[0] + py[1] + py[2] + py[3]; 233 dy = PV_SIGN(xsum) * (roundtab16[(PV_ABS(xsum)) & 0xF] + 234 (((PV_ABS(xsum)) >> 4) << 1)); 235 } 236 237 /* Pointer to previous luminance frame */ 238 c_prev = prev->yChan; 239 240 pred_block = video->mblock->pred_block; 241 242 /* some blocks have no residue or INTER4V */ 243 /*if (mode == MODE_INTER4V) 05/08/15 */ 244 /* Motion Compensation for an 8x8 block within a MB */ 245 /* (4 MV per MB) */ 246 247 248 249 /* Call function that performs luminance prediction */ 250 /* luminance_pred_mode_inter4v(xpos, ypos, px, py, c_prev, 251 video->mblock->pred_block, width, height, 252 round1, mvwidth, &xsum, &ysum);*/ 253 c_comp = video->currVop->yChan + offset; 254 255 256 xpred = (int)((xpos << 1) + px[0]); 257 ypred = (int)((ypos << 1) + py[0]); 258 259 if ((CBP >> 5)&1) 260 { 261 pred = pred_block; 262 pred_width = 16; 263 } 264 else 265 { 266 pred = c_comp; 267 pred_width = width; 268 } 269 270 /* check whether the MV points outside the frame */ 271 if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) && 272 ypred >= 0 && ypred <= ((height << 1) - (2*B_SIZE))) 273 { /*****************************/ 274 /* (x,y) is inside the frame */ 275 /*****************************/ 276 ; 277 GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*width), 278 pred, width, (pred_width << 1) | round1); 279 } 280 else 281 { /******************************/ 282 /* (x,y) is outside the frame */ 283 /******************************/ 284 GetPredOutside(xpred, ypred, c_prev, 285 pred, width, height, round1, pred_width); 286 } 287 288 289 /* Compute prediction values over current luminance MB */ 290 /* (blocks 1); add motion vector prior to input; */ 291 /* add 8 to x_pos to advance to next block */ 292 xpred = (int)(((xpos + B_SIZE) << 1) + px[1]); 293 ypred = (int)((ypos << 1) + py[1]); 294 295 if ((CBP >> 4)&1) 296 { 297 pred = pred_block + 8; 298 pred_width = 16; 299 } 300 else 301 { 302 pred = c_comp + 8; 303 pred_width = width; 304 } 305 306 /* check whether the MV points outside the frame */ 307 if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) && 308 ypred >= 0 && ypred <= ((height << 1) - (2*B_SIZE))) 309 { /*****************************/ 310 /* (x,y) is inside the frame */ 311 /*****************************/ 312 GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*width), 313 pred, width, (pred_width << 1) | round1); 314 } 315 else 316 { /******************************/ 317 /* (x,y) is outside the frame */ 318 /******************************/ 319 GetPredOutside(xpred, ypred, c_prev, 320 pred, width, height, round1, pred_width); 321 } 322 323 324 325 /* Compute prediction values over current luminance MB */ 326 /* (blocks 2); add motion vector prior to input */ 327 /* add 8 to y_pos to advance to block on next row */ 328 xpred = (int)((xpos << 1) + px[2]); 329 ypred = (int)(((ypos + B_SIZE) << 1) + py[2]); 330 331 if ((CBP >> 3)&1) 332 { 333 pred = pred_block + 128; 334 pred_width = 16; 335 } 336 else 337 { 338 pred = c_comp + (width << 3); 339 pred_width = width; 340 } 341 342 /* check whether the MV points outside the frame */ 343 if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) && 344 ypred >= 0 && ypred <= ((height << 1) - (2*B_SIZE))) 345 { /*****************************/ 346 /* (x,y) is inside the frame */ 347 /*****************************/ 348 GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*width), 349 pred, width, (pred_width << 1) | round1); 350 } 351 else 352 { /******************************/ 353 /* (x,y) is outside the frame */ 354 /******************************/ 355 GetPredOutside(xpred, ypred, c_prev, 356 pred, width, height, round1, pred_width); 357 } 358 359 360 361 /* Compute prediction values over current luminance MB */ 362 /* (blocks 3); add motion vector prior to input; */ 363 /* add 8 to x_pos and y_pos to advance to next block */ 364 /* on next row */ 365 xpred = (int)(((xpos + B_SIZE) << 1) + px[3]); 366 ypred = (int)(((ypos + B_SIZE) << 1) + py[3]); 367 368 if ((CBP >> 2)&1) 369 { 370 pred = pred_block + 136; 371 pred_width = 16; 372 } 373 else 374 { 375 pred = c_comp + (width << 3) + 8; 376 pred_width = width; 377 } 378 379 /* check whether the MV points outside the frame */ 380 if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) && 381 ypred >= 0 && ypred <= ((height << 1) - (2*B_SIZE))) 382 { /*****************************/ 383 /* (x,y) is inside the frame */ 384 /*****************************/ 385 GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*width), 386 pred, width, (pred_width << 1) | round1); 387 } 388 else 389 { /******************************/ 390 /* (x,y) is outside the frame */ 391 /******************************/ 392 GetPredOutside(xpred, ypred, c_prev, 393 pred, width, height, round1, pred_width); 394 } 395 /* Call function to set de-blocking and de-ringing */ 396 /* semaphores for luminance */ 397 398 #ifdef PV_POSTPROC_ON 399 if (video->postFilterType != PV_NO_POST_PROC) 400 { 401 if (mode&INTER_1VMASK) 402 { 403 pp_dec_y = video->pstprcTypCur + imv; 404 ll[0] = 1; 405 ll[1] = mvwidth - 1; 406 ll[2] = 1; 407 ll[3] = -mvwidth - 1; 408 msk_deblock = pp_semaphore_luma(xpred, ypred, pp_dec_y, 409 video->pstprcTypPrv, ll, &tmp, px[0], py[0], mvwidth, 410 width, height); 411 412 pp_dec_u = video->pstprcTypCur + (size >> 6) + 413 ((imv + (xpos >> 3)) >> 2); 414 415 pp_semaphore_chroma_inter(xpred, ypred, pp_dec_u, 416 video->pstprcTypPrv, dx, dy, mvwidth, height, size, 417 tmp, msk_deblock); 418 } 419 else 420 { 421 /* Post-processing mode (MBM_INTER8) */ 422 /* deblocking and deringing) */ 423 pp_dec_y = video->pstprcTypCur + imv; 424 *pp_dec_y = 4; 425 *(pp_dec_y + 1) = 4; 426 *(pp_dec_y + mvwidth) = 4; 427 *(pp_dec_y + mvwidth + 1) = 4; 428 pp_dec_u = video->pstprcTypCur + (size >> 6) + 429 ((imv + (xpos >> 3)) >> 2); 430 *pp_dec_u = 4; 431 pp_dec_u[size>>8] = 4; 432 } 433 } 434 #endif 435 436 437 /* xpred and ypred calculation for Chrominance is */ 438 /* in full-pel resolution. */ 439 440 /* Chrominance */ 441 /* width of chrominance data in pixels (y axis) */ 442 width >>= 1; 443 444 /* heigth of chrominance data in pixels (x axis) */ 445 height >>= 1; 446 447 /* Pointer to previous chrominance b frame */ 448 cu_prev = prev->uChan; 449 450 /* Pointer to previous chrominance r frame */ 451 cv_prev = prev->vChan; 452 453 /* x position in prediction data offset by motion vector */ 454 /* xpred calculation for Chrominance is in full-pel */ 455 /* resolution. */ 456 xpred = xpos + dx; 457 458 /* y position in prediction data offset by motion vector */ 459 /* ypred calculation for Chrominance is in full-pel */ 460 /* resolution. */ 461 ypred = ypos + dy; 462 463 cu_comp = video->currVop->uChan + (offset >> 2) + (xpos >> 2); 464 cv_comp = video->currVop->vChan + (offset >> 2) + (xpos >> 2); 465 466 /* Call function that performs chrominance prediction */ 467 /* chrominance_pred(xpred, ypred, cu_prev, cv_prev, 468 pred_block, width_uv, height_uv, 469 round1);*/ 470 if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) && ypred >= 0 && 471 ypred <= ((height << 1) - (2*B_SIZE))) 472 { 473 /*****************************/ 474 /* (x,y) is inside the frame */ 475 /*****************************/ 476 if ((CBP >> 1)&1) 477 { 478 pred = pred_block + 256; 479 pred_width = 16; 480 } 481 else 482 { 483 pred = cu_comp; 484 pred_width = width; 485 } 486 487 /* Compute prediction for Chrominance b (block[4]) */ 488 GetPredAdvBTable[ypred&1][xpred&1](cu_prev + (xpred >> 1) + ((ypred >> 1)*width), 489 pred, width, (pred_width << 1) | round1); 490 491 if (CBP&1) 492 { 493 pred = pred_block + 264; 494 pred_width = 16; 495 } 496 else 497 { 498 pred = cv_comp; 499 pred_width = width; 500 } 501 /* Compute prediction for Chrominance r (block[5]) */ 502 GetPredAdvBTable[ypred&1][xpred&1](cv_prev + (xpred >> 1) + ((ypred >> 1)*width), 503 pred, width, (pred_width << 1) | round1); 504 505 return ; 506 } 507 else 508 { 509 /******************************/ 510 /* (x,y) is outside the frame */ 511 /******************************/ 512 if ((CBP >> 1)&1) 513 { 514 pred = pred_block + 256; 515 pred_width = 16; 516 } 517 else 518 { 519 pred = cu_comp; 520 pred_width = width; 521 } 522 523 /* Compute prediction for Chrominance b (block[4]) */ 524 GetPredOutside(xpred, ypred, cu_prev, 525 pred, width, height, round1, pred_width); 526 527 if (CBP&1) 528 { 529 pred = pred_block + 264; 530 pred_width = 16; 531 } 532 else 533 { 534 pred = cv_comp; 535 pred_width = width; 536 } 537 538 /* Compute prediction for Chrominance r (block[5]) */ 539 GetPredOutside(xpred, ypred, cv_prev, 540 pred, width, height, round1, pred_width); 541 542 return ; 543 } 544 545 } 546 547 /*** special function for skipped macroblock, Aug 15, 2005 */ 548 void SkippedMBMotionComp( 549 VideoDecData *video 550 ) 551 { 552 Vop *prev = video->prevVop; 553 Vop *comp; 554 int ypos, xpos; 555 PIXEL *c_comp, *c_prev; 556 PIXEL *cu_comp, *cu_prev; 557 PIXEL *cv_comp, *cv_prev; 558 int width, width_uv; 559 int32 offset; 560 #ifdef PV_POSTPROC_ON // 2/14/2001 561 int imv; 562 int32 size = (int32) video->nTotalMB << 8; 563 uint8 *pp_dec_y, *pp_dec_u; 564 uint8 *pp_prev1; 565 int mvwidth = video->nMBPerRow << 1; 566 #endif 567 568 width = video->width; 569 width_uv = width >> 1; 570 ypos = video->mbnum_row << 4 ; 571 xpos = video->mbnum_col << 4 ; 572 offset = (int32)ypos * width + xpos; 573 574 575 /* zero motion compensation for previous frame */ 576 /*mby*width + mbx;*/ 577 c_prev = prev->yChan + offset; 578 /*by*width_uv + bx;*/ 579 cu_prev = prev->uChan + (offset >> 2) + (xpos >> 2); 580 /*by*width_uv + bx;*/ 581 cv_prev = prev->vChan + (offset >> 2) + (xpos >> 2); 582 583 comp = video->currVop; 584 585 c_comp = comp->yChan + offset; 586 cu_comp = comp->uChan + (offset >> 2) + (xpos >> 2); 587 cv_comp = comp->vChan + (offset >> 2) + (xpos >> 2); 588 589 590 /* Copy previous reconstructed frame into the current frame */ 591 PutSKIPPED_MB(c_comp, c_prev, width); 592 PutSKIPPED_B(cu_comp, cu_prev, width_uv); 593 PutSKIPPED_B(cv_comp, cv_prev, width_uv); 594 595 /* 10/24/2000 post_processing semaphore generation */ 596 #ifdef PV_POSTPROC_ON // 2/14/2001 597 if (video->postFilterType != PV_NO_POST_PROC) 598 { 599 imv = (offset >> 6) - (xpos >> 6) + (xpos >> 3); 600 /* Post-processing mode (copy previous MB) */ 601 pp_prev1 = video->pstprcTypPrv + imv; 602 pp_dec_y = video->pstprcTypCur + imv; 603 *pp_dec_y = *pp_prev1; 604 *(pp_dec_y + 1) = *(pp_prev1 + 1); 605 *(pp_dec_y + mvwidth) = *(pp_prev1 + mvwidth); 606 *(pp_dec_y + mvwidth + 1) = *(pp_prev1 + mvwidth + 1); 607 608 /* chrominance */ 609 /*4*MB_in_width*MB_in_height*/ 610 pp_prev1 = video->pstprcTypPrv + (size >> 6) + 611 ((imv + (xpos >> 3)) >> 2); 612 pp_dec_u = video->pstprcTypCur + (size >> 6) + 613 ((imv + (xpos >> 3)) >> 2); 614 *pp_dec_u = *pp_prev1; 615 pp_dec_u[size>>8] = pp_prev1[size>>8]; 616 } 617 #endif 618 /*---------------------------------------------------------------------------- 619 ; Return nothing or data or data pointer 620 ----------------------------------------------------------------------------*/ 621 622 return; 623 } 624