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     xpos = x half-pixel of (x,y) coordinates within a VOP; motion
     24            compensated coordinates; native data type
     25     ypos = y half-pixel of (x,y) coordinates within a VOP; motion
     26            compensated coordinates; native data type
     27     comp = pointer to 8-bit compensated prediction values within a VOP;
     28            computed by this module (i/o); full-pel resolution; 8-bit data
     29     c_prev = pointer to previous 8-bit prediction values within a VOP;
     30          values range from (0-255); full-pel resolution; 8-bit data
     31     sh_d = pointer to residual values used to compensate the predicted
     32            value; values range from (-512 to 511); full-pel resolution;
     33            native data type
     34     width = width of the VOP in pixels (x axis); full-pel resolution;
     35         native data type
     36     height = height of the VOP in pixels (y axis); full-pel resolution;
     37          native data type
     38     rnd1 = rounding value for case when one dimension uses half-pel
     39            resolution; native data type
     40     rnd2 = rounding value for case when two dimensions uses half-pel
     41            resolution; native data type
     42 
     43  Outputs:
     44     returns 1
     45 
     46  Local Stores/Buffers/Pointers Needed:
     47     None
     48 
     49  Global Stores/Buffers/Pointers Needed:
     50     None
     51 
     52  Pointers and Buffers Modified:
     53     comp = buffer contains newly computed compensated prediction values
     54 
     55  Local Stores Modified:
     56     None
     57 
     58  Global Stores Modified:
     59     None
     60 
     61 ------------------------------------------------------------------------------
     62  FUNCTION DESCRIPTION
     63 
     64  Summary:
     65 
     66  This function performs motion compensated prediction for the case where
     67  the motion vector points to a block outside the VOP. The function interpolates
     68  the pixels that are outside the VOP using the boundary pixels for the block.
     69  Once the values are interpolated, the pixel values are computed for a block
     70  in the current VOP. The prediction values are generated by averaging pixel
     71  values in the previous VOP; the block position in the previous frame is
     72  computed from the current block's motion vector. The computed pixel values
     73  are calculated by adding the prediction values to the block residual values.
     74 
     75  Details:
     76 
     77  First, this functions determines which VOP boundary(ies) the motion vector
     78  is outside, i.e., left, right, top, bottom. xpos is compared to the left and
     79  right boundaries; ypos is compared to the top and bottom boundaries. The number
     80  of block pixels inside the the boundary in the x and y directions are stored
     81  in endx and endy, respectively. If the entire block is inside the x or y
     82  boundary, the respectively end is set to 0.
     83 
     84  After the boundaries are tested, any pixels lying outside a boundary are
     85  interpolated from the boundary pixels. For example, if the block is outside the
     86  bottom boundary, boundary pixels alone the bottom of the VOP as used to
     87  interpolated those pixels lying outside the bottom boundary. The interpolation
     88  used is a simple column-wise or row-wise copy of the boundary pixels (inside the
     89  block) depending on which boundary the block is outside. In our example, each
     90  boundary pixel would be copied column-wise to the pixel beneath it. If the
     91  block was outside right boundary, the boundary pixels would be copied row-wise
     92  to the pixel to the right of it. If the block was outside both an x and y
     93  boundary, the boundary pixels would be copied row-wise for the portion of the
     94  block outside the x boundary, and column-wise for the portion of the block
     95  outside the y boundary. And so on.
     96 
     97  Once the pixel interpolation is complete, the motion compensated output values
     98  (comp[]) are calculed from the motion compensated prediction (pred[])values and
     99  the residual values (sh_d[]) of the current frame. The prediction values are
    100  generated by averaging pixel values in the previous VOP; the block position in
    101  the previous frame is computed from the current block's motion vector. The
    102  computed pixel values are calculated by adding the prediction values to the
    103  block residual values.
    104 
    105 */
    106 
    107 /*----------------------------------------------------------------------------
    108 ; INCLUDES
    109 ----------------------------------------------------------------------------*/
    110 #include "mp4dec_lib.h"
    111 #include "motion_comp.h"
    112 
    113 #define PAD_CORNER {    temp = *prev; \
    114             temp |= (temp<<8);  \
    115             temp |= (temp<<16); \
    116             *((uint32*)ptr) = temp; \
    117             *((uint32*)(ptr+4)) = temp;  \
    118             *((uint32*)(ptr+=16)) = temp;  \
    119             *((uint32*)(ptr+4)) = temp;  \
    120             *((uint32*)(ptr+=16)) = temp;  \
    121             *((uint32*)(ptr+4)) = temp;  \
    122             *((uint32*)(ptr+=16)) = temp;  \
    123             *((uint32*)(ptr+4)) = temp;  \
    124             *((uint32*)(ptr+=16)) = temp;  \
    125             *((uint32*)(ptr+4)) = temp;  \
    126             *((uint32*)(ptr+=16)) = temp;  \
    127             *((uint32*)(ptr+4)) = temp;  \
    128             *((uint32*)(ptr+=16)) = temp;  \
    129             *((uint32*)(ptr+4)) = temp;  \
    130             *((uint32*)(ptr+=16)) = temp;  \
    131             *((uint32*)(ptr+4)) = temp;  }
    132 
    133 #define PAD_ROW  {  temp = *((uint32*)prev); \
    134                     temp2 = *((uint32*)(prev+4)); \
    135             *((uint32*)ptr) =  temp;\
    136             *((uint32*)(ptr+4)) =  temp2; \
    137             *((uint32*)(ptr+=16)) = temp; \
    138             *((uint32*)(ptr+4)) = temp2;\
    139             *((uint32*)(ptr+=16)) = temp; \
    140             *((uint32*)(ptr+4)) = temp2;\
    141             *((uint32*)(ptr+=16)) = temp; \
    142             *((uint32*)(ptr+4)) = temp2;\
    143             *((uint32*)(ptr+=16)) = temp; \
    144             *((uint32*)(ptr+4)) = temp2;\
    145             *((uint32*)(ptr+=16)) = temp; \
    146             *((uint32*)(ptr+4)) = temp2;\
    147             *((uint32*)(ptr+=16)) = temp; \
    148             *((uint32*)(ptr+4)) = temp2;\
    149             *((uint32*)(ptr+=16)) = temp; \
    150             *((uint32*)(ptr+4)) = temp2;}
    151 
    152 #define PAD_EXTRA_4x8           {   temp = *((uint32*)(prev+8)); \
    153                 *((uint32*)ptr) =  temp; \
    154                 *((uint32*)(ptr+=16)) = temp; \
    155                 *((uint32*)(ptr+=16)) = temp; \
    156                 *((uint32*)(ptr+=16)) = temp; \
    157                 *((uint32*)(ptr+=16)) = temp; \
    158                 *((uint32*)(ptr+=16)) = temp; \
    159                 *((uint32*)(ptr+=16)) = temp; \
    160                 *((uint32*)(ptr+=16)) = temp; }
    161 
    162 #define PAD_COL { temp = *prev; \
    163             temp|=(temp<<8);  temp|=(temp<<16); \
    164             *((uint32*)ptr) = temp; \
    165             *((uint32*)(ptr+4)) = temp; \
    166             temp = *(prev+=16); \
    167             temp|=(temp<<8);  temp|=(temp<<16); \
    168             *((uint32*)(ptr+=16)) = temp; \
    169             *((uint32*)(ptr+4)) = temp; \
    170             temp = *(prev+=16); \
    171             temp|=(temp<<8);  temp|=(temp<<16); \
    172             *((uint32*)(ptr+=16)) = temp; \
    173             *((uint32*)(ptr+4)) = temp; \
    174             temp = *(prev+=16); \
    175             temp|=(temp<<8);  temp|=(temp<<16); \
    176             *((uint32*)(ptr+=16)) = temp; \
    177             *((uint32*)(ptr+4)) = temp; \
    178             temp = *(prev+=16); \
    179             temp|=(temp<<8);  temp|=(temp<<16); \
    180             *((uint32*)(ptr+=16)) = temp; \
    181             *((uint32*)(ptr+4)) = temp; \
    182             temp = *(prev+=16); \
    183             temp|=(temp<<8);  temp|=(temp<<16); \
    184             *((uint32*)(ptr+=16)) = temp; \
    185             *((uint32*)(ptr+4)) = temp; \
    186             temp = *(prev+=16); \
    187             temp|=(temp<<8);  temp|=(temp<<16); \
    188             *((uint32*)(ptr+=16)) = temp; \
    189             *((uint32*)(ptr+4)) = temp; \
    190             temp = *(prev+=16); \
    191             temp|=(temp<<8);  temp|=(temp<<16); \
    192             *((uint32*)(ptr+=16)) = temp; \
    193             *((uint32*)(ptr+4)) = temp;}
    194 
    195 /* copy 8x8 block */
    196 #define COPY_BLOCK  {           *((uint32*)ptr) = *((uint32*)prev); \
    197             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
    198             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
    199             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
    200             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
    201             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
    202             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
    203             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
    204             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
    205             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
    206             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
    207             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
    208             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
    209             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
    210             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
    211             *((uint32*)(ptr+4)) = *((uint32*)(prev+4));  }
    212 
    213 #define COPY_12x8       {       *((uint32*)ptr) = *((uint32*)prev); \
    214             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
    215             *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
    216             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
    217             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
    218             *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
    219             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
    220             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
    221             *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
    222             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
    223             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
    224             *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
    225             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
    226             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
    227             *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
    228             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
    229             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
    230             *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
    231             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
    232             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
    233             *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
    234             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
    235             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
    236             *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); }
    237 
    238 /*----------------------------------------------------------------------------
    239 ; FUNCTION CODE
    240 ----------------------------------------------------------------------------*/
    241 int GetPredOutside(
    242     int xpos,       /* i */
    243     int ypos,       /* i */
    244     uint8 *c_prev,      /* i */
    245     uint8 *pred_block,      /* i */
    246     int width,      /* i */
    247     int height,     /* i */
    248     int rnd1,       /* i */
    249     int pred_width
    250 )
    251 {
    252     /*----------------------------------------------------------------------------
    253     ; Define all local variables
    254     ----------------------------------------------------------------------------*/
    255     uint8   *prev;      /* pointers to adjacent pixels in the    */
    256     uint8   pred[256];  /* storage for padded pixel values, 16x16 */
    257     uint8   *ptr;
    258     int xoffset;
    259     uint32 temp, temp2;
    260 
    261     /*----------------------------------------------------------------------------
    262     ; Function body here
    263     ----------------------------------------------------------------------------*/
    264     /* saturate xpos and ypos */
    265     if (xpos < -16) xpos = -16;
    266     if (xpos > ((width - 1) << 1)) xpos = (width - 1) << 1;
    267     if (ypos < -16) ypos = -16;
    268     if (ypos > ((height - 1) << 1)) ypos = (height - 1) << 1;
    269 
    270     if (xpos < 0)
    271     {
    272         if (ypos < 0) /* pad top left of frame */
    273         {
    274             /* copy the block */
    275             ptr = pred + (8 << 4) + 8;
    276             prev = c_prev;
    277             COPY_BLOCK
    278 
    279             /* pad the corner */
    280             ptr = pred;
    281             prev = pred + (8 << 4) + 8;
    282             PAD_CORNER
    283 
    284             /* pad top */
    285             ptr = pred + 8;
    286             prev = pred + (8 << 4) + 8;
    287             PAD_ROW
    288 
    289             /* pad left */
    290             ptr = pred + (8 << 4);
    291             prev = pred + (8 << 4) + 8;
    292             PAD_COL
    293 
    294 
    295             ptr = pred + (((ypos >> 1) + 8) << 4) + (xpos >> 1) + 8;
    296 
    297             GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
    298 
    299             return 1;
    300         }
    301         else if ((ypos >> 1) < (height - B_SIZE)) /* pad left of frame */
    302         {
    303             /* copy block */
    304             ptr = pred + 8;
    305             prev = c_prev + (ypos >> 1) * width;
    306             COPY_BLOCK
    307             /* copy extra line */
    308             *((uint32*)(ptr += 16)) = *((uint32*)(prev += width));
    309             *((uint32*)(ptr + 4)) = *((uint32*)(prev + 4));
    310 
    311             /* pad left */
    312             ptr = pred;
    313             prev = pred + 8;
    314             PAD_COL
    315             /* pad extra line */
    316             temp = *(prev += 16);
    317             temp |= (temp << 8);
    318             temp |= (temp << 16);
    319             *((uint32*)(ptr += 16)) = temp;
    320             *((uint32*)(ptr + 4)) = temp;
    321 
    322             ptr = pred + 8 + (xpos >> 1);
    323 
    324             GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
    325 
    326             return 1;
    327         }
    328         else /* pad bottom left of frame */
    329         {
    330             /* copy the block */
    331             ptr = pred + 8; /* point to the center */
    332             prev = c_prev + width * (height - 8);
    333             COPY_BLOCK
    334 
    335             /* pad the corner */
    336             ptr = pred + (8 << 4);
    337             prev = ptr - 8;
    338             PAD_CORNER
    339 
    340             /* pad bottom */
    341             ptr = pred + (8 << 4) + 8;
    342             prev = ptr - 16;
    343             PAD_ROW
    344 
    345             /* pad left */
    346             ptr = pred ;
    347             prev = ptr + 8;
    348             PAD_COL
    349 
    350             ptr = pred + 8 + (((ypos >> 1) - (height - 8)) << 4) + (xpos >> 1);
    351 
    352             GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
    353 
    354             return 1;
    355         }
    356     }
    357     else if ((xpos >> 1) < (width - B_SIZE))
    358     {
    359         if (ypos < 0) /* pad top of frame */
    360         {
    361             xoffset = xpos >> 1;
    362             xoffset = xoffset & 0x3; /* word align ptr */
    363 
    364             /* copy block */
    365             ptr = pred + (8 << 4);
    366             prev = c_prev + (xpos >> 1) - xoffset;
    367 
    368             if (xoffset || (xpos&1)) /* copy extra 4x8 */
    369             {
    370                 COPY_12x8
    371             }
    372             else
    373             {
    374                 COPY_BLOCK
    375             }
    376 
    377             /* pad top */
    378             ptr = pred;
    379             prev = pred + (8 << 4);
    380             PAD_ROW
    381             if (xoffset || (xpos&1)) /* pad extra 4x8 */
    382             {
    383                 ptr = pred + 8;
    384                 PAD_EXTRA_4x8
    385             }
    386 
    387             ptr = pred + (((ypos >> 1) + 8) << 4) + xoffset;
    388 
    389             GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
    390 
    391             return 1;
    392         }
    393         else /* pad bottom of frame */
    394         {
    395             xoffset = xpos >> 1;
    396             xoffset = xoffset & 0x3; /* word align ptr */
    397             /* copy block */
    398             ptr = pred ;
    399             prev = c_prev + width * (height - 8) + (xpos >> 1) - xoffset;
    400             if (xoffset  || (xpos&1))
    401             {
    402                 COPY_12x8
    403             }
    404             else
    405             {
    406                 COPY_BLOCK
    407             }
    408 
    409             /* pad bottom */
    410             ptr = pred + (8 << 4);
    411             prev = ptr - 16;
    412             PAD_ROW
    413             if (xoffset || (xpos&1))
    414             {
    415                 ptr = pred + (8 << 4) + 8;
    416                 PAD_EXTRA_4x8
    417             }
    418 
    419             ptr = pred + (((ypos >> 1) - (height - 8)) << 4) + xoffset;
    420 
    421             GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
    422 
    423             return 1;
    424         }
    425     }
    426     else
    427     {
    428         if (ypos < 0) /* pad top right of frame */
    429         {
    430             /* copy block */
    431             ptr = pred + (8 << 4);
    432             prev = c_prev + width - 8;
    433             COPY_BLOCK
    434 
    435             /* pad top-right */
    436             ptr = pred + 8;
    437             prev = pred + (8 << 4) + 7;
    438             PAD_CORNER
    439 
    440             /* pad top */
    441             ptr = pred ;
    442             prev = pred + (8 << 4);
    443             PAD_ROW;
    444 
    445             /* pad right */
    446             ptr = pred + (8 << 4) + 8;
    447             prev = ptr - 1;
    448             PAD_COL;
    449 
    450             ptr = pred + ((8 + (ypos >> 1)) << 4) + (8 - (width - (xpos >> 1)));
    451 
    452             GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
    453 
    454             return 1;
    455         }
    456         else if ((ypos >> 1) < (height - B_SIZE)) /* pad right of frame */
    457         {
    458             /* copy block */
    459             ptr = pred;
    460             prev = c_prev + (ypos >> 1) * width + width - 8;
    461             COPY_BLOCK
    462             /* copy extra line */
    463             *((uint32*)(ptr += 16)) = *((uint32*)(prev += width));
    464             *((uint32*)(ptr + 4)) = *((uint32*)(prev + 4));
    465 
    466             /* pad right */
    467             ptr = pred + 8;
    468             prev = ptr - 1;
    469             PAD_COL;
    470             /* pad extra line */
    471             temp = *(prev += 16);
    472             temp |= (temp << 8);
    473             temp |= (temp << 16);
    474             *((uint32*)(ptr += 16)) = temp;
    475             *((uint32*)(ptr + 4)) = temp;
    476 
    477 
    478             ptr = pred + 8 - (width - (xpos >> 1));
    479 
    480             GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
    481 
    482             return 1;
    483 
    484         }
    485         else /* pad bottom right of frame */
    486         {
    487             /* copy block */
    488             ptr = pred;
    489             prev = c_prev + width * (height - 8) + width - 8;
    490             COPY_BLOCK
    491 
    492             /* pad bottom-right */
    493             ptr = pred + (8 << 4) + 8;
    494             prev = ptr - 17;
    495             PAD_CORNER
    496 
    497             /* pad right */
    498             ptr = pred + 8;
    499             prev = ptr - 1;
    500             PAD_COL
    501 
    502             /* pad bottom */
    503             ptr = pred + (8 << 4);
    504             prev = ptr - 16;
    505             PAD_ROW
    506 
    507             ptr = pred + 8 - (width - (xpos >> 1)) + ((8 - (height - (ypos >> 1))) << 4);
    508 
    509             GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
    510 
    511             return 1;
    512         }
    513     }
    514 }
    515