Home | History | Annotate | Download | only in src
      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