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 "mp4def.h"
     19 #include "mp4enc_lib.h"
     20 #include "mp4lib_int.h"
     21 #include "m4venc_oscl.h"
     22 
     23 /* 3/29/01 fast half-pel search based on neighboring guess */
     24 /* value ranging from 0 to 4, high complexity (more accurate) to
     25    low complexity (less accurate) */
     26 #define HP_DISTANCE_TH      2  /* half-pel distance threshold */
     27 
     28 #define PREF_16_VEC 129     /* 1MV bias versus 4MVs*/
     29 
     30 #ifdef __cplusplus
     31 extern "C"
     32 {
     33 #endif
     34     void GenerateSearchRegion(UChar *searchPadding, UChar *ref, Int width, Int height,
     35     Int ilow, Int ihigh, Int jlow, Int jhigh);
     36 
     37     void InterpDiag(UChar *prev, Int lx, UChar *pred_block);
     38     void InterpHorz(UChar *prev, Int lx, UChar *pred_block);
     39     void InterpVert(UChar *prev, Int lx, UChar *pred_block);
     40 #ifdef __cplusplus
     41 }
     42 #endif
     43 
     44 
     45 const static Int distance_tab[9][9] =   /* [hp_guess][k] */
     46 {
     47     {0, 1, 1, 1, 1, 1, 1, 1, 1},
     48     {1, 0, 1, 2, 3, 4, 3, 2, 1},
     49     {1, 0, 0, 0, 1, 2, 3, 2, 1},
     50     {1, 2, 1, 0, 1, 2, 3, 4, 3},
     51     {1, 2, 1, 0, 0, 0, 1, 2, 3},
     52     {1, 4, 3, 2, 1, 0, 1, 2, 3},
     53     {1, 2, 3, 2, 1, 0, 0, 0, 1},
     54     {1, 2, 3, 4, 3, 2, 1, 0, 1},
     55     {1, 0, 1, 2, 3, 2, 1, 0, 0}
     56 };
     57 
     58 
     59 /*=====================================================================
     60     Function:   FindHalfPelMB
     61     Date:       10/7/2000
     62     Purpose:    Find half pel resolution MV surrounding the full-pel MV
     63 =====================================================================*/
     64 
     65 void FindHalfPelMB(VideoEncData *video, UChar *cur, MOT *mot, UChar *ncand,
     66                    Int xpos, Int ypos, Int *xhmin, Int *yhmin, Int hp_guess)
     67 {
     68 //  hp_mem = ULong *vertArray; /* 20x17 */
     69 //           ULong *horzArray; /* 20x16 */
     70 //           ULong *diagArray; /* 20x17 */
     71     Int dmin, d;
     72 
     73     Int xh, yh;
     74     Int k, kmin = 0;
     75     Int imin, jmin, ilow, jlow;
     76     Int h263_mode = video->encParams->H263_Enabled; /*  3/29/01 */
     77     Int in_range[9] = {0, 1, 1, 1, 1, 1, 1, 1, 1}; /*  3/29/01 */
     78     Int range = video->encParams->SearchRange;
     79     Int lx = video->currVop->pitch;
     80     Int width = video->currVop->width; /*  padding */
     81     Int height = video->vol[video->currLayer]->height;
     82     Int(**SAD_MB_HalfPel)(UChar*, UChar*, Int, void*) =
     83         video->functionPointer->SAD_MB_HalfPel;
     84     void *extra_info = video->sad_extra_info;
     85 
     86     Int next_hp_pos[9][2] = {{0, 0}, {2, 0}, {1, 1}, {0, 2}, { -1, 1}, { -2, 0}, { -1, -1}, {0, -2}, {0, -1}};
     87     Int next_ncand[9] = {0, 1 , lx, lx, 0, -1, -1, -lx, -lx};
     88 
     89     cur = video->currYMB;
     90 
     91     /**************** check range ***************************/
     92     /*  3/29/01 */
     93     imin = xpos + (mot[0].x >> 1);
     94     jmin = ypos + (mot[0].y >> 1);
     95     ilow = xpos - range;
     96     jlow = ypos - range;
     97 
     98     if (!h263_mode)
     99     {
    100         if (imin <= -15 || imin == ilow)
    101             in_range[1] = in_range[7] = in_range[8] = 0;
    102         else if (imin >= width - 1)
    103             in_range[3] = in_range[4] = in_range[5] = 0;
    104         if (jmin <= -15 || jmin == jlow)
    105             in_range[1] = in_range[2] = in_range[3] = 0;
    106         else if (jmin >= height - 1)
    107             in_range[5] = in_range[6] = in_range[7] = 0;
    108     }
    109     else
    110     {
    111         if (imin <= 0 || imin == ilow)
    112             in_range[1] = in_range[7] = in_range[8] = 0;
    113         else if (imin >= width - 16)
    114             in_range[3] = in_range[4] = in_range[5] = 0;
    115         if (jmin <= 0 || jmin == jlow)
    116             in_range[1] = in_range[2] = in_range[3] = 0;
    117         else if (jmin >= height - 16)
    118             in_range[5] = in_range[6] = in_range[7] = 0;
    119     }
    120 
    121     xhmin[0] = 0;
    122     yhmin[0] = 0;
    123     dmin = mot[0].sad;
    124 
    125     xh = 0;
    126     yh = -1;
    127     ncand -= lx; /* initial position */
    128 
    129     for (k = 2; k <= 8; k += 2)
    130     {
    131         if (distance_tab[hp_guess][k] < HP_DISTANCE_TH)
    132         {
    133             if (in_range[k])
    134             {
    135                 d = (*(SAD_MB_HalfPel[((yh&1)<<1)+(xh&1)]))(ncand, cur, (dmin << 16) | lx, extra_info);
    136 
    137                 if (d < dmin)
    138                 {
    139                     dmin = d;
    140                     xhmin[0] = xh;
    141                     yhmin[0] = yh;
    142                     kmin = k;
    143                 }
    144                 else if (d == dmin &&
    145                          PV_ABS(mot[0].x + xh) + PV_ABS(mot[0].y + yh) < PV_ABS(mot[0].x + xhmin[0]) + PV_ABS(mot[0].y + yhmin[0]))
    146                 {
    147                     xhmin[0] = xh;
    148                     yhmin[0] = yh;
    149                     kmin = k;
    150                 }
    151 
    152             }
    153         }
    154         xh += next_hp_pos[k][0];
    155         yh += next_hp_pos[k][1];
    156         ncand += next_ncand[k];
    157 
    158         if (k == 8)
    159         {
    160             if (xhmin[0] != 0 || yhmin[0] != 0)
    161             {
    162                 k = -1;
    163                 hp_guess = kmin;
    164             }
    165         }
    166     }
    167 
    168     mot[0].sad = dmin;
    169     mot[0].x += xhmin[0];
    170     mot[0].y += yhmin[0];
    171 
    172     return ;
    173 }
    174 
    175 #ifndef NO_INTER4V
    176 /*=====================================================================
    177     Function:   FindHalfPelBlk
    178     Date:       10/7/2000
    179     Purpose:    Find half pel resolution MV surrounding the full-pel MV
    180                 And decide between 1MV or 4MV mode
    181 =====================================================================*/
    182 ///// THIS FUNCTION IS NOT WORKING!!! NEED TO BE RIVISITED
    183 
    184 Int FindHalfPelBlk(VideoEncData *video, UChar *cur, MOT *mot, Int sad16, UChar *ncand8[],
    185                    UChar *mode, Int xpos, Int ypos, Int *xhmin, Int *yhmin, UChar *hp_mem)
    186 {
    187     Int k, comp;
    188     Int xh, yh;//, xhmin, yhmin;
    189     Int imin, jmin, ilow, jlow;
    190     Int height;
    191     UChar *cand, *cur8;
    192     UChar *hmem;//[17*17]; /* half-pel memory */
    193     Int d, dmin, sad8;
    194     Int lx = video->currVop->pitch;
    195     Int width = video->currVop->width; /* , padding */
    196     Int(*SAD_Blk_HalfPel)(UChar*, UChar*, Int, Int, Int, Int, Int, void*) = video->functionPointer->SAD_Blk_HalfPel;
    197     void *extra_info = video->sad_extra_info;
    198     Int in_range[8]; /*  3/29/01 */
    199     Int range = video->encParams->SearchRange;
    200     Int swidth;
    201     Int next_hp_pos[8][2] = {{1, 0}, {1, 0}, {0, 1}, {0, 1}, { -1, 0}, { -1, 0}, {0, -1}, {0, -1}};
    202 
    203     height = video->vol[video->currLayer]->height;
    204 
    205     hmem = hp_mem;
    206     sad8 = 0;
    207     for (comp = 0; comp < 4; comp++)
    208     {
    209 #ifdef _SAD_STAT
    210         num_HP_Blk++;
    211 #endif
    212         /**************** check range ***************************/
    213         /*  3/29/01 */
    214         M4VENC_MEMSET(in_range, 1, sizeof(Int) << 3);
    215         imin = xpos + ((comp & 1) << 3) + (mot[comp+1].x >> 1);
    216         jmin = ypos + ((comp & 2) << 2) + (mot[comp+1].y >> 1);
    217         ilow = xpos + ((comp & 1) << 3) - range;
    218         jlow = ypos + ((comp & 2) << 2) - range;
    219 
    220         if (imin <= -15 || imin == ilow)
    221             in_range[0] = in_range[6] = in_range[7] = 0;
    222         else if (imin >= width - 1)
    223             in_range[2] = in_range[3] = in_range[4] = 0;
    224 
    225         if (jmin <= -15 || jmin == jlow)
    226             in_range[0] = in_range[1] = in_range[2] = 0;
    227         else if (jmin >= height - 1)
    228             in_range[4] = in_range[5] = in_range[6] = 0;
    229 
    230         /**************** half-pel search ***********************/
    231         cur8 = cur + ((comp & 1) << 3) + ((comp & 2) << 2) * width ;
    232 
    233         /* generate half-pel search region */
    234         {
    235             cand = ncand8[comp+1];
    236             swidth = lx;
    237         }
    238 
    239         xhmin[comp+1] = 0;
    240         yhmin[comp+1] = 0;
    241         dmin = mot[comp+1].sad;
    242 
    243         xh = -1;
    244         yh = -1;
    245         for (k = 0; k < 8; k++)
    246         {
    247             if (in_range[k])
    248             {
    249                 d = (*SAD_Blk_HalfPel)(cand, cur8, dmin, lx, swidth, xh, yh, extra_info);
    250 
    251                 if (d < dmin)
    252                 {
    253                     dmin = d;
    254                     xhmin[comp+1] = xh;
    255                     yhmin[comp+1] = yh;
    256                 }
    257             }
    258             xh += next_hp_pos[k][0];
    259             yh += next_hp_pos[k][1];
    260         }
    261         /********************************************/
    262         mot[comp+1].x += xhmin[comp+1];
    263         mot[comp+1].y += yhmin[comp+1];
    264         mot[comp+1].sad = dmin;
    265         sad8 += dmin;
    266 
    267         if (sad8 >= sad16 - PREF_16_VEC)
    268         {
    269             *mode = MODE_INTER;
    270             for (k = 1; k <= 4; k++)
    271             {
    272                 mot[k].sad = (mot[0].sad + 2) >> 2;
    273                 mot[k].x = mot[0].x;
    274                 mot[k].y = mot[0].y;
    275             }
    276             return sad8;
    277         }
    278 
    279         hmem += (10 * 10);
    280     }
    281 
    282     *mode = MODE_INTER4V;
    283 
    284     return sad8;
    285 }
    286 #endif /* NO_INTER4V */
    287 
    288