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
FindHalfPelMB(VideoEncData * video,UChar * cur,MOT * mot,UChar * ncand,Int xpos,Int ypos,Int * xhmin,Int * yhmin,Int hp_guess)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
FindHalfPelBlk(VideoEncData * video,UChar * cur,MOT * mot,Int sad16,UChar * ncand8[],UChar * mode,Int xpos,Int ypos,Int * xhmin,Int * yhmin,UChar * hp_mem)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