Home | History | Annotate | Download | only in source
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      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 express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*------------------------------------------------------------------------------
     18 
     19     Table of contents
     20 
     21      1. Include headers
     22      2. External compiler flags
     23      3. Module defines
     24      4. Local function prototypes
     25      5. Functions
     26           h264bsdInterPrediction
     27           MvPrediction16x16
     28           MvPrediction16x8
     29           MvPrediction8x16
     30           MvPrediction8x8
     31           MvPrediction
     32           MedianFilter
     33           GetInterNeighbour
     34           GetPredictionMv
     35 
     36 ------------------------------------------------------------------------------*/
     37 
     38 /*------------------------------------------------------------------------------
     39     1. Include headers
     40 ------------------------------------------------------------------------------*/
     41 
     42 #include "h264bsd_inter_prediction.h"
     43 #include "h264bsd_neighbour.h"
     44 #include "h264bsd_util.h"
     45 #include "h264bsd_reconstruct.h"
     46 #include "h264bsd_dpb.h"
     47 
     48 /*------------------------------------------------------------------------------
     49     2. External compiler flags
     50 --------------------------------------------------------------------------------
     51 
     52 --------------------------------------------------------------------------------
     53     3. Module defines
     54 ------------------------------------------------------------------------------*/
     55 
     56 typedef struct
     57 {
     58     u32 available;
     59     u32 refIndex;
     60     mv_t mv;
     61 } interNeighbour_t;
     62 
     63 /*------------------------------------------------------------------------------
     64     4. Local function prototypes
     65 ------------------------------------------------------------------------------*/
     66 
     67 static u32 MvPrediction16x16(mbStorage_t *pMb, mbPred_t *mbPred,
     68     dpbStorage_t *dpb);
     69 static u32 MvPrediction16x8(mbStorage_t *pMb, mbPred_t *mbPred,
     70     dpbStorage_t *dpb);
     71 static u32 MvPrediction8x16(mbStorage_t *pMb, mbPred_t *mbPred,
     72     dpbStorage_t *dpb);
     73 static u32 MvPrediction8x8(mbStorage_t *pMb, subMbPred_t *subMbPred,
     74     dpbStorage_t *dpb);
     75 static u32 MvPrediction(mbStorage_t *pMb, subMbPred_t *subMbPred,
     76     u32 mbPartIdx, u32 subMbPartIdx);
     77 static i32 MedianFilter(i32 a, i32 b, i32 c);
     78 
     79 static void GetInterNeighbour(u32 sliceId, mbStorage_t *nMb,
     80     interNeighbour_t *n, u32 index);
     81 static void GetPredictionMv(mv_t *mv, interNeighbour_t *a, u32 refIndex);
     82 
     83 static const neighbour_t N_A_SUB_PART[4][4][4] = {
     84     { { {MB_A,5}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
     85       { {MB_A,5}, {MB_A,7}, {MB_NA,0}, {MB_NA,0} },
     86       { {MB_A,5}, {MB_CURR,0}, {MB_NA,0}, {MB_NA,0} },
     87       { {MB_A,5}, {MB_CURR,0}, {MB_A,7}, {MB_CURR,2} } },
     88 
     89     { { {MB_CURR,1}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
     90       { {MB_CURR,1}, {MB_CURR,3}, {MB_NA,0}, {MB_NA,0} },
     91       { {MB_CURR,1}, {MB_CURR,4}, {MB_NA,0}, {MB_NA,0} },
     92       { {MB_CURR,1}, {MB_CURR,4}, {MB_CURR,3}, {MB_CURR,6} } },
     93 
     94     { { {MB_A,13}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
     95       { {MB_A,13}, {MB_A,15}, {MB_NA,0}, {MB_NA,0} },
     96       { {MB_A,13}, {MB_CURR,8}, {MB_NA,0}, {MB_NA,0} },
     97       { {MB_A,13}, {MB_CURR,8}, {MB_A,15}, {MB_CURR,10} } },
     98 
     99     { { {MB_CURR,9}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
    100       { {MB_CURR,9}, {MB_CURR,11}, {MB_NA,0}, {MB_NA,0} },
    101       { {MB_CURR,9}, {MB_CURR,12}, {MB_NA,0}, {MB_NA,0} },
    102       { {MB_CURR,9}, {MB_CURR,12}, {MB_CURR,11}, {MB_CURR,14} } } };
    103 
    104 static const neighbour_t N_B_SUB_PART[4][4][4] = {
    105     { { {MB_B,10}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
    106       { {MB_B,10}, {MB_CURR,0}, {MB_NA,0}, {MB_NA,0} },
    107       { {MB_B,10}, {MB_B,11}, {MB_NA,0}, {MB_NA,0} },
    108       { {MB_B,10}, {MB_B,11}, {MB_CURR,0}, {MB_CURR,1} } },
    109 
    110     { { {MB_B,14}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
    111       { {MB_B,14}, {MB_CURR,4}, {MB_NA,0}, {MB_NA,0} },
    112       { {MB_B,14}, {MB_B,15}, {MB_NA,0}, {MB_NA,0} },
    113       { {MB_B,14}, {MB_B,15}, {MB_CURR,4}, {MB_CURR,5} } },
    114 
    115     { { {MB_CURR,2}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
    116       { {MB_CURR,2}, {MB_CURR,8}, {MB_NA,0}, {MB_NA,0} },
    117       { {MB_CURR,2}, {MB_CURR,3}, {MB_NA,0}, {MB_NA,0} },
    118       { {MB_CURR,2}, {MB_CURR,3}, {MB_CURR,8}, {MB_CURR,9} } },
    119 
    120     { { {MB_CURR,6}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
    121       { {MB_CURR,6}, {MB_CURR,12}, {MB_NA,0}, {MB_NA,0} },
    122       { {MB_CURR,6}, {MB_CURR,7}, {MB_NA,0}, {MB_NA,0} },
    123       { {MB_CURR,6}, {MB_CURR,7}, {MB_CURR,12}, {MB_CURR,13} } } };
    124 
    125 static const neighbour_t N_C_SUB_PART[4][4][4] = {
    126     { { {MB_B,14}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
    127       { {MB_B,14}, {MB_NA,4}, {MB_NA,0}, {MB_NA,0} },
    128       { {MB_B,11}, {MB_B,14}, {MB_NA,0}, {MB_NA,0} },
    129       { {MB_B,11}, {MB_B,14}, {MB_CURR,1}, {MB_NA,4} } },
    130 
    131     { { {MB_C,10}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
    132       { {MB_C,10}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
    133       { {MB_B,15}, {MB_C,10}, {MB_NA,0}, {MB_NA,0} },
    134       { {MB_B,15}, {MB_C,10}, {MB_CURR,5}, {MB_NA,0} } },
    135 
    136     { { {MB_CURR,6}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
    137       { {MB_CURR,6}, {MB_NA,12}, {MB_NA,0}, {MB_NA,0} },
    138       { {MB_CURR,3}, {MB_CURR,6}, {MB_NA,0}, {MB_NA,0} },
    139       { {MB_CURR,3}, {MB_CURR,6}, {MB_CURR,9}, {MB_NA,12} } },
    140 
    141     { { {MB_NA,2}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
    142       { {MB_NA,2}, {MB_NA,8}, {MB_NA,0}, {MB_NA,0} },
    143       { {MB_CURR,7}, {MB_NA,2}, {MB_NA,0}, {MB_NA,0} },
    144       { {MB_CURR,7}, {MB_NA,2}, {MB_CURR,13}, {MB_NA,8} } } };
    145 
    146 static const neighbour_t N_D_SUB_PART[4][4][4] = {
    147     { { {MB_D,15}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
    148       { {MB_D,15}, {MB_A,5}, {MB_NA,0}, {MB_NA,0} },
    149       { {MB_D,15}, {MB_B,10}, {MB_NA,0}, {MB_NA,0} },
    150       { {MB_D,15}, {MB_B,10}, {MB_A,5}, {MB_CURR,0} } },
    151 
    152     { { {MB_B,11}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
    153       { {MB_B,11}, {MB_CURR,1}, {MB_NA,0}, {MB_NA,0} },
    154       { {MB_B,11}, {MB_B,14}, {MB_NA,0}, {MB_NA,0} },
    155       { {MB_B,11}, {MB_B,14}, {MB_CURR,1}, {MB_CURR,4} } },
    156 
    157     { { {MB_A,7}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
    158       { {MB_A,7}, {MB_A,13}, {MB_NA,0}, {MB_NA,0} },
    159       { {MB_A,7}, {MB_CURR,2}, {MB_NA,0}, {MB_NA,0} },
    160       { {MB_A,7}, {MB_CURR,2}, {MB_A,13}, {MB_CURR,8} } },
    161 
    162     { { {MB_CURR,3}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
    163       { {MB_CURR,3}, {MB_CURR,9}, {MB_NA,0}, {MB_NA,0} },
    164       { {MB_CURR,3}, {MB_CURR,6}, {MB_NA,0}, {MB_NA,0} },
    165       { {MB_CURR,3}, {MB_CURR,6}, {MB_CURR,9}, {MB_CURR,12} } } };
    166 
    167 
    168 #ifdef H264DEC_OMXDL
    169 
    170 /*------------------------------------------------------------------------------
    171 
    172     Function: h264bsdInterPrediction
    173 
    174         Functional description:
    175           Processes one inter macroblock. Performs motion vector prediction
    176           and reconstructs prediction macroblock. Writes the final macroblock
    177           (prediction + residual) into the output image (currImage)
    178 
    179         Inputs:
    180           pMb           pointer to macroblock specific information
    181           pMbLayer      pointer to current macroblock data from stream
    182           dpb           pointer to decoded picture buffer
    183           mbNum         current macroblock number
    184           currImage     pointer to output image
    185           data          pointer where predicted macroblock will be stored
    186 
    187         Outputs:
    188           pMb           structure is updated with current macroblock
    189           currImage     current macroblock is written into image
    190           data          prediction is stored here
    191 
    192         Returns:
    193           HANTRO_OK     success
    194           HANTRO_NOK    error in motion vector prediction
    195 
    196 ------------------------------------------------------------------------------*/
    197 u32 h264bsdInterPrediction(mbStorage_t *pMb, macroblockLayer_t *pMbLayer,
    198     dpbStorage_t *dpb, u32 mbNum, image_t *currImage, u8 *data)
    199 {
    200 
    201 /* Variables */
    202 
    203     u32 i;
    204     u32 x, y;
    205     u32 colAndRow;
    206     subMbPartMode_e subPartMode;
    207     image_t refImage;
    208     u8 fillBuff[32*21 + 15 + 32];
    209     u8 *pFill;
    210     u32 tmp;
    211 /* Code */
    212 
    213     ASSERT(pMb);
    214     ASSERT(h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTER);
    215     ASSERT(pMbLayer);
    216 
    217     /* 16-byte alignment */
    218     pFill = ALIGN(fillBuff, 16);
    219 
    220     /* set row bits 15:0 */
    221     colAndRow = mbNum / currImage->width;
    222     /*set col to bits 31:16 */
    223     colAndRow += (mbNum - colAndRow * currImage->width) << 16;
    224     colAndRow <<= 4;
    225 
    226     refImage.width = currImage->width;
    227     refImage.height = currImage->height;
    228 
    229     switch (pMb->mbType)
    230     {
    231         case P_Skip:
    232         case P_L0_16x16:
    233             if (MvPrediction16x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
    234                 return(HANTRO_NOK);
    235             refImage.data = pMb->refAddr[0];
    236             tmp = (0<<24) + (0<<16) + (16<<8) + 16;
    237             h264bsdPredictSamples(data, pMb->mv, &refImage,
    238                                     colAndRow, tmp, pFill);
    239             break;
    240 
    241         case P_L0_L0_16x8:
    242             if ( MvPrediction16x8(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
    243                 return(HANTRO_NOK);
    244             refImage.data = pMb->refAddr[0];
    245             tmp = (0<<24) + (0<<16) + (16<<8) + 8;
    246             h264bsdPredictSamples(data, pMb->mv, &refImage,
    247                                     colAndRow, tmp, pFill);
    248 
    249             refImage.data = pMb->refAddr[2];
    250             tmp = (0<<24) + (8<<16) + (16<<8) + 8;
    251             h264bsdPredictSamples(data, pMb->mv+8, &refImage,
    252                                     colAndRow, tmp, pFill);
    253             break;
    254 
    255         case P_L0_L0_8x16:
    256             if ( MvPrediction8x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
    257                 return(HANTRO_NOK);
    258             refImage.data = pMb->refAddr[0];
    259             tmp = (0<<24) + (0<<16) + (8<<8) + 16;
    260             h264bsdPredictSamples(data, pMb->mv, &refImage,
    261                                     colAndRow, tmp, pFill);
    262             refImage.data = pMb->refAddr[1];
    263             tmp = (8<<24) + (0<<16) + (8<<8) + 16;
    264             h264bsdPredictSamples(data, pMb->mv+4, &refImage,
    265                                     colAndRow, tmp, pFill);
    266             break;
    267 
    268         default: /* P_8x8 and P_8x8ref0 */
    269             if ( MvPrediction8x8(pMb, &pMbLayer->subMbPred, dpb) != HANTRO_OK)
    270                 return(HANTRO_NOK);
    271             for (i = 0; i < 4; i++)
    272             {
    273                 refImage.data = pMb->refAddr[i];
    274                 subPartMode =
    275                     h264bsdSubMbPartMode(pMbLayer->subMbPred.subMbType[i]);
    276                 x = i & 0x1 ? 8 : 0;
    277                 y = i < 2 ? 0 : 8;
    278                 switch (subPartMode)
    279                 {
    280                     case MB_SP_8x8:
    281                         tmp = (x<<24) + (y<<16) + (8<<8) + 8;
    282                         h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
    283                                                     colAndRow, tmp, pFill);
    284                         break;
    285 
    286                     case MB_SP_8x4:
    287                         tmp = (x<<24) + (y<<16) + (8<<8) + 4;
    288                         h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
    289                                                     colAndRow, tmp, pFill);
    290                         tmp = (x<<24) + ((y+4)<<16) + (8<<8) + 4;
    291                         h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage,
    292                                                     colAndRow, tmp, pFill);
    293                         break;
    294 
    295                     case MB_SP_4x8:
    296                         tmp = (x<<24) + (y<<16) + (4<<8) + 8;
    297                         h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
    298                                                     colAndRow, tmp, pFill);
    299                         tmp = ((x+4)<<24) + (y<<16) + (4<<8) + 8;
    300                         h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage,
    301                                                     colAndRow, tmp, pFill);
    302                         break;
    303 
    304                     default:
    305                         tmp = (x<<24) + (y<<16) + (4<<8) + 4;
    306                         h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
    307                                                     colAndRow, tmp, pFill);
    308                         tmp = ((x+4)<<24) + (y<<16) + (4<<8) + 4;
    309                         h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage,
    310                                                     colAndRow, tmp, pFill);
    311                         tmp = (x<<24) + ((y+4)<<16) + (4<<8) + 4;
    312                         h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage,
    313                                                     colAndRow, tmp, pFill);
    314                         tmp = ((x+4)<<24) + ((y+4)<<16) + (4<<8) + 4;
    315                         h264bsdPredictSamples(data, pMb->mv+4*i+3, &refImage,
    316                                                     colAndRow, tmp, pFill);
    317                         break;
    318                 }
    319             }
    320             break;
    321     }
    322 
    323     /* if decoded flag > 1 -> mb has already been successfully decoded and
    324      * written to output -> do not write again */
    325     if (pMb->decoded > 1)
    326         return HANTRO_OK;
    327 
    328     return(HANTRO_OK);
    329 }
    330 
    331 #else /* H264DEC_OMXDL */
    332 
    333 /*------------------------------------------------------------------------------
    334 
    335     Function: h264bsdInterPrediction
    336 
    337         Functional description:
    338           Processes one inter macroblock. Performs motion vector prediction
    339           and reconstructs prediction macroblock. Writes the final macroblock
    340           (prediction + residual) into the output image (currImage)
    341 
    342         Inputs:
    343           pMb           pointer to macroblock specific information
    344           pMbLayer      pointer to current macroblock data from stream
    345           dpb           pointer to decoded picture buffer
    346           mbNum         current macroblock number
    347           currImage     pointer to output image
    348           data          pointer where predicted macroblock will be stored
    349 
    350         Outputs:
    351           pMb           structure is updated with current macroblock
    352           currImage     current macroblock is written into image
    353           data          prediction is stored here
    354 
    355         Returns:
    356           HANTRO_OK     success
    357           HANTRO_NOK    error in motion vector prediction
    358 
    359 ------------------------------------------------------------------------------*/
    360 u32 h264bsdInterPrediction(mbStorage_t *pMb, macroblockLayer_t *pMbLayer,
    361     dpbStorage_t *dpb, u32 mbNum, image_t *currImage, u8 *data)
    362 {
    363 
    364 /* Variables */
    365 
    366     u32 i;
    367     u32 x, y;
    368     u32 row, col;
    369     subMbPartMode_e subPartMode;
    370     image_t refImage;
    371 
    372 /* Code */
    373 
    374     ASSERT(pMb);
    375     ASSERT(h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTER);
    376     ASSERT(pMbLayer);
    377 
    378     row = mbNum / currImage->width;
    379     col = mbNum - row * currImage->width;
    380     row *= 16;
    381     col *= 16;
    382 
    383     refImage.width = currImage->width;
    384     refImage.height = currImage->height;
    385 
    386     switch (pMb->mbType)
    387     {
    388         case P_Skip:
    389         case P_L0_16x16:
    390             if (MvPrediction16x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
    391                 return(HANTRO_NOK);
    392             refImage.data = pMb->refAddr[0];
    393             h264bsdPredictSamples(data, pMb->mv, &refImage, col, row, 0, 0,
    394                 16, 16);
    395             break;
    396 
    397         case P_L0_L0_16x8:
    398             if ( MvPrediction16x8(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
    399                 return(HANTRO_NOK);
    400             refImage.data = pMb->refAddr[0];
    401             h264bsdPredictSamples(data, pMb->mv, &refImage, col, row, 0, 0,
    402                 16, 8);
    403             refImage.data = pMb->refAddr[2];
    404             h264bsdPredictSamples(data, pMb->mv+8, &refImage, col, row, 0, 8,
    405                 16, 8);
    406             break;
    407 
    408         case P_L0_L0_8x16:
    409             if ( MvPrediction8x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
    410                 return(HANTRO_NOK);
    411             refImage.data = pMb->refAddr[0];
    412             h264bsdPredictSamples(data, pMb->mv, &refImage, col, row, 0, 0,
    413                 8, 16);
    414             refImage.data = pMb->refAddr[1];
    415             h264bsdPredictSamples(data, pMb->mv+4, &refImage, col, row, 8, 0,
    416                 8, 16);
    417             break;
    418 
    419         default: /* P_8x8 and P_8x8ref0 */
    420             if ( MvPrediction8x8(pMb, &pMbLayer->subMbPred, dpb) != HANTRO_OK)
    421                 return(HANTRO_NOK);
    422             for (i = 0; i < 4; i++)
    423             {
    424                 refImage.data = pMb->refAddr[i];
    425                 subPartMode =
    426                     h264bsdSubMbPartMode(pMbLayer->subMbPred.subMbType[i]);
    427                 x = i & 0x1 ? 8 : 0;
    428                 y = i < 2 ? 0 : 8;
    429                 switch (subPartMode)
    430                 {
    431                     case MB_SP_8x8:
    432                         h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
    433                             col, row, x, y, 8, 8);
    434                         break;
    435 
    436                     case MB_SP_8x4:
    437                         h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
    438                             col, row, x, y, 8, 4);
    439                         h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage,
    440                             col, row, x, y+4, 8, 4);
    441                         break;
    442 
    443                     case MB_SP_4x8:
    444                         h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
    445                             col, row, x, y, 4, 8);
    446                         h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage,
    447                             col, row, x+4, y, 4, 8);
    448                         break;
    449 
    450                     default:
    451                         h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
    452                             col, row, x, y, 4, 4);
    453                         h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage,
    454                             col, row, x+4, y, 4, 4);
    455                         h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage,
    456                             col, row, x, y+4, 4, 4);
    457                         h264bsdPredictSamples(data, pMb->mv+4*i+3, &refImage,
    458                             col, row, x+4, y+4, 4, 4);
    459                         break;
    460                 }
    461             }
    462             break;
    463     }
    464 
    465     /* if decoded flag > 1 -> mb has already been successfully decoded and
    466      * written to output -> do not write again */
    467     if (pMb->decoded > 1)
    468         return HANTRO_OK;
    469 
    470     if (pMb->mbType != P_Skip)
    471     {
    472         h264bsdWriteOutputBlocks(currImage, mbNum, data,
    473             pMbLayer->residual.level);
    474     }
    475     else
    476     {
    477         h264bsdWriteMacroblock(currImage, data);
    478     }
    479 
    480     return(HANTRO_OK);
    481 }
    482 #endif /* H264DEC_OMXDL */
    483 
    484 /*------------------------------------------------------------------------------
    485 
    486     Function: MvPrediction16x16
    487 
    488         Functional description:
    489             Motion vector prediction for 16x16 partition mode
    490 
    491 ------------------------------------------------------------------------------*/
    492 
    493 u32 MvPrediction16x16(mbStorage_t *pMb, mbPred_t *mbPred, dpbStorage_t *dpb)
    494 {
    495 
    496 /* Variables */
    497 
    498     mv_t mv;
    499     mv_t mvPred;
    500     interNeighbour_t a[3]; /* A, B, C */
    501     u32 refIndex;
    502     u8 *tmp;
    503     u32 *tmpMv1, *tmpMv2;
    504 
    505 /* Code */
    506 
    507     refIndex = mbPred->refIdxL0[0];
    508 
    509     GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 5);
    510     GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 10);
    511     /*lint --e(740)  Unusual pointer cast (incompatible indirect types) */
    512     tmpMv1 = (u32*)(&a[0].mv); /* we test just that both MVs are zero */
    513     /*lint --e(740) */
    514     tmpMv2 = (u32*)(&a[1].mv); /* i.e. a[0].mv.hor == 0 && a[0].mv.ver == 0 */
    515     if (pMb->mbType == P_Skip &&
    516         (!a[0].available || !a[1].available ||
    517          ( a[0].refIndex == 0 && ((u32)(*tmpMv1) == 0) ) ||
    518          ( a[1].refIndex == 0 && ((u32)(*tmpMv2) == 0) )))
    519     {
    520             mv.hor = mv.ver = 0;
    521     }
    522     else
    523     {
    524         mv = mbPred->mvdL0[0];
    525         GetInterNeighbour(pMb->sliceId, pMb->mbC, a+2, 10);
    526         if (!a[2].available)
    527         {
    528             GetInterNeighbour(pMb->sliceId, pMb->mbD, a+2, 15);
    529         }
    530 
    531         GetPredictionMv(&mvPred, a, refIndex);
    532 
    533         mv.hor += mvPred.hor;
    534         mv.ver += mvPred.ver;
    535 
    536         /* horizontal motion vector range [-2048, 2047.75] */
    537         if ((u32)(i32)(mv.hor+8192) >= (16384))
    538             return(HANTRO_NOK);
    539 
    540         /* vertical motion vector range [-512, 511.75]
    541          * (smaller for low levels) */
    542         if ((u32)(i32)(mv.ver+2048) >= (4096))
    543             return(HANTRO_NOK);
    544     }
    545 
    546     tmp = h264bsdGetRefPicData(dpb, refIndex);
    547     if (tmp == NULL)
    548         return(HANTRO_NOK);
    549 
    550     pMb->mv[0] = pMb->mv[1] = pMb->mv[2] = pMb->mv[3] =
    551     pMb->mv[4] = pMb->mv[5] = pMb->mv[6] = pMb->mv[7] =
    552     pMb->mv[8] = pMb->mv[9] = pMb->mv[10] = pMb->mv[11] =
    553     pMb->mv[12] = pMb->mv[13] = pMb->mv[14] = pMb->mv[15] = mv;
    554 
    555     pMb->refPic[0] = refIndex;
    556     pMb->refPic[1] = refIndex;
    557     pMb->refPic[2] = refIndex;
    558     pMb->refPic[3] = refIndex;
    559     pMb->refAddr[0] = tmp;
    560     pMb->refAddr[1] = tmp;
    561     pMb->refAddr[2] = tmp;
    562     pMb->refAddr[3] = tmp;
    563 
    564     return(HANTRO_OK);
    565 
    566 }
    567 
    568 /*------------------------------------------------------------------------------
    569 
    570     Function: MvPrediction16x8
    571 
    572         Functional description:
    573             Motion vector prediction for 16x8 partition mode
    574 
    575 ------------------------------------------------------------------------------*/
    576 
    577 u32 MvPrediction16x8(mbStorage_t *pMb, mbPred_t *mbPred, dpbStorage_t *dpb)
    578 {
    579 
    580 /* Variables */
    581 
    582     mv_t mv;
    583     mv_t mvPred;
    584     interNeighbour_t a[3]; /* A, B, C */
    585     u32 refIndex;
    586     u8 *tmp;
    587 
    588 /* Code */
    589 
    590     mv = mbPred->mvdL0[0];
    591     refIndex = mbPred->refIdxL0[0];
    592 
    593     GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 10);
    594 
    595     if (a[1].refIndex == refIndex)
    596         mvPred = a[1].mv;
    597     else
    598     {
    599         GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 5);
    600         GetInterNeighbour(pMb->sliceId, pMb->mbC, a+2, 10);
    601         if (!a[2].available)
    602         {
    603             GetInterNeighbour(pMb->sliceId, pMb->mbD, a+2, 15);
    604         }
    605 
    606         GetPredictionMv(&mvPred, a, refIndex);
    607 
    608     }
    609     mv.hor += mvPred.hor;
    610     mv.ver += mvPred.ver;
    611 
    612     /* horizontal motion vector range [-2048, 2047.75] */
    613     if ((u32)(i32)(mv.hor+8192) >= (16384))
    614         return(HANTRO_NOK);
    615 
    616     /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
    617     if ((u32)(i32)(mv.ver+2048) >= (4096))
    618         return(HANTRO_NOK);
    619 
    620     tmp = h264bsdGetRefPicData(dpb, refIndex);
    621     if (tmp == NULL)
    622         return(HANTRO_NOK);
    623 
    624     pMb->mv[0] = pMb->mv[1] = pMb->mv[2] = pMb->mv[3] =
    625     pMb->mv[4] = pMb->mv[5] = pMb->mv[6] = pMb->mv[7] = mv;
    626     pMb->refPic[0] = refIndex;
    627     pMb->refPic[1] = refIndex;
    628     pMb->refAddr[0] = tmp;
    629     pMb->refAddr[1] = tmp;
    630 
    631     mv = mbPred->mvdL0[1];
    632     refIndex = mbPred->refIdxL0[1];
    633 
    634     GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 13);
    635     if (a[0].refIndex == refIndex)
    636         mvPred = a[0].mv;
    637     else
    638     {
    639         a[1].available = HANTRO_TRUE;
    640         a[1].refIndex = pMb->refPic[0];
    641         a[1].mv = pMb->mv[0];
    642 
    643         /* c is not available */
    644         GetInterNeighbour(pMb->sliceId, pMb->mbA, a+2, 7);
    645 
    646         GetPredictionMv(&mvPred, a, refIndex);
    647 
    648     }
    649     mv.hor += mvPred.hor;
    650     mv.ver += mvPred.ver;
    651 
    652     /* horizontal motion vector range [-2048, 2047.75] */
    653     if ((u32)(i32)(mv.hor+8192) >= (16384))
    654         return(HANTRO_NOK);
    655 
    656     /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
    657     if ((u32)(i32)(mv.ver+2048) >= (4096))
    658         return(HANTRO_NOK);
    659 
    660     tmp = h264bsdGetRefPicData(dpb, refIndex);
    661     if (tmp == NULL)
    662         return(HANTRO_NOK);
    663 
    664     pMb->mv[8] = pMb->mv[9] = pMb->mv[10] = pMb->mv[11] =
    665     pMb->mv[12] = pMb->mv[13] = pMb->mv[14] = pMb->mv[15] = mv;
    666     pMb->refPic[2] = refIndex;
    667     pMb->refPic[3] = refIndex;
    668     pMb->refAddr[2] = tmp;
    669     pMb->refAddr[3] = tmp;
    670 
    671     return(HANTRO_OK);
    672 
    673 }
    674 
    675 /*------------------------------------------------------------------------------
    676 
    677     Function: MvPrediction8x16
    678 
    679         Functional description:
    680             Motion vector prediction for 8x16 partition mode
    681 
    682 ------------------------------------------------------------------------------*/
    683 
    684 u32 MvPrediction8x16(mbStorage_t *pMb, mbPred_t *mbPred, dpbStorage_t *dpb)
    685 {
    686 
    687 /* Variables */
    688 
    689     mv_t mv;
    690     mv_t mvPred;
    691     interNeighbour_t a[3]; /* A, B, C */
    692     u32 refIndex;
    693     u8 *tmp;
    694 
    695 /* Code */
    696 
    697     mv = mbPred->mvdL0[0];
    698     refIndex = mbPred->refIdxL0[0];
    699 
    700     GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 5);
    701 
    702     if (a[0].refIndex == refIndex)
    703         mvPred = a[0].mv;
    704     else
    705     {
    706         GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 10);
    707         GetInterNeighbour(pMb->sliceId, pMb->mbB, a+2, 14);
    708         if (!a[2].available)
    709         {
    710             GetInterNeighbour(pMb->sliceId, pMb->mbD, a+2, 15);
    711         }
    712 
    713         GetPredictionMv(&mvPred, a, refIndex);
    714 
    715     }
    716     mv.hor += mvPred.hor;
    717     mv.ver += mvPred.ver;
    718 
    719     /* horizontal motion vector range [-2048, 2047.75] */
    720     if ((u32)(i32)(mv.hor+8192) >= (16384))
    721         return(HANTRO_NOK);
    722 
    723     /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
    724     if ((u32)(i32)(mv.ver+2048) >= (4096))
    725         return(HANTRO_NOK);
    726 
    727     tmp = h264bsdGetRefPicData(dpb, refIndex);
    728     if (tmp == NULL)
    729         return(HANTRO_NOK);
    730 
    731     pMb->mv[0] = pMb->mv[1] = pMb->mv[2] = pMb->mv[3] =
    732     pMb->mv[8] = pMb->mv[9] = pMb->mv[10] = pMb->mv[11] = mv;
    733     pMb->refPic[0] = refIndex;
    734     pMb->refPic[2] = refIndex;
    735     pMb->refAddr[0] = tmp;
    736     pMb->refAddr[2] = tmp;
    737 
    738     mv = mbPred->mvdL0[1];
    739     refIndex = mbPred->refIdxL0[1];
    740 
    741     GetInterNeighbour(pMb->sliceId, pMb->mbC, a+2, 10);
    742     if (!a[2].available)
    743     {
    744         GetInterNeighbour(pMb->sliceId, pMb->mbB, a+2, 11);
    745     }
    746     if (a[2].refIndex == refIndex)
    747         mvPred = a[2].mv;
    748     else
    749     {
    750         a[0].available = HANTRO_TRUE;
    751         a[0].refIndex = pMb->refPic[0];
    752         a[0].mv = pMb->mv[0];
    753 
    754         GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 14);
    755 
    756         GetPredictionMv(&mvPred, a, refIndex);
    757 
    758     }
    759     mv.hor += mvPred.hor;
    760     mv.ver += mvPred.ver;
    761 
    762     /* horizontal motion vector range [-2048, 2047.75] */
    763     if ((u32)(i32)(mv.hor+8192) >= (16384))
    764         return(HANTRO_NOK);
    765 
    766     /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
    767     if ((u32)(i32)(mv.ver+2048) >= (4096))
    768         return(HANTRO_NOK);
    769 
    770     tmp = h264bsdGetRefPicData(dpb, refIndex);
    771     if (tmp == NULL)
    772         return(HANTRO_NOK);
    773 
    774     pMb->mv[4] = pMb->mv[5] = pMb->mv[6] = pMb->mv[7] =
    775     pMb->mv[12] = pMb->mv[13] = pMb->mv[14] = pMb->mv[15] = mv;
    776     pMb->refPic[1] = refIndex;
    777     pMb->refPic[3] = refIndex;
    778     pMb->refAddr[1] = tmp;
    779     pMb->refAddr[3] = tmp;
    780 
    781     return(HANTRO_OK);
    782 
    783 }
    784 
    785 /*------------------------------------------------------------------------------
    786 
    787     Function: MvPrediction8x8
    788 
    789         Functional description:
    790             Motion vector prediction for 8x8 partition mode
    791 
    792 ------------------------------------------------------------------------------*/
    793 
    794 u32 MvPrediction8x8(mbStorage_t *pMb, subMbPred_t *subMbPred, dpbStorage_t *dpb)
    795 {
    796 
    797 /* Variables */
    798 
    799     u32 i, j;
    800     u32 numSubMbPart;
    801 
    802 /* Code */
    803 
    804     for (i = 0; i < 4; i++)
    805     {
    806         numSubMbPart = h264bsdNumSubMbPart(subMbPred->subMbType[i]);
    807         pMb->refPic[i] = subMbPred->refIdxL0[i];
    808         pMb->refAddr[i] = h264bsdGetRefPicData(dpb, subMbPred->refIdxL0[i]);
    809         if (pMb->refAddr[i] == NULL)
    810             return(HANTRO_NOK);
    811         for (j = 0; j < numSubMbPart; j++)
    812         {
    813             if (MvPrediction(pMb, subMbPred, i, j) != HANTRO_OK)
    814                 return(HANTRO_NOK);
    815         }
    816     }
    817 
    818     return(HANTRO_OK);
    819 
    820 }
    821 
    822 /*------------------------------------------------------------------------------
    823 
    824     Function: MvPrediction
    825 
    826         Functional description:
    827             Perform motion vector prediction for sub-partition
    828 
    829 ------------------------------------------------------------------------------*/
    830 
    831 u32 MvPrediction(mbStorage_t *pMb, subMbPred_t *subMbPred, u32 mbPartIdx,
    832     u32 subMbPartIdx)
    833 {
    834 
    835 /* Variables */
    836 
    837     mv_t mv, mvPred;
    838     u32 refIndex;
    839     subMbPartMode_e subMbPartMode;
    840     const neighbour_t *n;
    841     mbStorage_t *nMb;
    842     interNeighbour_t a[3]; /* A, B, C */
    843 
    844 /* Code */
    845 
    846     mv = subMbPred->mvdL0[mbPartIdx][subMbPartIdx];
    847     subMbPartMode = h264bsdSubMbPartMode(subMbPred->subMbType[mbPartIdx]);
    848     refIndex = subMbPred->refIdxL0[mbPartIdx];
    849 
    850     n = N_A_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx;
    851     nMb = h264bsdGetNeighbourMb(pMb, n->mb);
    852     GetInterNeighbour(pMb->sliceId, nMb, a, n->index);
    853 
    854     n = N_B_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx;
    855     nMb = h264bsdGetNeighbourMb(pMb, n->mb);
    856     GetInterNeighbour(pMb->sliceId, nMb, a+1, n->index);
    857 
    858     n = N_C_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx;
    859     nMb = h264bsdGetNeighbourMb(pMb, n->mb);
    860     GetInterNeighbour(pMb->sliceId, nMb, a+2, n->index);
    861 
    862     if (!a[2].available)
    863     {
    864         n = N_D_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx;
    865         nMb = h264bsdGetNeighbourMb(pMb, n->mb);
    866         GetInterNeighbour(pMb->sliceId, nMb, a+2, n->index);
    867     }
    868 
    869     GetPredictionMv(&mvPred, a, refIndex);
    870 
    871     mv.hor += mvPred.hor;
    872     mv.ver += mvPred.ver;
    873 
    874     /* horizontal motion vector range [-2048, 2047.75] */
    875     if (((u32)(i32)(mv.hor+8192) >= (16384)))
    876         return(HANTRO_NOK);
    877 
    878     /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
    879     if (((u32)(i32)(mv.ver+2048) >= (4096)))
    880         return(HANTRO_NOK);
    881 
    882     switch (subMbPartMode)
    883     {
    884         case MB_SP_8x8:
    885             pMb->mv[4*mbPartIdx] = mv;
    886             pMb->mv[4*mbPartIdx + 1] = mv;
    887             pMb->mv[4*mbPartIdx + 2] = mv;
    888             pMb->mv[4*mbPartIdx + 3] = mv;
    889             break;
    890 
    891         case MB_SP_8x4:
    892             pMb->mv[4*mbPartIdx + 2*subMbPartIdx] = mv;
    893             pMb->mv[4*mbPartIdx + 2*subMbPartIdx + 1] = mv;
    894             break;
    895 
    896         case MB_SP_4x8:
    897             pMb->mv[4*mbPartIdx + subMbPartIdx] = mv;
    898             pMb->mv[4*mbPartIdx + subMbPartIdx + 2] = mv;
    899             break;
    900 
    901         case MB_SP_4x4:
    902             pMb->mv[4*mbPartIdx + subMbPartIdx] = mv;
    903             break;
    904     }
    905 
    906     return(HANTRO_OK);
    907 
    908 }
    909 
    910 /*------------------------------------------------------------------------------
    911 
    912     Function: MedianFilter
    913 
    914         Functional description:
    915             Median filtering for motion vector prediction
    916 
    917 ------------------------------------------------------------------------------*/
    918 
    919 i32 MedianFilter(i32 a, i32 b, i32 c)
    920 {
    921 
    922 /* Variables */
    923 
    924     i32 max,min,med;
    925 
    926 /* Code */
    927 
    928     max = min = med = a;
    929     if (b > max)
    930     {
    931         max = b;
    932     }
    933     else if (b < min)
    934     {
    935         min = b;
    936     }
    937     if (c > max)
    938     {
    939         med = max;
    940     }
    941     else if (c < min)
    942     {
    943         med = min;
    944     }
    945     else
    946     {
    947         med = c;
    948     }
    949 
    950     return(med);
    951 }
    952 
    953 /*------------------------------------------------------------------------------
    954 
    955     Function: GetInterNeighbour
    956 
    957         Functional description:
    958             Get availability, reference index and motion vector of a neighbour
    959 
    960 ------------------------------------------------------------------------------*/
    961 
    962 void GetInterNeighbour(u32 sliceId, mbStorage_t *nMb,
    963     interNeighbour_t *n, u32 index)
    964 {
    965 
    966     n->available = HANTRO_FALSE;
    967     n->refIndex = 0xFFFFFFFF;
    968     n->mv.hor = n->mv.ver = 0;
    969 
    970     if (nMb && (sliceId == nMb->sliceId))
    971     {
    972         u32 tmp;
    973         mv_t tmpMv;
    974 
    975         tmp = nMb->mbType;
    976         n->available = HANTRO_TRUE;
    977         /* MbPartPredMode "inlined" */
    978         if (tmp <= P_8x8ref0)
    979         {
    980             tmpMv = nMb->mv[index];
    981             tmp = nMb->refPic[index>>2];
    982             n->refIndex = tmp;
    983             n->mv = tmpMv;
    984         }
    985     }
    986 
    987 }
    988 
    989 /*------------------------------------------------------------------------------
    990 
    991     Function: GetPredictionMv
    992 
    993         Functional description:
    994             Compute motion vector predictor based on neighbours A, B and C
    995 
    996 ------------------------------------------------------------------------------*/
    997 
    998 void GetPredictionMv(mv_t *mv, interNeighbour_t *a, u32 refIndex)
    999 {
   1000 
   1001     if ( a[1].available || a[2].available || !a[0].available)
   1002     {
   1003         u32 isA, isB, isC;
   1004         isA = (a[0].refIndex == refIndex) ? HANTRO_TRUE : HANTRO_FALSE;
   1005         isB = (a[1].refIndex == refIndex) ? HANTRO_TRUE : HANTRO_FALSE;
   1006         isC = (a[2].refIndex == refIndex) ? HANTRO_TRUE : HANTRO_FALSE;
   1007 
   1008         if (((u32)isA+(u32)isB+(u32)isC) != 1)
   1009         {
   1010             mv->hor = (i16)MedianFilter(a[0].mv.hor, a[1].mv.hor, a[2].mv.hor);
   1011             mv->ver = (i16)MedianFilter(a[0].mv.ver, a[1].mv.ver, a[2].mv.ver);
   1012         }
   1013         else if (isA)
   1014             *mv = a[0].mv;
   1015         else if (isB)
   1016             *mv = a[1].mv;
   1017         else
   1018             *mv = a[2].mv;
   1019     }
   1020     else
   1021     {
   1022         *mv = a[0].mv;
   1023     }
   1024 
   1025 }
   1026 
   1027 
   1028