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