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