PageRenderTime 67ms CodeModel.GetById 2ms app.highlight 58ms RepoModel.GetById 1ms app.codeStats 0ms

/H264Dec/source/h264bsd_inter_prediction.c

http://github.com/mbebenita/Broadway
C | 1027 lines | 646 code | 175 blank | 206 comment | 101 complexity | f4e66e14665fb0988b02d085fb58e453 MD5 | raw file
   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
  56typedef struct
  57{
  58    u32 available;
  59    u32 refIndex;
  60    mv_t mv;
  61} interNeighbour_t;
  62
  63/*------------------------------------------------------------------------------
  64    4. Local function prototypes
  65------------------------------------------------------------------------------*/
  66
  67static u32 MvPrediction16x16(mbStorage_t *pMb, mbPred_t *mbPred,
  68    dpbStorage_t *dpb);
  69static u32 MvPrediction16x8(mbStorage_t *pMb, mbPred_t *mbPred,
  70    dpbStorage_t *dpb);
  71static u32 MvPrediction8x16(mbStorage_t *pMb, mbPred_t *mbPred,
  72    dpbStorage_t *dpb);
  73static u32 MvPrediction8x8(mbStorage_t *pMb, subMbPred_t *subMbPred,
  74    dpbStorage_t *dpb);
  75static u32 MvPrediction(mbStorage_t *pMb, subMbPred_t *subMbPred,
  76    u32 mbPartIdx, u32 subMbPartIdx);
  77static i32 MedianFilter(i32 a, i32 b, i32 c);
  78
  79static void GetInterNeighbour(u32 sliceId, mbStorage_t *nMb,
  80    interNeighbour_t *n, u32 index);
  81static void GetPredictionMv(mv_t *mv, interNeighbour_t *a, u32 refIndex);
  82
  83static 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
 104static 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
 125static 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
 146static 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------------------------------------------------------------------------------*/
 197u32 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------------------------------------------------------------------------------*/
 360u32 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
 493u32 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
 577u32 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
 684u32 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
 794u32 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
 831u32 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
 919i32 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
 962void 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
 998void 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