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 #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