diff options
Diffstat (limited to 'media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp')
-rw-r--r-- | media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp new file mode 100644 index 0000000..319c76f --- /dev/null +++ b/media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp @@ -0,0 +1,287 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 1998-2009 PacketVideo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ +#include "mp4def.h" +#include "mp4enc_lib.h" +#include "mp4lib_int.h" +#include "m4venc_oscl.h" + +/* 3/29/01 fast half-pel search based on neighboring guess */ +/* value ranging from 0 to 4, high complexity (more accurate) to + low complexity (less accurate) */ +#define HP_DISTANCE_TH 2 /* half-pel distance threshold */ + +#define PREF_16_VEC 129 /* 1MV bias versus 4MVs*/ + +#ifdef __cplusplus +extern "C" +{ +#endif + void GenerateSearchRegion(UChar *searchPadding, UChar *ref, Int width, Int height, + Int ilow, Int ihigh, Int jlow, Int jhigh); + + void InterpDiag(UChar *prev, Int lx, UChar *pred_block); + void InterpHorz(UChar *prev, Int lx, UChar *pred_block); + void InterpVert(UChar *prev, Int lx, UChar *pred_block); +#ifdef __cplusplus +} +#endif + + +const static Int distance_tab[9][9] = /* [hp_guess][k] */ +{ + {0, 1, 1, 1, 1, 1, 1, 1, 1}, + {1, 0, 1, 2, 3, 4, 3, 2, 1}, + {1, 0, 0, 0, 1, 2, 3, 2, 1}, + {1, 2, 1, 0, 1, 2, 3, 4, 3}, + {1, 2, 1, 0, 0, 0, 1, 2, 3}, + {1, 4, 3, 2, 1, 0, 1, 2, 3}, + {1, 2, 3, 2, 1, 0, 0, 0, 1}, + {1, 2, 3, 4, 3, 2, 1, 0, 1}, + {1, 0, 1, 2, 3, 2, 1, 0, 0} +}; + + +/*===================================================================== + Function: FindHalfPelMB + Date: 10/7/2000 + Purpose: Find half pel resolution MV surrounding the full-pel MV +=====================================================================*/ + +void FindHalfPelMB(VideoEncData *video, UChar *cur, MOT *mot, UChar *ncand, + Int xpos, Int ypos, Int *xhmin, Int *yhmin, Int hp_guess) +{ +// hp_mem = ULong *vertArray; /* 20x17 */ +// ULong *horzArray; /* 20x16 */ +// ULong *diagArray; /* 20x17 */ + Int dmin, d; + + Int xh, yh; + Int k, kmin = 0; + Int imin, jmin, ilow, jlow; + Int h263_mode = video->encParams->H263_Enabled; /* 3/29/01 */ + Int in_range[9] = {0, 1, 1, 1, 1, 1, 1, 1, 1}; /* 3/29/01 */ + Int range = video->encParams->SearchRange; + Int lx = video->currVop->pitch; + Int width = video->currVop->width; /* padding */ + Int height = video->vol[video->currLayer]->height; + Int(**SAD_MB_HalfPel)(UChar*, UChar*, Int, void*) = + video->functionPointer->SAD_MB_HalfPel; + void *extra_info = video->sad_extra_info; + + Int next_hp_pos[9][2] = {{0, 0}, {2, 0}, {1, 1}, {0, 2}, { -1, 1}, { -2, 0}, { -1, -1}, {0, -2}, {0, -1}}; + Int next_ncand[9] = {0, 1 , lx, lx, 0, -1, -1, -lx, -lx}; + + cur = video->currYMB; + + /**************** check range ***************************/ + /* 3/29/01 */ + imin = xpos + (mot[0].x >> 1); + jmin = ypos + (mot[0].y >> 1); + ilow = xpos - range; + jlow = ypos - range; + + if (!h263_mode) + { + if (imin <= -15 || imin == ilow) + in_range[1] = in_range[7] = in_range[8] = 0; + else if (imin >= width - 1) + in_range[3] = in_range[4] = in_range[5] = 0; + if (jmin <= -15 || jmin == jlow) + in_range[1] = in_range[2] = in_range[3] = 0; + else if (jmin >= height - 1) + in_range[5] = in_range[6] = in_range[7] = 0; + } + else + { + if (imin <= 0 || imin == ilow) + in_range[1] = in_range[7] = in_range[8] = 0; + else if (imin >= width - 16) + in_range[3] = in_range[4] = in_range[5] = 0; + if (jmin <= 0 || jmin == jlow) + in_range[1] = in_range[2] = in_range[3] = 0; + else if (jmin >= height - 16) + in_range[5] = in_range[6] = in_range[7] = 0; + } + + xhmin[0] = 0; + yhmin[0] = 0; + dmin = mot[0].sad; + + xh = 0; + yh = -1; + ncand -= lx; /* initial position */ + + for (k = 2; k <= 8; k += 2) + { + if (distance_tab[hp_guess][k] < HP_DISTANCE_TH) + { + if (in_range[k]) + { + d = (*(SAD_MB_HalfPel[((yh&1)<<1)+(xh&1)]))(ncand, cur, (dmin << 16) | lx, extra_info); + + if (d < dmin) + { + dmin = d; + xhmin[0] = xh; + yhmin[0] = yh; + kmin = k; + } + else if (d == dmin && + 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])) + { + xhmin[0] = xh; + yhmin[0] = yh; + kmin = k; + } + + } + } + xh += next_hp_pos[k][0]; + yh += next_hp_pos[k][1]; + ncand += next_ncand[k]; + + if (k == 8) + { + if (xhmin[0] != 0 || yhmin[0] != 0) + { + k = -1; + hp_guess = kmin; + } + } + } + + mot[0].sad = dmin; + mot[0].x += xhmin[0]; + mot[0].y += yhmin[0]; + + return ; +} + +#ifndef NO_INTER4V +/*===================================================================== + Function: FindHalfPelBlk + Date: 10/7/2000 + Purpose: Find half pel resolution MV surrounding the full-pel MV + And decide between 1MV or 4MV mode +=====================================================================*/ +///// THIS FUNCTION IS NOT WORKING!!! NEED TO BE RIVISITED + +Int FindHalfPelBlk(VideoEncData *video, UChar *cur, MOT *mot, Int sad16, UChar *ncand8[], + UChar *mode, Int xpos, Int ypos, Int *xhmin, Int *yhmin, UChar *hp_mem) +{ + Int k, comp; + Int xh, yh;//, xhmin, yhmin; + Int imin, jmin, ilow, jlow; + Int height; + UChar *cand, *cur8; + UChar *hmem;//[17*17]; /* half-pel memory */ + Int d, dmin, sad8; + Int lx = video->currVop->pitch; + Int width = video->currVop->width; /* , padding */ + Int(*SAD_Blk_HalfPel)(UChar*, UChar*, Int, Int, Int, Int, Int, void*) = video->functionPointer->SAD_Blk_HalfPel; + void *extra_info = video->sad_extra_info; + Int in_range[8]; /* 3/29/01 */ + Int range = video->encParams->SearchRange; + Int swidth; + Int next_hp_pos[8][2] = {{1, 0}, {1, 0}, {0, 1}, {0, 1}, { -1, 0}, { -1, 0}, {0, -1}, {0, -1}}; + + height = video->vol[video->currLayer]->height; + + hmem = hp_mem; + sad8 = 0; + for (comp = 0; comp < 4; comp++) + { +#ifdef _SAD_STAT + num_HP_Blk++; +#endif + /**************** check range ***************************/ + /* 3/29/01 */ + M4VENC_MEMSET(in_range, 1, sizeof(Int) << 3); + imin = xpos + ((comp & 1) << 3) + (mot[comp+1].x >> 1); + jmin = ypos + ((comp & 2) << 2) + (mot[comp+1].y >> 1); + ilow = xpos + ((comp & 1) << 3) - range; + jlow = ypos + ((comp & 2) << 2) - range; + + if (imin <= -15 || imin == ilow) + in_range[0] = in_range[6] = in_range[7] = 0; + else if (imin >= width - 1) + in_range[2] = in_range[3] = in_range[4] = 0; + + if (jmin <= -15 || jmin == jlow) + in_range[0] = in_range[1] = in_range[2] = 0; + else if (jmin >= height - 1) + in_range[4] = in_range[5] = in_range[6] = 0; + + /**************** half-pel search ***********************/ + cur8 = cur + ((comp & 1) << 3) + ((comp & 2) << 2) * width ; + + /* generate half-pel search region */ + { + cand = ncand8[comp+1]; + swidth = lx; + } + + xhmin[comp+1] = 0; + yhmin[comp+1] = 0; + dmin = mot[comp+1].sad; + + xh = -1; + yh = -1; + for (k = 0; k < 8; k++) + { + if (in_range[k]) + { + d = (*SAD_Blk_HalfPel)(cand, cur8, dmin, lx, swidth, xh, yh, extra_info); + + if (d < dmin) + { + dmin = d; + xhmin[comp+1] = xh; + yhmin[comp+1] = yh; + } + } + xh += next_hp_pos[k][0]; + yh += next_hp_pos[k][1]; + } + /********************************************/ + mot[comp+1].x += xhmin[comp+1]; + mot[comp+1].y += yhmin[comp+1]; + mot[comp+1].sad = dmin; + sad8 += dmin; + + if (sad8 >= sad16 - PREF_16_VEC) + { + *mode = MODE_INTER; + for (k = 1; k <= 4; k++) + { + mot[k].sad = (mot[0].sad + 2) >> 2; + mot[k].x = mot[0].x; + mot[k].y = mot[0].y; + } + return sad8; + } + + hmem += (10 * 10); + } + + *mode = MODE_INTER4V; + + return sad8; +} +#endif /* NO_INTER4V */ + |