Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 #include <string.h>
     19 
     20 #include "avclib_common.h"
     21 
     22 OSCL_EXPORT_REF void InitNeighborAvailability(AVCCommonObj *video, int mbNum)
     23 {
     24     int PicWidthInMbs = video->PicWidthInMbs;
     25 
     26     // do frame-only and postpone intraAvail calculattion
     27     video->mbAddrA = mbNum - 1;
     28     video->mbAddrB = mbNum - PicWidthInMbs;
     29     video->mbAddrC = mbNum - PicWidthInMbs + 1;
     30     video->mbAddrD = mbNum - PicWidthInMbs - 1;
     31 
     32     video->mbAvailA = video->mbAvailB = video->mbAvailC = video->mbAvailD = 0;
     33     if (video->mb_x)
     34     {
     35         video->mbAvailA = (video->mblock[video->mbAddrA].slice_id == video->currMB->slice_id);
     36         if (video->mb_y)
     37         {
     38             video->mbAvailD = (video->mblock[video->mbAddrD].slice_id == video->currMB->slice_id);
     39         }
     40     }
     41 
     42     if (video->mb_y)
     43     {
     44         video->mbAvailB = (video->mblock[video->mbAddrB].slice_id == video->currMB->slice_id);
     45         if (video->mb_x < (PicWidthInMbs - 1))
     46         {
     47             video->mbAvailC = (video->mblock[video->mbAddrC].slice_id == video->currMB->slice_id);
     48         }
     49     }
     50     return ;
     51 }
     52 
     53 bool mb_is_available(AVCMacroblock *mblock, uint PicSizeInMbs, int mbAddr, int currMbAddr)
     54 {
     55     if (mbAddr < 0 || mbAddr >= (int)PicSizeInMbs)
     56     {
     57         return FALSE;
     58     }
     59 
     60     if (mblock[mbAddr].slice_id != mblock[currMbAddr].slice_id)
     61     {
     62         return FALSE;
     63     }
     64 
     65     return TRUE;
     66 }
     67 
     68 OSCL_EXPORT_REF int predict_nnz(AVCCommonObj *video, int i, int j)
     69 {
     70     int pred_nnz = 0;
     71     int cnt      = 1;
     72     AVCMacroblock *tempMB;
     73 
     74     /* left block */
     75     /*getLuma4x4Neighbour(video, mb_nr, i, j, -1, 0, &pix);
     76     leftMB = video->mblock + pix.mb_addr; */
     77     /* replace the above with below (won't work for field decoding),  1/19/04 */
     78 
     79     if (i)
     80     {
     81         pred_nnz = video->currMB->nz_coeff[(j<<2)+i-1];
     82     }
     83     else
     84     {
     85         if (video->mbAvailA)
     86         {
     87             tempMB = video->mblock + video->mbAddrA;
     88             pred_nnz = tempMB->nz_coeff[(j<<2)+3];
     89         }
     90         else
     91         {
     92             cnt = 0;
     93         }
     94     }
     95 
     96 
     97     /* top block */
     98     /*getLuma4x4Neighbour(video, mb_nr, i, j, 0, -1, &pix);
     99     topMB = video->mblock + pix.mb_addr;*/
    100     /* replace the above with below (won't work for field decoding),  1/19/04 */
    101 
    102     if (j)
    103     {
    104         pred_nnz += video->currMB->nz_coeff[((j-1)<<2)+i];
    105         cnt++;
    106     }
    107     else
    108     {
    109         if (video->mbAvailB)
    110         {
    111             tempMB = video->mblock + video->mbAddrB;
    112             pred_nnz += tempMB->nz_coeff[12+i];
    113             cnt++;
    114         }
    115     }
    116 
    117 
    118     if (cnt == 2)
    119     {
    120         pred_nnz = (pred_nnz + 1) >> 1;
    121     }
    122 
    123     return pred_nnz;
    124 
    125 }
    126 
    127 
    128 OSCL_EXPORT_REF int predict_nnz_chroma(AVCCommonObj *video, int i, int j)
    129 {
    130     int pred_nnz = 0;
    131     int cnt      = 1;
    132     AVCMacroblock *tempMB;
    133 
    134     /* left block */
    135     /*getChroma4x4Neighbour(video, mb_nr, i%2, j-4, -1, 0, &pix);
    136     leftMB = video->mblock + pix.mb_addr;*/
    137     /* replace the above with below (won't work for field decoding),  1/19/04 */
    138     if (i&1)
    139     {
    140         pred_nnz = video->currMB->nz_coeff[(j<<2)+i-1];
    141 
    142     }
    143     else
    144     {
    145         if (video->mbAvailA)
    146         {
    147             tempMB = video->mblock + video->mbAddrA;
    148             pred_nnz = tempMB->nz_coeff[(j<<2)+i+1];
    149         }
    150         else
    151         {
    152             cnt = 0;
    153         }
    154     }
    155 
    156 
    157     /* top block */
    158     /*getChroma4x4Neighbour(video, mb_nr, i%2, j-4, 0, -1, &pix);
    159     topMB = video->mblock + pix.mb_addr;*/
    160     /* replace the above with below (won't work for field decoding),  1/19/04 */
    161 
    162     if (j&1)
    163     {
    164         pred_nnz += video->currMB->nz_coeff[((j-1)<<2)+i];
    165         cnt++;
    166     }
    167     else
    168     {
    169         if (video->mbAvailB)
    170         {
    171             tempMB = video->mblock + video->mbAddrB;
    172             pred_nnz += tempMB->nz_coeff[20+i];
    173             cnt++;
    174         }
    175 
    176     }
    177 
    178     if (cnt == 2)
    179     {
    180         pred_nnz = (pred_nnz + 1) >> 1;
    181     }
    182 
    183     return pred_nnz;
    184 }
    185 
    186 OSCL_EXPORT_REF void GetMotionVectorPredictor(AVCCommonObj *video, int encFlag)
    187 {
    188     AVCMacroblock *currMB = video->currMB;
    189     AVCMacroblock *MB_A, *MB_B, *MB_C, *MB_D;
    190     int block_x, block_y, block_x_1, block_y_1, new_block_x;
    191     int mbPartIdx, subMbPartIdx, offset_indx;
    192     int16 *mv, pmv_x, pmv_y;
    193     int nmSubMbHeight, nmSubMbWidth, mbPartIdx_X, mbPartIdx_Y;
    194     int avail_a, avail_b, avail_c;
    195     const static uint32 C = 0x5750;
    196     int i, j, offset_MbPart_indx, refIdxLXA, refIdxLXB, refIdxLXC = 0, curr_ref_idx;
    197     int pmv_A_x, pmv_B_x, pmv_C_x = 0, pmv_A_y, pmv_B_y, pmv_C_y = 0;
    198 
    199     /* we have to take care of Intra/skip blocks somewhere, i.e. set MV to  0 and set ref to -1! */
    200     /* we have to populate refIdx as well */
    201 
    202 
    203     MB_A = &video->mblock[video->mbAddrA];
    204     MB_B = &video->mblock[video->mbAddrB];
    205 
    206 
    207     if (currMB->mbMode == AVC_SKIP /* && !encFlag */) /* only for decoder */
    208     {
    209         currMB->ref_idx_L0[0] = currMB->ref_idx_L0[1] = currMB->ref_idx_L0[2] = currMB->ref_idx_L0[3] = 0;
    210         if (video->mbAvailA && video->mbAvailB)
    211         {
    212             if ((MB_A->ref_idx_L0[1] == 0 && MB_A->mvL0[3] == 0) ||
    213                     (MB_B->ref_idx_L0[2] == 0 && MB_B->mvL0[12] == 0))
    214             {
    215                 memset(currMB->mvL0, 0, sizeof(int32)*16);
    216                 return;
    217             }
    218         }
    219         else
    220         {
    221             memset(currMB->mvL0, 0, sizeof(int32)*16);
    222             return;
    223         }
    224         video->mvd_l0[0][0][0] = 0;
    225         video->mvd_l0[0][0][1] = 0;
    226     }
    227 
    228     MB_C = &video->mblock[video->mbAddrC];
    229     MB_D = &video->mblock[video->mbAddrD];
    230 
    231     offset_MbPart_indx = 0;
    232     for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
    233     {
    234         offset_indx = 0;
    235         nmSubMbHeight = currMB->SubMbPartHeight[mbPartIdx] >> 2;
    236         nmSubMbWidth = currMB->SubMbPartWidth[mbPartIdx] >> 2;
    237         mbPartIdx_X = ((mbPartIdx + offset_MbPart_indx) & 1) << 1;
    238         mbPartIdx_Y = (mbPartIdx + offset_MbPart_indx) & 2;
    239 
    240         for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
    241         {
    242             block_x = mbPartIdx_X + ((subMbPartIdx + offset_indx) & 1);
    243             block_y = mbPartIdx_Y + (((subMbPartIdx + offset_indx) >> 1) & 1);
    244 
    245             block_x_1 = block_x - 1;
    246             block_y_1 = block_y - 1;
    247             refIdxLXA = refIdxLXB = refIdxLXC = -1;
    248             pmv_A_x = pmv_A_y = pmv_B_x = pmv_B_y = pmv_C_x = pmv_C_y = 0;
    249 
    250             if (block_x)
    251             {
    252                 avail_a = 1;
    253                 refIdxLXA = currMB->ref_idx_L0[(block_y & 2) + (block_x_1 >> 1)];
    254                 mv = (int16*)(currMB->mvL0 + (block_y << 2) + block_x_1);
    255                 pmv_A_x = *mv++;
    256                 pmv_A_y = *mv;
    257             }
    258             else
    259             {
    260                 avail_a = video->mbAvailA;
    261                 if (avail_a)
    262                 {
    263                     refIdxLXA = MB_A->ref_idx_L0[(block_y & 2) + 1];
    264                     mv = (int16*)(MB_A->mvL0 + (block_y << 2) + 3);
    265                     pmv_A_x = *mv++;
    266                     pmv_A_y = *mv;
    267                 }
    268             }
    269 
    270             if (block_y)
    271             {
    272                 avail_b = 1;
    273                 refIdxLXB = currMB->ref_idx_L0[(block_y_1 & 2) + (block_x >> 1)];
    274                 mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + block_x);
    275                 pmv_B_x = *mv++;
    276                 pmv_B_y = *mv;
    277             }
    278 
    279             else
    280             {
    281                 avail_b = video->mbAvailB;
    282                 if (avail_b)
    283                 {
    284                     refIdxLXB = MB_B->ref_idx_L0[2 + (block_x >> 1)];
    285                     mv = (int16*)(MB_B->mvL0 + 12 + block_x);
    286                     pmv_B_x = *mv++;
    287                     pmv_B_y = *mv;
    288                 }
    289             }
    290 
    291             new_block_x = block_x + (currMB->SubMbPartWidth[mbPartIdx] >> 2) - 1;
    292             avail_c = (C >> ((block_y << 2) + new_block_x)) & 0x1;
    293 
    294             if (avail_c)
    295             {
    296                 /* it guaranteed that block_y > 0 && new_block_x<3 ) */
    297                 refIdxLXC = currMB->ref_idx_L0[(block_y_1 & 2) + ((new_block_x+1) >> 1)];
    298                 mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + (new_block_x + 1));
    299                 pmv_C_x = *mv++;
    300                 pmv_C_y = *mv;
    301             }
    302             else
    303             {
    304                 if (block_y == 0 && new_block_x < 3)
    305                 {
    306                     avail_c = video->mbAvailB;
    307                     if (avail_c)
    308                     {
    309                         refIdxLXC = MB_B->ref_idx_L0[2 + ((new_block_x+1)>>1)];
    310                         mv = (int16*)(MB_B->mvL0 + 12 + (new_block_x + 1));
    311                         pmv_C_x = *mv++;
    312                         pmv_C_y = *mv;
    313                     }
    314                 }
    315                 else if (block_y == 0 && new_block_x == 3)
    316                 {
    317                     avail_c = video->mbAvailC;
    318                     if (avail_c)
    319                     {
    320                         refIdxLXC = MB_C->ref_idx_L0[2];
    321                         mv = (int16*)(MB_C->mvL0 + 12);
    322                         pmv_C_x = *mv++;
    323                         pmv_C_y = *mv;
    324                     }
    325                 }
    326 
    327                 if (avail_c == 0)
    328                 {   /* check D */
    329                     if (block_x && block_y)
    330                     {
    331                         avail_c = 1;
    332                         refIdxLXC =  currMB->ref_idx_L0[(block_y_1 & 2) + (block_x_1 >> 1)];
    333                         mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + block_x_1);
    334                         pmv_C_x = *mv++;
    335                         pmv_C_y = *mv;
    336                     }
    337                     else if (block_y)
    338                     {
    339                         avail_c = video->mbAvailA;
    340                         if (avail_c)
    341                         {
    342                             refIdxLXC =  MB_A->ref_idx_L0[(block_y_1 & 2) + 1];
    343                             mv = (int16*)(MB_A->mvL0 + (block_y_1 << 2) + 3);
    344                             pmv_C_x = *mv++;
    345                             pmv_C_y = *mv;
    346                         }
    347                     }
    348                     else if (block_x)
    349                     {
    350                         avail_c = video->mbAvailB;
    351                         if (avail_c)
    352                         {
    353                             refIdxLXC = MB_B->ref_idx_L0[2 + (block_x_1 >> 1)];
    354                             mv = (int16*)(MB_B->mvL0 + 12 + block_x_1);
    355                             pmv_C_x = *mv++;
    356                             pmv_C_y = *mv;
    357                         }
    358                     }
    359                     else
    360                     {
    361                         avail_c = video->mbAvailD;
    362                         if (avail_c)
    363                         {
    364                             refIdxLXC = MB_D->ref_idx_L0[3];
    365                             mv = (int16*)(MB_D->mvL0 + 15);
    366                             pmv_C_x = *mv++;
    367                             pmv_C_y = *mv;
    368                         }
    369                     }
    370                 }
    371             }
    372 
    373             offset_indx = currMB->SubMbPartWidth[mbPartIdx] >> 3;
    374 
    375             curr_ref_idx = currMB->ref_idx_L0[(block_y & 2) + (block_x >> 1)];
    376 
    377             if (avail_a && !(avail_b || avail_c))
    378             {
    379                 pmv_x = pmv_A_x;
    380                 pmv_y = pmv_A_y;
    381             }
    382             else if (((curr_ref_idx == refIdxLXA) + (curr_ref_idx == refIdxLXB) + (curr_ref_idx == refIdxLXC)) == 1)
    383             {
    384                 if (curr_ref_idx == refIdxLXA)
    385                 {
    386                     pmv_x = pmv_A_x;
    387                     pmv_y = pmv_A_y;
    388                 }
    389                 else if (curr_ref_idx == refIdxLXB)
    390                 {
    391                     pmv_x = pmv_B_x;
    392                     pmv_y = pmv_B_y;
    393                 }
    394                 else
    395                 {
    396                     pmv_x = pmv_C_x;
    397                     pmv_y = pmv_C_y;
    398                 }
    399             }
    400             else
    401             {
    402                 pmv_x = AVC_MEDIAN(pmv_A_x, pmv_B_x, pmv_C_x);
    403                 pmv_y = AVC_MEDIAN(pmv_A_y, pmv_B_y, pmv_C_y);
    404             }
    405 
    406             /* overwrite if special case */
    407             if (currMB->NumMbPart == 2)
    408             {
    409                 if (currMB->MbPartWidth == 16)
    410                 {
    411                     if (mbPartIdx == 0)
    412                     {
    413                         if (refIdxLXB == curr_ref_idx)
    414                         {
    415                             pmv_x = pmv_B_x;
    416                             pmv_y = pmv_B_y;
    417                         }
    418                     }
    419                     else if (refIdxLXA == curr_ref_idx)
    420                     {
    421                         pmv_x = pmv_A_x;
    422                         pmv_y = pmv_A_y;
    423                     }
    424                 }
    425                 else
    426                 {
    427                     if (mbPartIdx == 0)
    428                     {
    429                         if (refIdxLXA == curr_ref_idx)
    430                         {
    431                             pmv_x = pmv_A_x;
    432                             pmv_y = pmv_A_y;
    433                         }
    434                     }
    435                     else if (refIdxLXC == curr_ref_idx)
    436                     {
    437                         pmv_x = pmv_C_x;
    438                         pmv_y = pmv_C_y;
    439                     }
    440                 }
    441             }
    442 
    443             mv = (int16*)(currMB->mvL0 + block_x + (block_y << 2));
    444 
    445             if (encFlag) /* calculate residual MV video->mvd_l0 */
    446             {
    447                 video->mvd_l0[mbPartIdx][subMbPartIdx][0] = *mv++ - pmv_x;
    448                 video->mvd_l0[mbPartIdx][subMbPartIdx][1] = *mv++ - pmv_y;
    449             }
    450             else    /* calculate original MV currMB->mvL0 */
    451             {
    452                 pmv_x += video->mvd_l0[mbPartIdx][subMbPartIdx][0];
    453                 pmv_y += video->mvd_l0[mbPartIdx][subMbPartIdx][1];
    454 
    455                 for (i = 0; i < nmSubMbHeight; i++)
    456                 {
    457                     for (j = 0; j < nmSubMbWidth; j++)
    458                     {
    459                         *mv++ = pmv_x;
    460                         *mv++ = pmv_y;
    461                     }
    462                     mv += (8 - (j << 1));
    463                 }
    464             }
    465         }
    466         offset_MbPart_indx = currMB->MbPartWidth >> 4;
    467 
    468     }
    469 }
    470 
    471 
    472