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