videoeditorengine/h263decoder/src/vdcaic.cpp
changeset 0 951a5db380a0
equal deleted inserted replaced
-1:000000000000 0:951a5db380a0
       
     1 /*
       
     2 * Copyright (c) 2010 Ixonos Plc.
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - Initial contribution
       
    11 *
       
    12 * Contributors:
       
    13 * Ixonos Plc
       
    14 *
       
    15 * Description:  
       
    16 * Advanced Intra Coding functions (MPEG-4).
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 
       
    22 
       
    23 #include "h263dConfig.h"
       
    24 
       
    25 #include "vdcaic.h"
       
    26 
       
    27 #include "errcodes.h"
       
    28 #include "debug.h"
       
    29 
       
    30 #include "zigzag.h"
       
    31 
       
    32 /*
       
    33  *
       
    34  * aicIntraDCSwitch
       
    35  *
       
    36  * Parameters:
       
    37  *    intraDCVLCThr  VOP-header field for QP dependent switching between 
       
    38  *                   MPEG-4 IntraDC coding and IntraAC VLC coding of the 
       
    39  *                   Intra DC coefficients
       
    40  *    QP             quantization parameter
       
    41  *
       
    42  * Function:
       
    43  *    This function decides based on the input parameters if the Intra DC
       
    44  *    should be decoded as MPEG-4 IntraDC (switched=0) or switched to  
       
    45  *    IntraAC VLC (switched=1)
       
    46  *
       
    47  * Returns:
       
    48  *    switched value
       
    49  *
       
    50  *
       
    51  *
       
    52  */
       
    53 
       
    54 u_char aicIntraDCSwitch(int intraDCVLCThr, int QP) {
       
    55 
       
    56    if ( intraDCVLCThr == 0 ) {
       
    57       return 0;
       
    58    }
       
    59    else if ( intraDCVLCThr == 7 ) {
       
    60       return 1;
       
    61    }
       
    62    else if ( QP >= intraDCVLCThr*2+11 ) {
       
    63       return 1;
       
    64    }
       
    65    else {
       
    66       return 0;
       
    67    }
       
    68 }
       
    69 
       
    70 /*
       
    71  *
       
    72  * aicDCScaler
       
    73  *
       
    74  * Parameters:
       
    75  *    QP       quantization parameter
       
    76  *    type     type of Block "1" Luminance "2" Chrominance
       
    77  *
       
    78  * Function:
       
    79  *    Calculation of DC quantization scale according
       
    80  *    to the incoming QP and block type
       
    81  *
       
    82  * Returns:
       
    83  *    dcScaler value
       
    84  *
       
    85  *
       
    86  *
       
    87  */
       
    88 
       
    89 int aicDCScaler (int QP, int type) {
       
    90 
       
    91    int dcScaler;
       
    92    if (type == 1) {
       
    93       if (QP > 0 && QP < 5) {
       
    94          dcScaler = 8;
       
    95       }
       
    96       else if (QP > 4 && QP < 9) {
       
    97          dcScaler = 2 * QP;
       
    98       }
       
    99       else if (QP > 8 && QP < 25) {
       
   100          dcScaler = QP + 8;
       
   101       }
       
   102       else {
       
   103          dcScaler = 2 * QP - 16;
       
   104       }
       
   105    }
       
   106    else {
       
   107       if (QP > 0 && QP < 5) {
       
   108          dcScaler = 8;
       
   109       }
       
   110       else if (QP > 4 && QP < 25) {
       
   111          dcScaler = (QP + 13) / 2;
       
   112       }
       
   113       else {
       
   114          dcScaler = QP - 6;
       
   115       }
       
   116    }
       
   117    return dcScaler;
       
   118 }
       
   119 
       
   120 /**
       
   121  * Small routine to compensate the QP value differences between the
       
   122  * predictor and current block AC coefficients
       
   123  *
       
   124  **/
       
   125 
       
   126 static int compensateQPDiff(int val, int QP) {
       
   127 
       
   128    if (val<0) {
       
   129       return (val-(QP>>1))/QP;
       
   130    }
       
   131    else {
       
   132       return (val+(QP>>1))/QP;
       
   133    }
       
   134 }
       
   135 
       
   136 /**
       
   137  * Small routine to fill default prediction values into a dcStore entry
       
   138  *
       
   139  */
       
   140 
       
   141 static void resetPredRow(int pred[])
       
   142 {
       
   143    memset (pred, 0, 7 * sizeof(int));
       
   144 }    
       
   145 
       
   146 /*
       
   147  *
       
   148  * aicStart
       
   149  *
       
   150  * Parameters:
       
   151  *    aicData     aicData_t structure
       
   152  *    instance    pointer to vdcInstance_t structure
       
   153  *
       
   154  * Function:
       
   155  *    This function initialises dcStore and qpStore buffers.
       
   156  *    One should call aicStart in the beginning of each VOP.
       
   157  *
       
   158  * Returns:
       
   159  *    Nothing
       
   160  *
       
   161  * Error codes:
       
   162  *
       
   163  *
       
   164  */
       
   165 
       
   166 void aicStart(aicData_t *aicData, int numMBsInMBLine, int16 *error)
       
   167 {
       
   168 
       
   169    int i,j, numStoreUnits;
       
   170    int initXpos[6] = {-1, 0, -1, 0, -1, -1};
       
   171    int initYpos[6] = {-1, -1, 0, 0, -1, -1};
       
   172    int initXtab[6] = {1, 0, 3, 2, 4, 5};
       
   173    int initYtab[6] = {2, 3, 0, 1, 4, 5};
       
   174    int initZtab[6] = {3, 2, 1, 0, 4, 5};
       
   175 
       
   176    numStoreUnits = numMBsInMBLine*2;
       
   177 
       
   178    if (!aicData->qpStore || !aicData->dcStore) {
       
   179       aicData->qpStore = (int16 *) calloc(numStoreUnits, sizeof(int16));
       
   180       if (!aicData->qpStore)
       
   181       {
       
   182           *error = ERR_VDC_MEMORY_ALLOC;
       
   183           return;
       
   184       }
       
   185       
       
   186       /* allocate space for 3D matrix to keep track of prediction values
       
   187       for DC/AC prediction */
       
   188       
       
   189       aicData->dcStore = (int ***)calloc(numStoreUnits, sizeof(int **));
       
   190       if (!aicData->dcStore)
       
   191       {
       
   192           *error = ERR_VDC_MEMORY_ALLOC;
       
   193           return;
       
   194       }
       
   195 
       
   196       for (i = 0; i < numStoreUnits; i++)
       
   197       {
       
   198          aicData->dcStore[i] = (int **)calloc(6, sizeof(int *));
       
   199          if (!aicData->dcStore[i])
       
   200          {
       
   201              *error = ERR_VDC_MEMORY_ALLOC;
       
   202              return;
       
   203          }
       
   204 
       
   205          for (j = 0; j < 6; j++)
       
   206          {
       
   207             aicData->dcStore[i][j] = (int *)calloc(15, sizeof(int));
       
   208             if ( !(aicData->dcStore[i][j]) )
       
   209             {
       
   210                 *error = ERR_VDC_MEMORY_ALLOC;
       
   211                 return;
       
   212             }
       
   213          }
       
   214       }
       
   215       
       
   216       aicData->numMBsInMBLine = numMBsInMBLine;
       
   217 
       
   218       for (i= 0; i < 6; i++)
       
   219       {
       
   220          aicData->Xpos[i] = initXpos[i];
       
   221          aicData->Ypos[i] = initYpos[i];
       
   222          aicData->Xtab[i] = initXtab[i];
       
   223          aicData->Ytab[i] = initYtab[i];
       
   224          aicData->Ztab[i] = initZtab[i];
       
   225       }
       
   226 
       
   227       /* 1 << (instance->bits_per_pixel - 1) */
       
   228       aicData->midGrey = 1 << 7; 
       
   229 
       
   230       aicData->ACpred_flag = 1;
       
   231    } else {
       
   232       memset(aicData->qpStore, 0, numStoreUnits * sizeof(int16));
       
   233    }
       
   234 
       
   235 }
       
   236 
       
   237 /*
       
   238  * Clip the reconstructed coefficient when it is stored for prediction 
       
   239  *
       
   240  */
       
   241 
       
   242 #define aicClip(rec) \
       
   243    ((rec < -2048) ? -2048 : ((rec > 2047) ? 2047 : rec))
       
   244    
       
   245 /*
       
   246  *
       
   247  * aicBlockUpdate
       
   248  *
       
   249  * Parameters:
       
   250  *    aicData        aicData_t structure
       
   251  *    currMBNum      Current Macroblocks Number
       
   252  *
       
   253  * Function:
       
   254  *    This function fills up the dcStore and qpStore of current MB.
       
   255  *
       
   256  * Returns:
       
   257  *    Nothing
       
   258  *
       
   259  * Error codes:
       
   260  *    None
       
   261  *
       
   262  *
       
   263  */
       
   264 
       
   265 void aicBlockUpdate (aicData_t *aicData, int currMBNum, int blockNum, int *block,
       
   266                 int pquant, int DC_coeff)
       
   267 {
       
   268 
       
   269    int n, currDCStoreIndex;
       
   270    assert(currMBNum >= 0);
       
   271 
       
   272    currDCStoreIndex = ((currMBNum / aicData->numMBsInMBLine) % 2) * aicData->numMBsInMBLine +
       
   273                   (currMBNum % aicData->numMBsInMBLine);
       
   274 
       
   275    if (block != NULL) {
       
   276       
       
   277       aicData->dcStore[currDCStoreIndex][blockNum][0] = aicClip(DC_coeff);
       
   278       block[0] = aicClip(block[0]);
       
   279 
       
   280       for (n = 1; n < 8; n++)
       
   281       {
       
   282          aicData->dcStore[currDCStoreIndex][blockNum][n] = block[zigzag[n]] = aicClip(block[zigzag[n]]);
       
   283          aicData->dcStore[currDCStoreIndex][blockNum][n+7] = block[zigzag[n<<3 /**8*/]] = aicClip(block[zigzag[n<<3 /**8*/]]);
       
   284       }
       
   285    }
       
   286 
       
   287    if (blockNum == 0) 
       
   288       aicData->qpStore[currDCStoreIndex]= (int16) pquant;
       
   289 }
       
   290 
       
   291 /*
       
   292  *
       
   293  * aicIsBlockValid
       
   294  *
       
   295  * Parameters:
       
   296  *    aicData        aicData_t structure
       
   297  *    currMBNum      Current Macroblocks Number
       
   298  *
       
   299  * Function:
       
   300  *    This function checks if the current MB has a valid entry in the 
       
   301  *    dcStore and qpStore (needed in predictor validation of I-MBs in a P-VOP).
       
   302  *
       
   303  * Returns:
       
   304  *    1 if MB has a valid entry
       
   305  *    0 if MB doesn't have a valid entry
       
   306  *
       
   307  * Error codes:
       
   308  *    None
       
   309  *
       
   310  *
       
   311  */
       
   312 
       
   313 int aicIsBlockValid (aicData_t *aicData, int currMBNum)
       
   314 {
       
   315    int currDCStoreIndex;
       
   316    assert(currMBNum >= 0);
       
   317 
       
   318    currDCStoreIndex = ((currMBNum / aicData->numMBsInMBLine) % 2) * aicData->numMBsInMBLine +
       
   319                   (currMBNum % aicData->numMBsInMBLine);
       
   320 
       
   321    if (aicData->qpStore[currDCStoreIndex] > 0 && aicData->qpStore[currDCStoreIndex] < 32)
       
   322       return 1;
       
   323    else
       
   324       return 0;
       
   325 }
       
   326 
       
   327 /*
       
   328  *
       
   329  * aicFree
       
   330  *
       
   331  * Parameters:
       
   332  *    aicData        aicData_t structure
       
   333  *    numOfMBs      Number of Macroblocks in VOP
       
   334  *
       
   335  * Function:
       
   336  *    This function frees the dynamic memory allocated by aicStart.
       
   337  *    aicFree should be called at least when exiting the main program.
       
   338  *    Alternatively it can be called whenever the playing a video has
       
   339  *    ended.
       
   340  *
       
   341  * Returns:
       
   342  *    Nothing
       
   343  *
       
   344  * Error codes:
       
   345  *    None
       
   346  *
       
   347  *
       
   348  */
       
   349 
       
   350 void aicFree(aicData_t *aicData)
       
   351 {
       
   352    int i,j;
       
   353 
       
   354    /* Free allocated memory for 3D matrix */
       
   355    if (aicData->dcStore) {
       
   356       for (i = 0; i < (aicData->numMBsInMBLine*2); i++)
       
   357       {
       
   358          for (j = 0; j < 6; j++)
       
   359             free((char *)aicData->dcStore[i][j]);
       
   360          free((char *)aicData->dcStore[i]);
       
   361       }
       
   362       free((char *)aicData->dcStore);
       
   363    }
       
   364 
       
   365    /* Free allocated memory for qpStore matrix */
       
   366    if (aicData->qpStore) {
       
   367       free((char *)aicData->qpStore);
       
   368    }
       
   369 }
       
   370 
       
   371 /*
       
   372  *
       
   373  * aicDCACrecon
       
   374  *
       
   375  * Parameters:
       
   376  *   aicData         aicData_t structure
       
   377  *   QP              QP of the current MB
       
   378  *   fTopMBMissing   flag indicating if the block above the current block
       
   379  *                   is outside of the current Video Packet or not a valid 
       
   380  *                   Intra block (in case of P-VOP decoding)
       
   381  *   fLeftMBMissing  flag indicating if the block left to the current block
       
   382  *                   is outside of the current Video Packet or not a valid 
       
   383  *                   Intra block (in case of P-VOP decoding)
       
   384  *   fBBlockOut      flag indicating if the top-left neighbour block of the
       
   385  *                   current block is outside of the current Video Packet
       
   386  *                   or not a valid Intra block (in case of P-VOP decoding)
       
   387  *   blockNum        number of the current block in the MB 
       
   388  *                   (0..3 luminance, 4..5 chrominance)
       
   389  *   qBlock          block of coefficients
       
   390  *   currMBNum       number of the current macroblocks in the VOP
       
   391  *
       
   392  * Function:
       
   393  *   This function reconstructs the DC and AC (first column or first row or none)
       
   394  *   coefficients of the current block by selecting the predictor from the 
       
   395  *   neighbouring blocks (or default values), and adding these predictor 
       
   396  *   values to qBlock. Its output is the quantized coefficient matrix in 
       
   397  *   normal zigzag order.
       
   398  *
       
   399  * Returns:
       
   400  *    Nothing
       
   401  *
       
   402  * Error codes:
       
   403  *    None
       
   404  *
       
   405  *
       
   406  */
       
   407 
       
   408 void aicDCACrecon(aicData_t *aicData, int QP, u_char fTopMBMissing, u_char fLeftMBMissing,
       
   409               u_char fBBlockOut,  int blockNum, int *qBlock, int currMBNum)
       
   410 {
       
   411    int m, n, tempDCScaler;
       
   412    int xCoordMB, yCoordMB, mbWidth, currDCStoreIndex;
       
   413    int blockA = 0, blockB = 0, blockC = 0, fBlockAExist = 0, fBlockCExist = 0;
       
   414    int gradHor, gradVer, predDC;
       
   415    int fVertical;
       
   416    int predA[7], predC[7];
       
   417    int pcoeff[64];
       
   418    assert(currMBNum >= 0);
       
   419    assert(qBlock != NULL);
       
   420 
       
   421    xCoordMB = currMBNum % aicData->numMBsInMBLine;
       
   422    yCoordMB = currMBNum / aicData->numMBsInMBLine;
       
   423    currDCStoreIndex = (yCoordMB % 2)*aicData->numMBsInMBLine + xCoordMB;
       
   424    mbWidth = aicData->numMBsInMBLine * ((currDCStoreIndex < aicData->numMBsInMBLine) ? -1 : 1);
       
   425 
       
   426 
       
   427    /* Find the direction of prediction and the DC prediction */
       
   428    switch ( blockNum ) {
       
   429    case 0 :
       
   430    case 4 :
       
   431    case 5 :
       
   432       /* Y0, U, and V blocks */
       
   433 
       
   434 
       
   435       /* Prediction blocks A (left), B (above-left), and C (above) */
       
   436       if ( ( yCoordMB == 0 && xCoordMB == 0) || (fTopMBMissing && fLeftMBMissing) || (xCoordMB == 0 && fTopMBMissing) || (yCoordMB == 0 && fLeftMBMissing) ) {
       
   437          /* top-left edge of VOP or VP */
       
   438          blockA = aicData->midGrey<<3 /**8*/;
       
   439          blockB = aicData->midGrey<<3 /**8*/;
       
   440          blockC = aicData->midGrey<<3 /**8*/;
       
   441          fBlockAExist = fBlockCExist = 0;
       
   442       }
       
   443       else if ( yCoordMB == 0 || fTopMBMissing ) {
       
   444          /* top row of VOP or VP, or MB on top not valid */
       
   445          blockA = aicData->dcStore[currDCStoreIndex+aicData->Xpos[blockNum]][aicData->Xtab[blockNum]][0];
       
   446          fBlockAExist = 1;
       
   447          if ( yCoordMB == 0 || fBBlockOut ) {
       
   448             /* B MB is out of this VP */
       
   449             blockB = aicData->midGrey<<3 /**8*/;
       
   450          }
       
   451          else {
       
   452             blockB = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth+aicData->Xpos[blockNum]][aicData->Ztab[blockNum]][0];
       
   453          }
       
   454          blockC = aicData->midGrey<<3 /**8*/;
       
   455          fBlockCExist = 0;
       
   456       }
       
   457       else if ( xCoordMB == 0 || fLeftMBMissing ) {
       
   458          /* left edge of VOP or VP, or MB on left not valid */
       
   459          blockA = aicData->midGrey<<3 /**8*/;
       
   460          fBlockAExist = 0;
       
   461          if ( xCoordMB == 0 || fBBlockOut ) {
       
   462             /* B MB is out of this VP */
       
   463             blockB = aicData->midGrey<<3 /**8*/;
       
   464          }
       
   465          else {
       
   466             blockB = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth+aicData->Xpos[blockNum]][aicData->Ztab[blockNum]][0];
       
   467          }
       
   468          blockC = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth][aicData->Ytab[blockNum]][0];
       
   469          fBlockCExist = 1;
       
   470       }
       
   471       else {
       
   472          /* Something else */
       
   473          blockA = aicData->dcStore[currDCStoreIndex+aicData->Xpos[blockNum]][aicData->Xtab[blockNum]][0];
       
   474          if ( fBBlockOut ) {
       
   475             /* B MB is out of this VP */
       
   476             blockB = aicData->midGrey<<3 /**8*/;
       
   477          }
       
   478          else {
       
   479             blockB = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth+aicData->Xpos[blockNum]][aicData->Ztab[blockNum]][0];
       
   480          }
       
   481          blockC = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth][aicData->Ytab[blockNum]][0];
       
   482          fBlockAExist = fBlockCExist = 1;
       
   483       }
       
   484       break;
       
   485    case 1 : 
       
   486       /* Y1 block */
       
   487 
       
   488       /* Prediction block A (left) always available */
       
   489       blockA = aicData->dcStore[currDCStoreIndex+aicData->Xpos[blockNum]][aicData->Xtab[blockNum]][0];
       
   490       fBlockAExist = 1;
       
   491       /* Prediction blocks B (above-left) and C (above) */
       
   492       if ( yCoordMB == 0 || fTopMBMissing ) {
       
   493          /* top row of VOP or VP */
       
   494          blockB = aicData->midGrey<<3 /**8*/;
       
   495          blockC = aicData->midGrey<<3 /**8*/;
       
   496          fBlockCExist = 0;
       
   497       }
       
   498       else {
       
   499          blockB = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth+aicData->Xpos[blockNum]][aicData->Ztab[blockNum]][0];
       
   500          blockC = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth][aicData->Ytab[blockNum]][0];
       
   501          fBlockCExist = 1;
       
   502       }
       
   503       break;
       
   504    case 2 :
       
   505       /* Y2 block */
       
   506 
       
   507       /* Prediction blocks A (left) and B (above-left) */
       
   508       if ( xCoordMB == 0 || fLeftMBMissing ) {
       
   509          /* left edge or first MB in VP */
       
   510          blockA = aicData->midGrey<<3 /**8*/;
       
   511          blockB = aicData->midGrey<<3 /**8*/;
       
   512          fBlockAExist = 0;
       
   513       }
       
   514       else {
       
   515          blockA = aicData->dcStore[currDCStoreIndex+aicData->Xpos[blockNum]][aicData->Xtab[blockNum]][0];
       
   516          blockB = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth+aicData->Xpos[blockNum]][aicData->Ztab[blockNum]][0];
       
   517          fBlockAExist = 1;
       
   518       }
       
   519       /* Prediction block C (above) always available */
       
   520       blockC = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth][aicData->Ytab[blockNum]][0];
       
   521       fBlockCExist = 1;
       
   522       break;
       
   523    case 3 :
       
   524       /* Y3 block */
       
   525 
       
   526       /* Prediction block A (left) always available */
       
   527       blockA = aicData->dcStore[currDCStoreIndex+aicData->Xpos[blockNum]][aicData->Xtab[blockNum]][0];
       
   528       /* Prediction block B (above-left) always available */
       
   529       blockB = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth+aicData->Xpos[blockNum]][aicData->Ztab[blockNum]][0];
       
   530       /* Prediction block C (above) always available */
       
   531       blockC = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth][aicData->Ytab[blockNum]][0];
       
   532       fBlockAExist = fBlockCExist = 1;
       
   533       break;
       
   534    }
       
   535 
       
   536 
       
   537 
       
   538 
       
   539    gradHor = blockB - blockC;
       
   540    gradVer = blockA - blockB;
       
   541 
       
   542    if ((abs(gradVer)) < (abs(gradHor))) {
       
   543       /* Vertical prediction (from C) */
       
   544       predDC = blockC;
       
   545       fVertical = 1;
       
   546    }
       
   547    else {
       
   548       /* Horizontal prediction (from A) */
       
   549       predDC = blockA;
       
   550       fVertical = 0;
       
   551    }
       
   552 
       
   553    /* Now reconstruct the DC coefficient */
       
   554    tempDCScaler = aicDCScaler(QP,(blockNum<4)?1:2);
       
   555    qBlock[0] = (u_int8) (qBlock[0] + (predDC + tempDCScaler/2) / tempDCScaler);
       
   556 
       
   557    /* Do AC prediction if required */
       
   558    if (aicData->ACpred_flag == 1) {
       
   559 
       
   560       /* Do inverse zigzag-scanning */
       
   561       if (fVertical) {
       
   562          for (m = 0; m < 64; m++) {
       
   563             pcoeff[m] = qBlock[zigzag_h[m]];
       
   564          }
       
   565       }
       
   566       else { /* horizontal prediction */
       
   567          for (m = 0; m < 64; m++) {
       
   568             pcoeff[m] = qBlock[zigzag_v[m]];
       
   569          }
       
   570       }
       
   571    
       
   572 
       
   573 
       
   574       /* AC predictions */
       
   575       if ( !fVertical && fBlockAExist ) {
       
   576          /* prediction from A */
       
   577          for (m = 8; m < 15; m++) {
       
   578             predA[m-8] = compensateQPDiff(((aicData->dcStore[currDCStoreIndex+aicData->Xpos[blockNum]][aicData->Xtab[blockNum]][m]) * 2 * (aicData->qpStore[currDCStoreIndex+aicData->Xpos[blockNum]])), (QP<<1));
       
   579          }
       
   580       }
       
   581       else if ( fVertical && fBlockCExist ) {
       
   582          /* prediction from C */
       
   583          for (m = 1; m < 8; m++) {
       
   584             predC[m-1] = compensateQPDiff(((aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth][aicData->Ytab[blockNum]][m]) * 2 * (aicData->qpStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth])), (QP<<1));
       
   585          }
       
   586       }
       
   587       else {
       
   588          /* Prediction not possible */
       
   589          if ( fVertical ) {
       
   590             resetPredRow(predC);
       
   591          }
       
   592          else {
       
   593             resetPredRow(predA);
       
   594          }
       
   595       }
       
   596 
       
   597 
       
   598 
       
   599       /* AC coefficients reconstruction*/
       
   600       if (fVertical) { /* Vertical, top row of block C */
       
   601          for (m = 0; m < 7; m++) {
       
   602             qBlock[zigzag[(m+1)*8]] = pcoeff[(m+1)*8];
       
   603          }
       
   604          for (m = 1; m < 8; m++) {
       
   605             qBlock[zigzag[m]] = pcoeff[m] + predC[m-1];
       
   606          }
       
   607       }
       
   608       else { /* Horizontal, left column of block A */
       
   609          for (m = 0; m < 7; m++) {
       
   610             qBlock[zigzag[(m+1)*8]] = pcoeff[(m+1)*8] + predA[m];
       
   611          }
       
   612          for (m = 1; m < 8; m++) {
       
   613             qBlock[zigzag[m]] = pcoeff[m];
       
   614          }
       
   615       }
       
   616 
       
   617       /* Copy the rest of the coefficients back to qBlock */
       
   618       for (m = 1; m < 8; m++) {
       
   619          for (n = 1; n < 8; n++) {
       
   620             qBlock[zigzag[m*8+n]] = pcoeff[m*8+n];
       
   621          }
       
   622       }
       
   623    }
       
   624 
       
   625 }
       
   626 
       
   627 // End of file