findhalfpel.cpp revision 59f566c4ec3dfc097ad8163523e522280b27e5c3
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
31extern "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
45const 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
65void 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
184Int 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