summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp')
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp287
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 */
+