11cc31e629e8132df390ae692873c847d1c2f62c0James Dong/* ------------------------------------------------------------------
21cc31e629e8132df390ae692873c847d1c2f62c0James Dong * Copyright (C) 1998-2009 PacketVideo
31cc31e629e8132df390ae692873c847d1c2f62c0James Dong *
41cc31e629e8132df390ae692873c847d1c2f62c0James Dong * Licensed under the Apache License, Version 2.0 (the "License");
51cc31e629e8132df390ae692873c847d1c2f62c0James Dong * you may not use this file except in compliance with the License.
61cc31e629e8132df390ae692873c847d1c2f62c0James Dong * You may obtain a copy of the License at
71cc31e629e8132df390ae692873c847d1c2f62c0James Dong *
81cc31e629e8132df390ae692873c847d1c2f62c0James Dong *      http://www.apache.org/licenses/LICENSE-2.0
91cc31e629e8132df390ae692873c847d1c2f62c0James Dong *
101cc31e629e8132df390ae692873c847d1c2f62c0James Dong * Unless required by applicable law or agreed to in writing, software
111cc31e629e8132df390ae692873c847d1c2f62c0James Dong * distributed under the License is distributed on an "AS IS" BASIS,
121cc31e629e8132df390ae692873c847d1c2f62c0James Dong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
131cc31e629e8132df390ae692873c847d1c2f62c0James Dong * express or implied.
141cc31e629e8132df390ae692873c847d1c2f62c0James Dong * See the License for the specific language governing permissions
151cc31e629e8132df390ae692873c847d1c2f62c0James Dong * and limitations under the License.
161cc31e629e8132df390ae692873c847d1c2f62c0James Dong * -------------------------------------------------------------------
171cc31e629e8132df390ae692873c847d1c2f62c0James Dong */
181cc31e629e8132df390ae692873c847d1c2f62c0James Dong#include "avcenc_lib.h"
191cc31e629e8132df390ae692873c847d1c2f62c0James Dong
201cc31e629e8132df390ae692873c847d1c2f62c0James Dong#define MIN_GOP     1   /* minimum size of GOP, 1/23/01, need to be tested */
211cc31e629e8132df390ae692873c847d1c2f62c0James Dong
221cc31e629e8132df390ae692873c847d1c2f62c0James Dong#define DEFAULT_REF_IDX     0  /* always from the first frame in the reflist */
231cc31e629e8132df390ae692873c847d1c2f62c0James Dong
241cc31e629e8132df390ae692873c847d1c2f62c0James Dong#define ALL_CAND_EQUAL  10  /*  any number greater than 5 will work */
251cc31e629e8132df390ae692873c847d1c2f62c0James Dong
261cc31e629e8132df390ae692873c847d1c2f62c0James Dong
271cc31e629e8132df390ae692873c847d1c2f62c0James Dong/* from TMN 3.2 */
281cc31e629e8132df390ae692873c847d1c2f62c0James Dong#define PREF_NULL_VEC 129   /* zero vector bias */
291cc31e629e8132df390ae692873c847d1c2f62c0James Dong#define PREF_16_VEC 129     /* 1MV bias versus 4MVs*/
301cc31e629e8132df390ae692873c847d1c2f62c0James Dong#define PREF_INTRA  3024//512       /* bias for INTRA coding */
311cc31e629e8132df390ae692873c847d1c2f62c0James Dong
321cc31e629e8132df390ae692873c847d1c2f62c0James Dongconst static int tab_exclude[9][9] =  // [last_loc][curr_loc]
331cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
341cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {0, 0, 0, 0, 0, 0, 0, 0, 0},
351cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {0, 0, 0, 0, 1, 1, 1, 0, 0},
361cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {0, 0, 0, 0, 1, 1, 1, 1, 1},
371cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {0, 0, 0, 0, 0, 0, 1, 1, 1},
381cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {0, 1, 1, 0, 0, 0, 1, 1, 1},
391cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {0, 1, 1, 0, 0, 0, 0, 0, 1},
401cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {0, 1, 1, 1, 1, 0, 0, 0, 1},
411cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {0, 0, 1, 1, 1, 0, 0, 0, 0},
421cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {0, 0, 1, 1, 1, 1, 1, 0, 0}
431cc31e629e8132df390ae692873c847d1c2f62c0James Dong}; //to decide whether to continue or compute
441cc31e629e8132df390ae692873c847d1c2f62c0James Dong
451cc31e629e8132df390ae692873c847d1c2f62c0James Dongconst static int refine_next[8][2] =    /* [curr_k][increment] */
461cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
471cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {0, 0}, {2, 0}, {1, 1}, {0, 2}, { -1, 1}, { -2, 0}, { -1, -1}, {0, -2}
481cc31e629e8132df390ae692873c847d1c2f62c0James Dong};
491cc31e629e8132df390ae692873c847d1c2f62c0James Dong
501cc31e629e8132df390ae692873c847d1c2f62c0James Dong#ifdef _SAD_STAT
511cc31e629e8132df390ae692873c847d1c2f62c0James Donguint32 num_MB = 0;
521cc31e629e8132df390ae692873c847d1c2f62c0James Donguint32 num_cand = 0;
531cc31e629e8132df390ae692873c847d1c2f62c0James Dong#endif
541cc31e629e8132df390ae692873c847d1c2f62c0James Dong
551cc31e629e8132df390ae692873c847d1c2f62c0James Dong/************************************************************************/
561cc31e629e8132df390ae692873c847d1c2f62c0James Dong#define TH_INTER_2  100  /* temporary for now */
571cc31e629e8132df390ae692873c847d1c2f62c0James Dong
581cc31e629e8132df390ae692873c847d1c2f62c0James Dong//#define FIXED_INTERPRED_MODE  AVC_P16
591cc31e629e8132df390ae692873c847d1c2f62c0James Dong#define FIXED_REF_IDX   0
601cc31e629e8132df390ae692873c847d1c2f62c0James Dong#define FIXED_MVX 0
611cc31e629e8132df390ae692873c847d1c2f62c0James Dong#define FIXED_MVY 0
621cc31e629e8132df390ae692873c847d1c2f62c0James Dong
631cc31e629e8132df390ae692873c847d1c2f62c0James Dong// only use when AVC_P8 or AVC_P8ref0
641cc31e629e8132df390ae692873c847d1c2f62c0James Dong#define FIXED_SUBMB_MODE    AVC_4x4
651cc31e629e8132df390ae692873c847d1c2f62c0James Dong/*************************************************************************/
661cc31e629e8132df390ae692873c847d1c2f62c0James Dong
671cc31e629e8132df390ae692873c847d1c2f62c0James Dong/* Initialize arrays necessary for motion search */
681cc31e629e8132df390ae692873c847d1c2f62c0James DongAVCEnc_Status InitMotionSearchModule(AVCHandle *avcHandle)
691cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
701cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
711cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCRateControl *rateCtrl = encvid->rateCtrl;
721cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int search_range = rateCtrl->mvRange;
731cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int number_of_subpel_positions = 4 * (2 * search_range + 3);
741cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int max_mv_bits, max_mvd;
751cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int temp_bits = 0;
761cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint8 *mvbits;
771cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int bits, imax, imin, i;
781cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint8* subpel_pred = (uint8*) encvid->subpel_pred; // all 16 sub-pel positions
791cc31e629e8132df390ae692873c847d1c2f62c0James Dong
801cc31e629e8132df390ae692873c847d1c2f62c0James Dong
811cc31e629e8132df390ae692873c847d1c2f62c0James Dong    while (number_of_subpel_positions > 0)
821cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
831cc31e629e8132df390ae692873c847d1c2f62c0James Dong        temp_bits++;
841cc31e629e8132df390ae692873c847d1c2f62c0James Dong        number_of_subpel_positions >>= 1;
851cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
861cc31e629e8132df390ae692873c847d1c2f62c0James Dong
871cc31e629e8132df390ae692873c847d1c2f62c0James Dong    max_mv_bits = 3 + 2 * temp_bits;
881cc31e629e8132df390ae692873c847d1c2f62c0James Dong    max_mvd  = (1 << (max_mv_bits >> 1)) - 1;
891cc31e629e8132df390ae692873c847d1c2f62c0James Dong
901cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->mvbits_array = (uint8*) avcHandle->CBAVC_Malloc(encvid->avcHandle->userData,
911cc31e629e8132df390ae692873c847d1c2f62c0James Dong                           sizeof(uint8) * (2 * max_mvd + 1), DEFAULT_ATTR);
921cc31e629e8132df390ae692873c847d1c2f62c0James Dong
931cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (encvid->mvbits_array == NULL)
941cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
951cc31e629e8132df390ae692873c847d1c2f62c0James Dong        return AVCENC_MEMORY_FAIL;
961cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
971cc31e629e8132df390ae692873c847d1c2f62c0James Dong
981cc31e629e8132df390ae692873c847d1c2f62c0James Dong    mvbits = encvid->mvbits  = encvid->mvbits_array + max_mvd;
991cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1001cc31e629e8132df390ae692873c847d1c2f62c0James Dong    mvbits[0] = 1;
1011cc31e629e8132df390ae692873c847d1c2f62c0James Dong    for (bits = 3; bits <= max_mv_bits; bits += 2)
1021cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
1031cc31e629e8132df390ae692873c847d1c2f62c0James Dong        imax = 1    << (bits >> 1);
1041cc31e629e8132df390ae692873c847d1c2f62c0James Dong        imin = imax >> 1;
1051cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1061cc31e629e8132df390ae692873c847d1c2f62c0James Dong        for (i = imin; i < imax; i++)   mvbits[-i] = mvbits[i] = bits;
1071cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
1081cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1091cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* initialize half-pel search */
1101cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->hpel_cand[0] = subpel_pred + REF_CENTER;
1111cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->hpel_cand[1] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 1 ;
1121cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->hpel_cand[2] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 1;
1131cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->hpel_cand[3] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 25;
1141cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->hpel_cand[4] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 25;
1151cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->hpel_cand[5] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 25;
1161cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->hpel_cand[6] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
1171cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->hpel_cand[7] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
1181cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->hpel_cand[8] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE;
1191cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1201cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* For quarter-pel interpolation around best half-pel result */
1211cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1221cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[0][0] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE;
1231cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[0][1] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 1;
1241cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[0][2] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
1251cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[0][3] = subpel_pred + REF_CENTER;
1261cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1271cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1281cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[1][0] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE;
1291cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[1][1] = subpel_pred + REF_CENTER - 24;
1301cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[1][2] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE;
1311cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[1][3] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 1;
1321cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1331cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[2][0] = subpel_pred + REF_CENTER - 24;
1341cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[2][1] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 1;
1351cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[2][2] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 1;
1361cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[2][3] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 1;
1371cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1381cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[3][0] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 1;
1391cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[3][1] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 1;
1401cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[3][2] = subpel_pred + REF_CENTER;
1411cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[3][3] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 25;
1421cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1431cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[4][0] = subpel_pred + REF_CENTER;
1441cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[4][1] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 25;
1451cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[4][2] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 25;
1461cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[4][3] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 25;
1471cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1481cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[5][0] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
1491cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[5][1] = subpel_pred + REF_CENTER;
1501cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[5][2] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
1511cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[5][3] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 25;
1521cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1531cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[6][0] = subpel_pred + REF_CENTER - 1;
1541cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[6][1] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
1551cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[6][2] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 24;
1561cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[6][3] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
1571cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1581cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[7][0] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE;
1591cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[7][1] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE;
1601cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[7][2] = subpel_pred + REF_CENTER - 1;
1611cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[7][3] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
1621cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1631cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[8][0] = subpel_pred + REF_CENTER - 25;
1641cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[8][1] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE;
1651cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[8][2] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE;
1661cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->bilin_base[8][3] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE;
1671cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1681cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1691cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return AVCENC_SUCCESS;
1701cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
1711cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1721cc31e629e8132df390ae692873c847d1c2f62c0James Dong/* Clean-up memory */
1731cc31e629e8132df390ae692873c847d1c2f62c0James Dongvoid CleanMotionSearchModule(AVCHandle *avcHandle)
1741cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
1751cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
1761cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1771cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (encvid->mvbits_array)
1781cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
1791cc31e629e8132df390ae692873c847d1c2f62c0James Dong        avcHandle->CBAVC_Free(avcHandle->userData, (int)(encvid->mvbits_array));
1801cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->mvbits = NULL;
1811cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
1821cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1831cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return ;
1841cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
1851cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1861cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1871cc31e629e8132df390ae692873c847d1c2f62c0James Dongbool IntraDecisionABE(int *min_cost, uint8 *cur, int pitch, bool ave)
1881cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
1891cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int j;
1901cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint8 *out;
1911cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int temp, SBE;
1921cc31e629e8132df390ae692873c847d1c2f62c0James Dong    OsclFloat ABE;
1931cc31e629e8132df390ae692873c847d1c2f62c0James Dong    bool intra = true;
1941cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1951cc31e629e8132df390ae692873c847d1c2f62c0James Dong    SBE = 0;
1961cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* top neighbor */
1971cc31e629e8132df390ae692873c847d1c2f62c0James Dong    out = cur - pitch;
1981cc31e629e8132df390ae692873c847d1c2f62c0James Dong    for (j = 0; j < 16; j++)
1991cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
2001cc31e629e8132df390ae692873c847d1c2f62c0James Dong        temp = out[j] - cur[j];
2011cc31e629e8132df390ae692873c847d1c2f62c0James Dong        SBE += ((temp >= 0) ? temp : -temp);
2021cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
2031cc31e629e8132df390ae692873c847d1c2f62c0James Dong
2041cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* left neighbor */
2051cc31e629e8132df390ae692873c847d1c2f62c0James Dong    out = cur - 1;
2061cc31e629e8132df390ae692873c847d1c2f62c0James Dong    out -= pitch;
2071cc31e629e8132df390ae692873c847d1c2f62c0James Dong    cur -= pitch;
2081cc31e629e8132df390ae692873c847d1c2f62c0James Dong    for (j = 0; j < 16; j++)
2091cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
2101cc31e629e8132df390ae692873c847d1c2f62c0James Dong        temp = *(out += pitch) - *(cur += pitch);
2111cc31e629e8132df390ae692873c847d1c2f62c0James Dong        SBE += ((temp >= 0) ? temp : -temp);
2121cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
2131cc31e629e8132df390ae692873c847d1c2f62c0James Dong
2141cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* compare mincost/384 and SBE/64 */
2151cc31e629e8132df390ae692873c847d1c2f62c0James Dong    ABE = SBE / 32.0; //ABE = SBE/64.0; //
2161cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (ABE >= *min_cost / 256.0) //if( ABE*0.8 >= min_cost/384.0) //
2171cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
2181cc31e629e8132df390ae692873c847d1c2f62c0James Dong        intra = false; // no possibility of intra, just use inter
2191cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
2201cc31e629e8132df390ae692873c847d1c2f62c0James Dong    else
2211cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
2221cc31e629e8132df390ae692873c847d1c2f62c0James Dong        if (ave == true)
2231cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
2241cc31e629e8132df390ae692873c847d1c2f62c0James Dong            *min_cost = (*min_cost + (int)(SBE * 8)) >> 1; // possibility of intra, averaging the cost
2251cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
2261cc31e629e8132df390ae692873c847d1c2f62c0James Dong        else
2271cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
2281cc31e629e8132df390ae692873c847d1c2f62c0James Dong            *min_cost = (int)(SBE * 8);
2291cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
2301cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
2311cc31e629e8132df390ae692873c847d1c2f62c0James Dong
2321cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return intra;
2331cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
2341cc31e629e8132df390ae692873c847d1c2f62c0James Dong
2351cc31e629e8132df390ae692873c847d1c2f62c0James Dong/******* main function for macroblock prediction for the entire frame ***/
2361cc31e629e8132df390ae692873c847d1c2f62c0James Dong/* if turns out to be IDR frame, set video->nal_unit_type to AVC_NALTYPE_IDR */
2371cc31e629e8132df390ae692873c847d1c2f62c0James Dongvoid AVCMotionEstimation(AVCEncObject *encvid)
2381cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
2391cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCCommonObj *video = encvid->common;
2401cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int slice_type = video->slice_type;
2411cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCFrameIO *currInput = encvid->currInput;
2421cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCPictureData *refPic = video->RefPicList0[0];
2431cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int i, j, k;
2441cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int mbwidth = video->PicWidthInMbs;
2451cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int mbheight = video->PicHeightInMbs;
2461cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int totalMB = video->PicSizeInMbs;
2471cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int pitch = currInput->pitch;
2481cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCMacroblock *currMB, *mblock = video->mblock;
2491cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCMV *mot_mb_16x16, *mot16x16 = encvid->mot16x16;
2501cc31e629e8132df390ae692873c847d1c2f62c0James Dong    // AVCMV *mot_mb_16x8, *mot_mb_8x16, *mot_mb_8x8, etc;
2511cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCRateControl *rateCtrl = encvid->rateCtrl;
2521cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint8 *intraSearch = encvid->intraSearch;
2531cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint FS_en = encvid->fullsearch_enable;
2541cc31e629e8132df390ae692873c847d1c2f62c0James Dong
2551cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int NumIntraSearch, start_i, numLoop, incr_i;
2561cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int mbnum, offset;
2571cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint8 *cur, *best_cand[5];
2581cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int totalSAD = 0;   /* average SAD for rate control */
2591cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int type_pred;
2601cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int abe_cost;
2611cc31e629e8132df390ae692873c847d1c2f62c0James Dong
2621cc31e629e8132df390ae692873c847d1c2f62c0James Dong#ifdef HTFM
2631cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /***** HYPOTHESIS TESTING ********/  /* 2/28/01 */
2641cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int collect = 0;
2651cc31e629e8132df390ae692873c847d1c2f62c0James Dong    HTFM_Stat htfm_stat;
2661cc31e629e8132df390ae692873c847d1c2f62c0James Dong    double newvar[16];
2671cc31e629e8132df390ae692873c847d1c2f62c0James Dong    double exp_lamda[15];
2681cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /*********************************/
2691cc31e629e8132df390ae692873c847d1c2f62c0James Dong#endif
2701cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int hp_guess = 0;
2711cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint32 mv_uint32;
2721cc31e629e8132df390ae692873c847d1c2f62c0James Dong
2731cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset = 0;
2741cc31e629e8132df390ae692873c847d1c2f62c0James Dong
2751cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (slice_type == AVC_I_SLICE)
2761cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
2771cc31e629e8132df390ae692873c847d1c2f62c0James Dong        /* cannot do I16 prediction here because it needs full decoding. */
2781cc31e629e8132df390ae692873c847d1c2f62c0James Dong        for (i = 0; i < totalMB; i++)
2791cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
2801cc31e629e8132df390ae692873c847d1c2f62c0James Dong            encvid->min_cost[i] = 0x7FFFFFFF;  /* max value for int */
2811cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
2821cc31e629e8132df390ae692873c847d1c2f62c0James Dong
2831cc31e629e8132df390ae692873c847d1c2f62c0James Dong        memset(intraSearch, 1, sizeof(uint8)*totalMB);
2841cc31e629e8132df390ae692873c847d1c2f62c0James Dong
2851cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->firstIntraRefreshMBIndx = 0; /* reset this */
2861cc31e629e8132df390ae692873c847d1c2f62c0James Dong
2871cc31e629e8132df390ae692873c847d1c2f62c0James Dong        return ;
2881cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
2891cc31e629e8132df390ae692873c847d1c2f62c0James Dong    else   // P_SLICE
2901cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
2911cc31e629e8132df390ae692873c847d1c2f62c0James Dong        for (i = 0; i < totalMB; i++)
2921cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
2931cc31e629e8132df390ae692873c847d1c2f62c0James Dong            mblock[i].mb_intra = 0;
2941cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
2951cc31e629e8132df390ae692873c847d1c2f62c0James Dong        memset(intraSearch, 1, sizeof(uint8)*totalMB);
2961cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
2971cc31e629e8132df390ae692873c847d1c2f62c0James Dong
2981cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (refPic->padded == 0)
2991cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
3001cc31e629e8132df390ae692873c847d1c2f62c0James Dong        AVCPaddingEdge(refPic);
3011cc31e629e8132df390ae692873c847d1c2f62c0James Dong        refPic->padded = 1;
3021cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
3031cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* Random INTRA update */
3041cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (rateCtrl->intraMBRate)
3051cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
3061cc31e629e8132df390ae692873c847d1c2f62c0James Dong        AVCRasterIntraUpdate(encvid, mblock, totalMB, rateCtrl->intraMBRate);
3071cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
3081cc31e629e8132df390ae692873c847d1c2f62c0James Dong
3091cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->sad_extra_info = NULL;
3101cc31e629e8132df390ae692873c847d1c2f62c0James Dong#ifdef HTFM
3111cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /***** HYPOTHESIS TESTING ********/
3121cc31e629e8132df390ae692873c847d1c2f62c0James Dong    InitHTFM(video, &htfm_stat, newvar, &collect);
3131cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /*********************************/
3141cc31e629e8132df390ae692873c847d1c2f62c0James Dong#endif
3151cc31e629e8132df390ae692873c847d1c2f62c0James Dong
3161cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if ((rateCtrl->scdEnable == 1)
3171cc31e629e8132df390ae692873c847d1c2f62c0James Dong            && ((rateCtrl->frame_rate < 5.0) || (video->sliceHdr->frame_num > MIN_GOP)))
3181cc31e629e8132df390ae692873c847d1c2f62c0James Dong        /* do not try to detect a new scene if low frame rate and too close to previous I-frame */
3191cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
3201cc31e629e8132df390ae692873c847d1c2f62c0James Dong        incr_i = 2;
3211cc31e629e8132df390ae692873c847d1c2f62c0James Dong        numLoop = 2;
3221cc31e629e8132df390ae692873c847d1c2f62c0James Dong        start_i = 1;
3231cc31e629e8132df390ae692873c847d1c2f62c0James Dong        type_pred = 0; /* for initial candidate selection */
3241cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
3251cc31e629e8132df390ae692873c847d1c2f62c0James Dong    else
3261cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
3271cc31e629e8132df390ae692873c847d1c2f62c0James Dong        incr_i = 1;
3281cc31e629e8132df390ae692873c847d1c2f62c0James Dong        numLoop = 1;
3291cc31e629e8132df390ae692873c847d1c2f62c0James Dong        start_i = 0;
3301cc31e629e8132df390ae692873c847d1c2f62c0James Dong        type_pred = 2;
3311cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
3321cc31e629e8132df390ae692873c847d1c2f62c0James Dong
3331cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* First pass, loop thru half the macroblock */
3341cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* determine scene change */
3351cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* Second pass, for the rest of macroblocks */
3361cc31e629e8132df390ae692873c847d1c2f62c0James Dong    NumIntraSearch = 0; // to be intra searched in the encoding loop.
3371cc31e629e8132df390ae692873c847d1c2f62c0James Dong    while (numLoop--)
3381cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
3391cc31e629e8132df390ae692873c847d1c2f62c0James Dong        for (j = 0; j < mbheight; j++)
3401cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
3411cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (incr_i > 1)
3421cc31e629e8132df390ae692873c847d1c2f62c0James Dong                start_i = (start_i == 0 ? 1 : 0) ; /* toggle 0 and 1 */
3431cc31e629e8132df390ae692873c847d1c2f62c0James Dong
3441cc31e629e8132df390ae692873c847d1c2f62c0James Dong            offset = pitch * (j << 4) + (start_i << 4);
3451cc31e629e8132df390ae692873c847d1c2f62c0James Dong
3461cc31e629e8132df390ae692873c847d1c2f62c0James Dong            mbnum = j * mbwidth + start_i;
3471cc31e629e8132df390ae692873c847d1c2f62c0James Dong
3481cc31e629e8132df390ae692873c847d1c2f62c0James Dong            for (i = start_i; i < mbwidth; i += incr_i)
3491cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
3501cc31e629e8132df390ae692873c847d1c2f62c0James Dong                video->mbNum = mbnum;
3511cc31e629e8132df390ae692873c847d1c2f62c0James Dong                video->currMB = currMB = mblock + mbnum;
3521cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mot_mb_16x16 = mot16x16 + mbnum;
3531cc31e629e8132df390ae692873c847d1c2f62c0James Dong
3541cc31e629e8132df390ae692873c847d1c2f62c0James Dong                cur = currInput->YCbCr[0] + offset;
3551cc31e629e8132df390ae692873c847d1c2f62c0James Dong
3561cc31e629e8132df390ae692873c847d1c2f62c0James Dong                if (currMB->mb_intra == 0) /* for INTER mode */
3571cc31e629e8132df390ae692873c847d1c2f62c0James Dong                {
3581cc31e629e8132df390ae692873c847d1c2f62c0James Dong#if defined(HTFM)
3591cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    HTFMPrepareCurMB_AVC(encvid, &htfm_stat, cur, pitch);
3601cc31e629e8132df390ae692873c847d1c2f62c0James Dong#else
3611cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    AVCPrepareCurMB(encvid, cur, pitch);
3621cc31e629e8132df390ae692873c847d1c2f62c0James Dong#endif
3631cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    /************************************************************/
3641cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    /******** full-pel 1MV search **********************/
3651cc31e629e8132df390ae692873c847d1c2f62c0James Dong
3661cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    AVCMBMotionSearch(encvid, cur, best_cand, i << 4, j << 4, type_pred,
3671cc31e629e8132df390ae692873c847d1c2f62c0James Dong                                      FS_en, &hp_guess);
3681cc31e629e8132df390ae692873c847d1c2f62c0James Dong
3691cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    abe_cost = encvid->min_cost[mbnum] = mot_mb_16x16->sad;
3701cc31e629e8132df390ae692873c847d1c2f62c0James Dong
3711cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    /* set mbMode and MVs */
3721cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    currMB->mbMode = AVC_P16;
3731cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    currMB->MBPartPredMode[0][0] = AVC_Pred_L0;
3741cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    mv_uint32 = ((mot_mb_16x16->y) << 16) | ((mot_mb_16x16->x) & 0xffff);
3751cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    for (k = 0; k < 32; k += 2)
3761cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    {
3771cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        currMB->mvL0[k>>1] = mv_uint32;
3781cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    }
3791cc31e629e8132df390ae692873c847d1c2f62c0James Dong
3801cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    /* make a decision whether it should be tested for intra or not */
3811cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    if (i != mbwidth - 1 && j != mbheight - 1 && i != 0 && j != 0)
3821cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    {
3831cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        if (false == IntraDecisionABE(&abe_cost, cur, pitch, true))
3841cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        {
3851cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            intraSearch[mbnum] = 0;
3861cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        }
3871cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        else
3881cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        {
3891cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            NumIntraSearch++;
3901cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            rateCtrl->MADofMB[mbnum] = abe_cost;
3911cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        }
3921cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    }
3931cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    else // boundary MBs, always do intra search
3941cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    {
3951cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        NumIntraSearch++;
3961cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    }
3971cc31e629e8132df390ae692873c847d1c2f62c0James Dong
3981cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    totalSAD += (int) rateCtrl->MADofMB[mbnum];//mot_mb_16x16->sad;
3991cc31e629e8132df390ae692873c847d1c2f62c0James Dong                }
4001cc31e629e8132df390ae692873c847d1c2f62c0James Dong                else    /* INTRA update, use for prediction */
4011cc31e629e8132df390ae692873c847d1c2f62c0James Dong                {
4021cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    mot_mb_16x16[0].x = mot_mb_16x16[0].y = 0;
4031cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4041cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    /* reset all other MVs to zero */
4051cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    /* mot_mb_16x8, mot_mb_8x16, mot_mb_8x8, etc. */
4061cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    abe_cost = encvid->min_cost[mbnum] = 0x7FFFFFFF;  /* max value for int */
4071cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4081cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    if (i != mbwidth - 1 && j != mbheight - 1 && i != 0 && j != 0)
4091cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    {
4101cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        IntraDecisionABE(&abe_cost, cur, pitch, false);
4111cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4121cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        rateCtrl->MADofMB[mbnum] = abe_cost;
4131cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        totalSAD += abe_cost;
4141cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    }
4151cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4161cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    NumIntraSearch++ ;
4171cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    /* cannot do I16 prediction here because it needs full decoding. */
4181cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    // intraSearch[mbnum] = 1;
4191cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4201cc31e629e8132df390ae692873c847d1c2f62c0James Dong                }
4211cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4221cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mbnum += incr_i;
4231cc31e629e8132df390ae692873c847d1c2f62c0James Dong                offset += (incr_i << 4);
4241cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4251cc31e629e8132df390ae692873c847d1c2f62c0James Dong            } /* for i */
4261cc31e629e8132df390ae692873c847d1c2f62c0James Dong        } /* for j */
4271cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4281cc31e629e8132df390ae692873c847d1c2f62c0James Dong        /* since we cannot do intra/inter decision here, the SCD has to be
4291cc31e629e8132df390ae692873c847d1c2f62c0James Dong        based on other criteria such as motion vectors coherency or the SAD */
4301cc31e629e8132df390ae692873c847d1c2f62c0James Dong        if (incr_i > 1 && numLoop) /* scene change on and first loop */
4311cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
4321cc31e629e8132df390ae692873c847d1c2f62c0James Dong            //if(NumIntraSearch > ((totalMB>>3)<<1) + (totalMB>>3)) /* 75% of 50%MBs */
4331cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (NumIntraSearch*99 > (48*totalMB)) /* 20% of 50%MBs */
4341cc31e629e8132df390ae692873c847d1c2f62c0James Dong                /* need to do more investigation about this threshold since the NumIntraSearch
4351cc31e629e8132df390ae692873c847d1c2f62c0James Dong                only show potential intra MBs, not the actual one */
4361cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
4371cc31e629e8132df390ae692873c847d1c2f62c0James Dong                /* we can choose to just encode I_SLICE without IDR */
4381cc31e629e8132df390ae692873c847d1c2f62c0James Dong                //video->nal_unit_type = AVC_NALTYPE_IDR;
4391cc31e629e8132df390ae692873c847d1c2f62c0James Dong                video->nal_unit_type = AVC_NALTYPE_SLICE;
4401cc31e629e8132df390ae692873c847d1c2f62c0James Dong                video->sliceHdr->slice_type = AVC_I_ALL_SLICE;
4411cc31e629e8132df390ae692873c847d1c2f62c0James Dong                video->slice_type = AVC_I_SLICE;
4421cc31e629e8132df390ae692873c847d1c2f62c0James Dong                memset(intraSearch, 1, sizeof(uint8)*totalMB);
4431cc31e629e8132df390ae692873c847d1c2f62c0James Dong                i = totalMB;
4441cc31e629e8132df390ae692873c847d1c2f62c0James Dong                while (i--)
4451cc31e629e8132df390ae692873c847d1c2f62c0James Dong                {
4461cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    mblock[i].mb_intra = 1;
4471cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    encvid->min_cost[i] = 0x7FFFFFFF;  /* max value for int */
4481cc31e629e8132df390ae692873c847d1c2f62c0James Dong                }
4491cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4501cc31e629e8132df390ae692873c847d1c2f62c0James Dong                rateCtrl->totalSAD = totalSAD * 2;  /* SAD */
4511cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4521cc31e629e8132df390ae692873c847d1c2f62c0James Dong                return ;
4531cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
4541cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
4551cc31e629e8132df390ae692873c847d1c2f62c0James Dong        /******** no scene change, continue motion search **********************/
4561cc31e629e8132df390ae692873c847d1c2f62c0James Dong        start_i = 0;
4571cc31e629e8132df390ae692873c847d1c2f62c0James Dong        type_pred++; /* second pass */
4581cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
4591cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4601cc31e629e8132df390ae692873c847d1c2f62c0James Dong    rateCtrl->totalSAD = totalSAD;  /* SAD */
4611cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4621cc31e629e8132df390ae692873c847d1c2f62c0James Dong#ifdef HTFM
4631cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /***** HYPOTHESIS TESTING ********/
4641cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (collect)
4651cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
4661cc31e629e8132df390ae692873c847d1c2f62c0James Dong        collect = 0;
4671cc31e629e8132df390ae692873c847d1c2f62c0James Dong        UpdateHTFM(encvid, newvar, exp_lamda, &htfm_stat);
4681cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
4691cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /*********************************/
4701cc31e629e8132df390ae692873c847d1c2f62c0James Dong#endif
4711cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4721cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return ;
4731cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
4741cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4751cc31e629e8132df390ae692873c847d1c2f62c0James Dong/*=====================================================================
4761cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Function:   PaddingEdge
4771cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Date:       09/16/2000
4781cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Purpose:    Pad edge of a Vop
4791cc31e629e8132df390ae692873c847d1c2f62c0James Dong=====================================================================*/
4801cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4811cc31e629e8132df390ae692873c847d1c2f62c0James Dongvoid  AVCPaddingEdge(AVCPictureData *refPic)
4821cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
4831cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint8 *src, *dst;
4841cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int i;
4851cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int pitch, width, height;
4861cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint32 temp1, temp2;
4871cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4881cc31e629e8132df390ae692873c847d1c2f62c0James Dong    width = refPic->width;
4891cc31e629e8132df390ae692873c847d1c2f62c0James Dong    height = refPic->height;
4901cc31e629e8132df390ae692873c847d1c2f62c0James Dong    pitch = refPic->pitch;
4911cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4921cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* pad top */
4931cc31e629e8132df390ae692873c847d1c2f62c0James Dong    src = refPic->Sl;
4941cc31e629e8132df390ae692873c847d1c2f62c0James Dong
4951cc31e629e8132df390ae692873c847d1c2f62c0James Dong    temp1 = *src; /* top-left corner */
4961cc31e629e8132df390ae692873c847d1c2f62c0James Dong    temp2 = src[width-1]; /* top-right corner */
4971cc31e629e8132df390ae692873c847d1c2f62c0James Dong    temp1 |= (temp1 << 8);
4981cc31e629e8132df390ae692873c847d1c2f62c0James Dong    temp1 |= (temp1 << 16);
4991cc31e629e8132df390ae692873c847d1c2f62c0James Dong    temp2 |= (temp2 << 8);
5001cc31e629e8132df390ae692873c847d1c2f62c0James Dong    temp2 |= (temp2 << 16);
5011cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5021cc31e629e8132df390ae692873c847d1c2f62c0James Dong    dst = src - (pitch << 4);
5031cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5041cc31e629e8132df390ae692873c847d1c2f62c0James Dong    *((uint32*)(dst - 16)) = temp1;
5051cc31e629e8132df390ae692873c847d1c2f62c0James Dong    *((uint32*)(dst - 12)) = temp1;
5061cc31e629e8132df390ae692873c847d1c2f62c0James Dong    *((uint32*)(dst - 8)) = temp1;
5071cc31e629e8132df390ae692873c847d1c2f62c0James Dong    *((uint32*)(dst - 4)) = temp1;
5081cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5091cc31e629e8132df390ae692873c847d1c2f62c0James Dong    memcpy(dst, src, width);
5101cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5111cc31e629e8132df390ae692873c847d1c2f62c0James Dong    *((uint32*)(dst += width)) = temp2;
5121cc31e629e8132df390ae692873c847d1c2f62c0James Dong    *((uint32*)(dst + 4)) = temp2;
5131cc31e629e8132df390ae692873c847d1c2f62c0James Dong    *((uint32*)(dst + 8)) = temp2;
5141cc31e629e8132df390ae692873c847d1c2f62c0James Dong    *((uint32*)(dst + 12)) = temp2;
5151cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5161cc31e629e8132df390ae692873c847d1c2f62c0James Dong    dst = dst - width - 16;
5171cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5181cc31e629e8132df390ae692873c847d1c2f62c0James Dong    i = 15;
5191cc31e629e8132df390ae692873c847d1c2f62c0James Dong    while (i--)
5201cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
5211cc31e629e8132df390ae692873c847d1c2f62c0James Dong        memcpy(dst + pitch, dst, pitch);
5221cc31e629e8132df390ae692873c847d1c2f62c0James Dong        dst += pitch;
5231cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
5241cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5251cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* pad sides */
5261cc31e629e8132df390ae692873c847d1c2f62c0James Dong    dst += (pitch + 16);
5271cc31e629e8132df390ae692873c847d1c2f62c0James Dong    src = dst;
5281cc31e629e8132df390ae692873c847d1c2f62c0James Dong    i = height;
5291cc31e629e8132df390ae692873c847d1c2f62c0James Dong    while (i--)
5301cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
5311cc31e629e8132df390ae692873c847d1c2f62c0James Dong        temp1 = *src;
5321cc31e629e8132df390ae692873c847d1c2f62c0James Dong        temp2 = src[width-1];
5331cc31e629e8132df390ae692873c847d1c2f62c0James Dong        temp1 |= (temp1 << 8);
5341cc31e629e8132df390ae692873c847d1c2f62c0James Dong        temp1 |= (temp1 << 16);
5351cc31e629e8132df390ae692873c847d1c2f62c0James Dong        temp2 |= (temp2 << 8);
5361cc31e629e8132df390ae692873c847d1c2f62c0James Dong        temp2 |= (temp2 << 16);
5371cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5381cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *((uint32*)(dst - 16)) = temp1;
5391cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *((uint32*)(dst - 12)) = temp1;
5401cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *((uint32*)(dst - 8)) = temp1;
5411cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *((uint32*)(dst - 4)) = temp1;
5421cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5431cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *((uint32*)(dst += width)) = temp2;
5441cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *((uint32*)(dst + 4)) = temp2;
5451cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *((uint32*)(dst + 8)) = temp2;
5461cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *((uint32*)(dst + 12)) = temp2;
5471cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5481cc31e629e8132df390ae692873c847d1c2f62c0James Dong        src += pitch;
5491cc31e629e8132df390ae692873c847d1c2f62c0James Dong        dst = src;
5501cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
5511cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5521cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* pad bottom */
5531cc31e629e8132df390ae692873c847d1c2f62c0James Dong    dst -= 16;
5541cc31e629e8132df390ae692873c847d1c2f62c0James Dong    i = 16;
5551cc31e629e8132df390ae692873c847d1c2f62c0James Dong    while (i--)
5561cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
5571cc31e629e8132df390ae692873c847d1c2f62c0James Dong        memcpy(dst, dst - pitch, pitch);
5581cc31e629e8132df390ae692873c847d1c2f62c0James Dong        dst += pitch;
5591cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
5601cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5611cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5621cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return ;
5631cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
5641cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5651cc31e629e8132df390ae692873c847d1c2f62c0James Dong/*===========================================================================
5661cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Function:   AVCRasterIntraUpdate
5671cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Date:       2/26/01
5681cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Purpose:    To raster-scan assign INTRA-update .
5691cc31e629e8132df390ae692873c847d1c2f62c0James Dong                N macroblocks are updated (also was programmable).
5701cc31e629e8132df390ae692873c847d1c2f62c0James Dong===========================================================================*/
5711cc31e629e8132df390ae692873c847d1c2f62c0James Dongvoid AVCRasterIntraUpdate(AVCEncObject *encvid, AVCMacroblock *mblock, int totalMB, int numRefresh)
5721cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
5731cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int indx, i;
5741cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5751cc31e629e8132df390ae692873c847d1c2f62c0James Dong    indx = encvid->firstIntraRefreshMBIndx;
5761cc31e629e8132df390ae692873c847d1c2f62c0James Dong    for (i = 0; i < numRefresh && indx < totalMB; i++)
5771cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
5781cc31e629e8132df390ae692873c847d1c2f62c0James Dong        (mblock + indx)->mb_intra = 1;
5791cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->intraSearch[indx++] = 1;
5801cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
5811cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5821cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* if read the end of frame, reset and loop around */
5831cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (indx >= totalMB - 1)
5841cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
5851cc31e629e8132df390ae692873c847d1c2f62c0James Dong        indx = 0;
5861cc31e629e8132df390ae692873c847d1c2f62c0James Dong        while (i < numRefresh && indx < totalMB)
5871cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
5881cc31e629e8132df390ae692873c847d1c2f62c0James Dong            (mblock + indx)->mb_intra = 1;
5891cc31e629e8132df390ae692873c847d1c2f62c0James Dong            encvid->intraSearch[indx++] = 1;
5901cc31e629e8132df390ae692873c847d1c2f62c0James Dong            i++;
5911cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
5921cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
5931cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5941cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->firstIntraRefreshMBIndx = indx; /* update with a new value */
5951cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5961cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return ;
5971cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
5981cc31e629e8132df390ae692873c847d1c2f62c0James Dong
5991cc31e629e8132df390ae692873c847d1c2f62c0James Dong
6001cc31e629e8132df390ae692873c847d1c2f62c0James Dong#ifdef HTFM
6011cc31e629e8132df390ae692873c847d1c2f62c0James Dongvoid InitHTFM(VideoEncData *encvid, HTFM_Stat *htfm_stat, double *newvar, int *collect)
6021cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
6031cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCCommonObj *video = encvid->common;
6041cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int i;
6051cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int lx = video->currPic->width; // padding
6061cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int lx2 = lx << 1;
6071cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int lx3 = lx2 + lx;
6081cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int rx = video->currPic->pitch;
6091cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int rx2 = rx << 1;
6101cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int rx3 = rx2 + rx;
6111cc31e629e8132df390ae692873c847d1c2f62c0James Dong
6121cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int *offset, *offset2;
6131cc31e629e8132df390ae692873c847d1c2f62c0James Dong
6141cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* 4/11/01, collect data every 30 frames, doesn't have to be base layer */
6151cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (((int)video->sliceHdr->frame_num) % 30 == 1)
6161cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
6171cc31e629e8132df390ae692873c847d1c2f62c0James Dong
6181cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *collect = 1;
6191cc31e629e8132df390ae692873c847d1c2f62c0James Dong
6201cc31e629e8132df390ae692873c847d1c2f62c0James Dong        htfm_stat->countbreak = 0;
6211cc31e629e8132df390ae692873c847d1c2f62c0James Dong        htfm_stat->abs_dif_mad_avg = 0;
6221cc31e629e8132df390ae692873c847d1c2f62c0James Dong
6231cc31e629e8132df390ae692873c847d1c2f62c0James Dong        for (i = 0; i < 16; i++)
6241cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
6251cc31e629e8132df390ae692873c847d1c2f62c0James Dong            newvar[i] = 0.0;
6261cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
6271cc31e629e8132df390ae692873c847d1c2f62c0James Dong//      encvid->functionPointer->SAD_MB_PADDING = &SAD_MB_PADDING_HTFM_Collect;
6281cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->functionPointer->SAD_Macroblock = &SAD_MB_HTFM_Collect;
6291cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->functionPointer->SAD_MB_HalfPel[0] = NULL;
6301cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->functionPointer->SAD_MB_HalfPel[1] = &SAD_MB_HP_HTFM_Collectxh;
6311cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->functionPointer->SAD_MB_HalfPel[2] = &SAD_MB_HP_HTFM_Collectyh;
6321cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->functionPointer->SAD_MB_HalfPel[3] = &SAD_MB_HP_HTFM_Collectxhyh;
6331cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->sad_extra_info = (void*)(htfm_stat);
6341cc31e629e8132df390ae692873c847d1c2f62c0James Dong        offset = htfm_stat->offsetArray;
6351cc31e629e8132df390ae692873c847d1c2f62c0James Dong        offset2 = htfm_stat->offsetRef;
6361cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
6371cc31e629e8132df390ae692873c847d1c2f62c0James Dong    else
6381cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
6391cc31e629e8132df390ae692873c847d1c2f62c0James Dong//      encvid->functionPointer->SAD_MB_PADDING = &SAD_MB_PADDING_HTFM;
6401cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->functionPointer->SAD_Macroblock = &SAD_MB_HTFM;
6411cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->functionPointer->SAD_MB_HalfPel[0] = NULL;
6421cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->functionPointer->SAD_MB_HalfPel[1] = &SAD_MB_HP_HTFMxh;
6431cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->functionPointer->SAD_MB_HalfPel[2] = &SAD_MB_HP_HTFMyh;
6441cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->functionPointer->SAD_MB_HalfPel[3] = &SAD_MB_HP_HTFMxhyh;
6451cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->sad_extra_info = (void*)(encvid->nrmlz_th);
6461cc31e629e8132df390ae692873c847d1c2f62c0James Dong        offset = encvid->nrmlz_th + 16;
6471cc31e629e8132df390ae692873c847d1c2f62c0James Dong        offset2 = encvid->nrmlz_th + 32;
6481cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
6491cc31e629e8132df390ae692873c847d1c2f62c0James Dong
6501cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset[0] = 0;
6511cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset[1] = lx2 + 2;
6521cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset[2] = 2;
6531cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset[3] = lx2;
6541cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset[4] = lx + 1;
6551cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset[5] = lx3 + 3;
6561cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset[6] = lx + 3;
6571cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset[7] = lx3 + 1;
6581cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset[8] = lx;
6591cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset[9] = lx3 + 2;
6601cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset[10] = lx3 ;
6611cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset[11] = lx + 2 ;
6621cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset[12] = 1;
6631cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset[13] = lx2 + 3;
6641cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset[14] = lx2 + 1;
6651cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset[15] = 3;
6661cc31e629e8132df390ae692873c847d1c2f62c0James Dong
6671cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset2[0] = 0;
6681cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset2[1] = rx2 + 2;
6691cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset2[2] = 2;
6701cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset2[3] = rx2;
6711cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset2[4] = rx + 1;
6721cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset2[5] = rx3 + 3;
6731cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset2[6] = rx + 3;
6741cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset2[7] = rx3 + 1;
6751cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset2[8] = rx;
6761cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset2[9] = rx3 + 2;
6771cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset2[10] = rx3 ;
6781cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset2[11] = rx + 2 ;
6791cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset2[12] = 1;
6801cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset2[13] = rx2 + 3;
6811cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset2[14] = rx2 + 1;
6821cc31e629e8132df390ae692873c847d1c2f62c0James Dong    offset2[15] = 3;
6831cc31e629e8132df390ae692873c847d1c2f62c0James Dong
6841cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return ;
6851cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
6861cc31e629e8132df390ae692873c847d1c2f62c0James Dong
6871cc31e629e8132df390ae692873c847d1c2f62c0James Dongvoid UpdateHTFM(AVCEncObject *encvid, double *newvar, double *exp_lamda, HTFM_Stat *htfm_stat)
6881cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
6891cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (htfm_stat->countbreak == 0)
6901cc31e629e8132df390ae692873c847d1c2f62c0James Dong        htfm_stat->countbreak = 1;
6911cc31e629e8132df390ae692873c847d1c2f62c0James Dong
6921cc31e629e8132df390ae692873c847d1c2f62c0James Dong    newvar[0] = (double)(htfm_stat->abs_dif_mad_avg) / (htfm_stat->countbreak * 16.);
6931cc31e629e8132df390ae692873c847d1c2f62c0James Dong
6941cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (newvar[0] < 0.001)
6951cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
6961cc31e629e8132df390ae692873c847d1c2f62c0James Dong        newvar[0] = 0.001; /* to prevent floating overflow */
6971cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
6981cc31e629e8132df390ae692873c847d1c2f62c0James Dong    exp_lamda[0] =  1 / (newvar[0] * 1.4142136);
6991cc31e629e8132df390ae692873c847d1c2f62c0James Dong    exp_lamda[1] = exp_lamda[0] * 1.5825;
7001cc31e629e8132df390ae692873c847d1c2f62c0James Dong    exp_lamda[2] = exp_lamda[0] * 2.1750;
7011cc31e629e8132df390ae692873c847d1c2f62c0James Dong    exp_lamda[3] = exp_lamda[0] * 3.5065;
7021cc31e629e8132df390ae692873c847d1c2f62c0James Dong    exp_lamda[4] = exp_lamda[0] * 3.1436;
7031cc31e629e8132df390ae692873c847d1c2f62c0James Dong    exp_lamda[5] = exp_lamda[0] * 3.5315;
7041cc31e629e8132df390ae692873c847d1c2f62c0James Dong    exp_lamda[6] = exp_lamda[0] * 3.7449;
7051cc31e629e8132df390ae692873c847d1c2f62c0James Dong    exp_lamda[7] = exp_lamda[0] * 4.5854;
7061cc31e629e8132df390ae692873c847d1c2f62c0James Dong    exp_lamda[8] = exp_lamda[0] * 4.6191;
7071cc31e629e8132df390ae692873c847d1c2f62c0James Dong    exp_lamda[9] = exp_lamda[0] * 5.4041;
7081cc31e629e8132df390ae692873c847d1c2f62c0James Dong    exp_lamda[10] = exp_lamda[0] * 6.5974;
7091cc31e629e8132df390ae692873c847d1c2f62c0James Dong    exp_lamda[11] = exp_lamda[0] * 10.5341;
7101cc31e629e8132df390ae692873c847d1c2f62c0James Dong    exp_lamda[12] = exp_lamda[0] * 10.0719;
7111cc31e629e8132df390ae692873c847d1c2f62c0James Dong    exp_lamda[13] = exp_lamda[0] * 12.0516;
7121cc31e629e8132df390ae692873c847d1c2f62c0James Dong    exp_lamda[14] = exp_lamda[0] * 15.4552;
7131cc31e629e8132df390ae692873c847d1c2f62c0James Dong
7141cc31e629e8132df390ae692873c847d1c2f62c0James Dong    CalcThreshold(HTFM_Pf, exp_lamda, encvid->nrmlz_th);
7151cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return ;
7161cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
7171cc31e629e8132df390ae692873c847d1c2f62c0James Dong
7181cc31e629e8132df390ae692873c847d1c2f62c0James Dong
7191cc31e629e8132df390ae692873c847d1c2f62c0James Dongvoid CalcThreshold(double pf, double exp_lamda[], int nrmlz_th[])
7201cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
7211cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int i;
7221cc31e629e8132df390ae692873c847d1c2f62c0James Dong    double temp[15];
7231cc31e629e8132df390ae692873c847d1c2f62c0James Dong    //  printf("\nLamda: ");
7241cc31e629e8132df390ae692873c847d1c2f62c0James Dong
7251cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* parametric PREMODELling */
7261cc31e629e8132df390ae692873c847d1c2f62c0James Dong    for (i = 0; i < 15; i++)
7271cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
7281cc31e629e8132df390ae692873c847d1c2f62c0James Dong        //    printf("%g ",exp_lamda[i]);
7291cc31e629e8132df390ae692873c847d1c2f62c0James Dong        if (pf < 0.5)
7301cc31e629e8132df390ae692873c847d1c2f62c0James Dong            temp[i] = 1 / exp_lamda[i] * M4VENC_LOG(2 * pf);
7311cc31e629e8132df390ae692873c847d1c2f62c0James Dong        else
7321cc31e629e8132df390ae692873c847d1c2f62c0James Dong            temp[i] = -1 / exp_lamda[i] * M4VENC_LOG(2 * (1 - pf));
7331cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
7341cc31e629e8132df390ae692873c847d1c2f62c0James Dong
7351cc31e629e8132df390ae692873c847d1c2f62c0James Dong    nrmlz_th[15] = 0;
7361cc31e629e8132df390ae692873c847d1c2f62c0James Dong    for (i = 0; i < 15; i++)        /* scale upto no.pixels */
7371cc31e629e8132df390ae692873c847d1c2f62c0James Dong        nrmlz_th[i] = (int)(temp[i] * ((i + 1) << 4) + 0.5);
7381cc31e629e8132df390ae692873c847d1c2f62c0James Dong
7391cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return ;
7401cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
7411cc31e629e8132df390ae692873c847d1c2f62c0James Dong
7421cc31e629e8132df390ae692873c847d1c2f62c0James Dongvoid    HTFMPrepareCurMB_AVC(AVCEncObject *encvid, HTFM_Stat *htfm_stat, uint8 *cur, int pitch)
7431cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
7441cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCCommonObj *video = encvid->common;
7451cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint32 *htfmMB = (uint32*)(encvid->currYMB);
7461cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint8 *ptr, byte;
7471cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int *offset;
7481cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int i;
7491cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint32 word;
7501cc31e629e8132df390ae692873c847d1c2f62c0James Dong
7511cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (((int)video->sliceHdr->frame_num) % 30 == 1)
7521cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
7531cc31e629e8132df390ae692873c847d1c2f62c0James Dong        offset = htfm_stat->offsetArray;
7541cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
7551cc31e629e8132df390ae692873c847d1c2f62c0James Dong    else
7561cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
7571cc31e629e8132df390ae692873c847d1c2f62c0James Dong        offset = encvid->nrmlz_th + 16;
7581cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
7591cc31e629e8132df390ae692873c847d1c2f62c0James Dong
7601cc31e629e8132df390ae692873c847d1c2f62c0James Dong    for (i = 0; i < 16; i++)
7611cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
7621cc31e629e8132df390ae692873c847d1c2f62c0James Dong        ptr = cur + offset[i];
7631cc31e629e8132df390ae692873c847d1c2f62c0James Dong        word = ptr[0];
7641cc31e629e8132df390ae692873c847d1c2f62c0James Dong        byte = ptr[4];
7651cc31e629e8132df390ae692873c847d1c2f62c0James Dong        word |= (byte << 8);
7661cc31e629e8132df390ae692873c847d1c2f62c0James Dong        byte = ptr[8];
7671cc31e629e8132df390ae692873c847d1c2f62c0James Dong        word |= (byte << 16);
7681cc31e629e8132df390ae692873c847d1c2f62c0James Dong        byte = ptr[12];
7691cc31e629e8132df390ae692873c847d1c2f62c0James Dong        word |= (byte << 24);
7701cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *htfmMB++ = word;
7711cc31e629e8132df390ae692873c847d1c2f62c0James Dong
7721cc31e629e8132df390ae692873c847d1c2f62c0James Dong        word = *(ptr += (pitch << 2));
7731cc31e629e8132df390ae692873c847d1c2f62c0James Dong        byte = ptr[4];
7741cc31e629e8132df390ae692873c847d1c2f62c0James Dong        word |= (byte << 8);
7751cc31e629e8132df390ae692873c847d1c2f62c0James Dong        byte = ptr[8];
7761cc31e629e8132df390ae692873c847d1c2f62c0James Dong        word |= (byte << 16);
7771cc31e629e8132df390ae692873c847d1c2f62c0James Dong        byte = ptr[12];
7781cc31e629e8132df390ae692873c847d1c2f62c0James Dong        word |= (byte << 24);
7791cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *htfmMB++ = word;
7801cc31e629e8132df390ae692873c847d1c2f62c0James Dong
7811cc31e629e8132df390ae692873c847d1c2f62c0James Dong        word = *(ptr += (pitch << 2));
7821cc31e629e8132df390ae692873c847d1c2f62c0James Dong        byte = ptr[4];
7831cc31e629e8132df390ae692873c847d1c2f62c0James Dong        word |= (byte << 8);
7841cc31e629e8132df390ae692873c847d1c2f62c0James Dong        byte = ptr[8];
7851cc31e629e8132df390ae692873c847d1c2f62c0James Dong        word |= (byte << 16);
7861cc31e629e8132df390ae692873c847d1c2f62c0James Dong        byte = ptr[12];
7871cc31e629e8132df390ae692873c847d1c2f62c0James Dong        word |= (byte << 24);
7881cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *htfmMB++ = word;
7891cc31e629e8132df390ae692873c847d1c2f62c0James Dong
7901cc31e629e8132df390ae692873c847d1c2f62c0James Dong        word = *(ptr += (pitch << 2));
7911cc31e629e8132df390ae692873c847d1c2f62c0James Dong        byte = ptr[4];
7921cc31e629e8132df390ae692873c847d1c2f62c0James Dong        word |= (byte << 8);
7931cc31e629e8132df390ae692873c847d1c2f62c0James Dong        byte = ptr[8];
7941cc31e629e8132df390ae692873c847d1c2f62c0James Dong        word |= (byte << 16);
7951cc31e629e8132df390ae692873c847d1c2f62c0James Dong        byte = ptr[12];
7961cc31e629e8132df390ae692873c847d1c2f62c0James Dong        word |= (byte << 24);
7971cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *htfmMB++ = word;
7981cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
7991cc31e629e8132df390ae692873c847d1c2f62c0James Dong
8001cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return ;
8011cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
8021cc31e629e8132df390ae692873c847d1c2f62c0James Dong
8031cc31e629e8132df390ae692873c847d1c2f62c0James Dong
8041cc31e629e8132df390ae692873c847d1c2f62c0James Dong#endif // HTFM
8051cc31e629e8132df390ae692873c847d1c2f62c0James Dong
8061cc31e629e8132df390ae692873c847d1c2f62c0James Dongvoid    AVCPrepareCurMB(AVCEncObject *encvid, uint8 *cur, int pitch)
8071cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
8081cc31e629e8132df390ae692873c847d1c2f62c0James Dong    void* tmp = (void*)(encvid->currYMB);
8091cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint32 *currYMB = (uint32*) tmp;
8101cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int i;
8111cc31e629e8132df390ae692873c847d1c2f62c0James Dong
8121cc31e629e8132df390ae692873c847d1c2f62c0James Dong    cur -= pitch;
8131cc31e629e8132df390ae692873c847d1c2f62c0James Dong
8141cc31e629e8132df390ae692873c847d1c2f62c0James Dong    for (i = 0; i < 16; i++)
8151cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
8161cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *currYMB++ = *((uint32*)(cur += pitch));
8171cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *currYMB++ = *((uint32*)(cur + 4));
8181cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *currYMB++ = *((uint32*)(cur + 8));
8191cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *currYMB++ = *((uint32*)(cur + 12));
8201cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
8211cc31e629e8132df390ae692873c847d1c2f62c0James Dong
8221cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return ;
8231cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
8241cc31e629e8132df390ae692873c847d1c2f62c0James Dong
8251cc31e629e8132df390ae692873c847d1c2f62c0James Dong#ifdef FIXED_INTERPRED_MODE
8261cc31e629e8132df390ae692873c847d1c2f62c0James Dong
8271cc31e629e8132df390ae692873c847d1c2f62c0James Dong/* due to the complexity of the predicted motion vector, we may not decide to skip
8281cc31e629e8132df390ae692873c847d1c2f62c0James Donga macroblock here just yet. */
8291cc31e629e8132df390ae692873c847d1c2f62c0James Dong/* We will find the best motion vector and the best intra prediction mode for each block. */
8301cc31e629e8132df390ae692873c847d1c2f62c0James Dong/* output are
8311cc31e629e8132df390ae692873c847d1c2f62c0James Dong    currMB->NumMbPart,  currMB->MbPartWidth, currMB->MbPartHeight,
8321cc31e629e8132df390ae692873c847d1c2f62c0James Dong    currMB->NumSubMbPart[], currMB->SubMbPartWidth[], currMB->SubMbPartHeight,
8331cc31e629e8132df390ae692873c847d1c2f62c0James Dong    currMB->MBPartPredMode[][] (L0 or L1 or BiPred)
8341cc31e629e8132df390ae692873c847d1c2f62c0James Dong    currMB->RefIdx[], currMB->ref_idx_L0[],
8351cc31e629e8132df390ae692873c847d1c2f62c0James Dong    currMB->mvL0[], currMB->mvL1[]
8361cc31e629e8132df390ae692873c847d1c2f62c0James Dong    */
8371cc31e629e8132df390ae692873c847d1c2f62c0James Dong
8381cc31e629e8132df390ae692873c847d1c2f62c0James DongAVCEnc_Status AVCMBMotionSearch(AVCEncObject *encvid, AVCMacroblock *currMB, int mbNum,
8391cc31e629e8132df390ae692873c847d1c2f62c0James Dong                                int num_pass)
8401cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
8411cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCCommonObj *video = encvid->common;
8421cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int mbPartIdx, subMbPartIdx;
8431cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int16 *mv;
8441cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int i;
8451cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int SubMbPartHeight, SubMbPartWidth, NumSubMbPart;
8461cc31e629e8132df390ae692873c847d1c2f62c0James Dong
8471cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* assign value to currMB->MBPartPredMode[][x],subMbMode[],NumSubMbPart[],SubMbPartWidth[],SubMbPartHeight[] */
8481cc31e629e8132df390ae692873c847d1c2f62c0James Dong
8491cc31e629e8132df390ae692873c847d1c2f62c0James Dong    currMB->mbMode = FIXED_INTERPRED_MODE;
8501cc31e629e8132df390ae692873c847d1c2f62c0James Dong    currMB->mb_intra = 0;
8511cc31e629e8132df390ae692873c847d1c2f62c0James Dong
8521cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (currMB->mbMode == AVC_P16)
8531cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
8541cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->NumMbPart = 1;
8551cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->MbPartWidth = 16;
8561cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->MbPartHeight = 16;
8571cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->SubMbPartHeight[0] = 16;
8581cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->SubMbPartWidth[0] = 16;
8591cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->NumSubMbPart[0] =  1;
8601cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
8611cc31e629e8132df390ae692873c847d1c2f62c0James Dong    else if (currMB->mbMode == AVC_P16x8)
8621cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
8631cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->NumMbPart = 2;
8641cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->MbPartWidth = 16;
8651cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->MbPartHeight = 8;
8661cc31e629e8132df390ae692873c847d1c2f62c0James Dong        for (i = 0; i < 2; i++)
8671cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
8681cc31e629e8132df390ae692873c847d1c2f62c0James Dong            currMB->SubMbPartWidth[i] = 16;
8691cc31e629e8132df390ae692873c847d1c2f62c0James Dong            currMB->SubMbPartHeight[i] = 8;
8701cc31e629e8132df390ae692873c847d1c2f62c0James Dong            currMB->NumSubMbPart[i] = 1;
8711cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
8721cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
8731cc31e629e8132df390ae692873c847d1c2f62c0James Dong    else if (currMB->mbMode == AVC_P8x16)
8741cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
8751cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->NumMbPart = 2;
8761cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->MbPartWidth = 8;
8771cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->MbPartHeight = 16;
8781cc31e629e8132df390ae692873c847d1c2f62c0James Dong        for (i = 0; i < 2; i++)
8791cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
8801cc31e629e8132df390ae692873c847d1c2f62c0James Dong            currMB->SubMbPartWidth[i] = 8;
8811cc31e629e8132df390ae692873c847d1c2f62c0James Dong            currMB->SubMbPartHeight[i] = 16;
8821cc31e629e8132df390ae692873c847d1c2f62c0James Dong            currMB->NumSubMbPart[i] = 1;
8831cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
8841cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
8851cc31e629e8132df390ae692873c847d1c2f62c0James Dong    else if (currMB->mbMode == AVC_P8 || currMB->mbMode == AVC_P8ref0)
8861cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
8871cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->NumMbPart = 4;
8881cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->MbPartWidth = 8;
8891cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->MbPartHeight = 8;
8901cc31e629e8132df390ae692873c847d1c2f62c0James Dong        if (FIXED_SUBMB_MODE == AVC_8x8)
8911cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
8921cc31e629e8132df390ae692873c847d1c2f62c0James Dong            SubMbPartHeight = 8;
8931cc31e629e8132df390ae692873c847d1c2f62c0James Dong            SubMbPartWidth = 8;
8941cc31e629e8132df390ae692873c847d1c2f62c0James Dong            NumSubMbPart = 1;
8951cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
8961cc31e629e8132df390ae692873c847d1c2f62c0James Dong        else if (FIXED_SUBMB_MODE == AVC_8x4)
8971cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
8981cc31e629e8132df390ae692873c847d1c2f62c0James Dong            SubMbPartHeight = 4;
8991cc31e629e8132df390ae692873c847d1c2f62c0James Dong            SubMbPartWidth = 8;
9001cc31e629e8132df390ae692873c847d1c2f62c0James Dong            NumSubMbPart = 2;
9011cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
9021cc31e629e8132df390ae692873c847d1c2f62c0James Dong        else if (FIXED_SUBMB_MODE == AVC_4x8)
9031cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
9041cc31e629e8132df390ae692873c847d1c2f62c0James Dong            SubMbPartHeight = 8;
9051cc31e629e8132df390ae692873c847d1c2f62c0James Dong            SubMbPartWidth = 4;
9061cc31e629e8132df390ae692873c847d1c2f62c0James Dong            NumSubMbPart = 2;
9071cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
9081cc31e629e8132df390ae692873c847d1c2f62c0James Dong        else if (FIXED_SUBMB_MODE == AVC_4x4)
9091cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
9101cc31e629e8132df390ae692873c847d1c2f62c0James Dong            SubMbPartHeight = 4;
9111cc31e629e8132df390ae692873c847d1c2f62c0James Dong            SubMbPartWidth = 4;
9121cc31e629e8132df390ae692873c847d1c2f62c0James Dong            NumSubMbPart = 4;
9131cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
9141cc31e629e8132df390ae692873c847d1c2f62c0James Dong
9151cc31e629e8132df390ae692873c847d1c2f62c0James Dong        for (i = 0; i < 4; i++)
9161cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
9171cc31e629e8132df390ae692873c847d1c2f62c0James Dong            currMB->subMbMode[i] = FIXED_SUBMB_MODE;
9181cc31e629e8132df390ae692873c847d1c2f62c0James Dong            currMB->SubMbPartHeight[i] = SubMbPartHeight;
9191cc31e629e8132df390ae692873c847d1c2f62c0James Dong            currMB->SubMbPartWidth[i] = SubMbPartWidth;
9201cc31e629e8132df390ae692873c847d1c2f62c0James Dong            currMB->NumSubMbPart[i] = NumSubMbPart;
9211cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
9221cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
9231cc31e629e8132df390ae692873c847d1c2f62c0James Dong    else /* it's probably intra mode */
9241cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
9251cc31e629e8132df390ae692873c847d1c2f62c0James Dong        return AVCENC_SUCCESS;
9261cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
9271cc31e629e8132df390ae692873c847d1c2f62c0James Dong
9281cc31e629e8132df390ae692873c847d1c2f62c0James Dong    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
9291cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
9301cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->MBPartPredMode[mbPartIdx][0]  = AVC_Pred_L0;
9311cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->ref_idx_L0[mbPartIdx] = FIXED_REF_IDX;
9321cc31e629e8132df390ae692873c847d1c2f62c0James Dong        currMB->RefIdx[mbPartIdx] = video->RefPicList0[FIXED_REF_IDX]->RefIdx;
9331cc31e629e8132df390ae692873c847d1c2f62c0James Dong
9341cc31e629e8132df390ae692873c847d1c2f62c0James Dong        for (subMbPartIdx = 0; subMbPartIdx < 4; subMbPartIdx++)
9351cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
9361cc31e629e8132df390ae692873c847d1c2f62c0James Dong            mv = (int16*)(currMB->mvL0 + (mbPartIdx << 2) + subMbPartIdx);
9371cc31e629e8132df390ae692873c847d1c2f62c0James Dong
9381cc31e629e8132df390ae692873c847d1c2f62c0James Dong            *mv++ = FIXED_MVX;
9391cc31e629e8132df390ae692873c847d1c2f62c0James Dong            *mv = FIXED_MVY;
9401cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
9411cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
9421cc31e629e8132df390ae692873c847d1c2f62c0James Dong
9431cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->min_cost = 0;
9441cc31e629e8132df390ae692873c847d1c2f62c0James Dong
9451cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return AVCENC_SUCCESS;
9461cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
9471cc31e629e8132df390ae692873c847d1c2f62c0James Dong
9481cc31e629e8132df390ae692873c847d1c2f62c0James Dong#else /* perform the search */
9491cc31e629e8132df390ae692873c847d1c2f62c0James Dong
9501cc31e629e8132df390ae692873c847d1c2f62c0James Dong/* This option #1 search is very similar to PV's MPEG4 motion search algorithm.
9511cc31e629e8132df390ae692873c847d1c2f62c0James Dong  The search is done in hierarchical manner from 16x16 MB down to smaller and smaller
9521cc31e629e8132df390ae692873c847d1c2f62c0James Dong  partition. At each level, a decision can be made to stop the search if the expected
9531cc31e629e8132df390ae692873c847d1c2f62c0James Dong  prediction gain is not worth the computation. The decision can also be made at the finest
9541cc31e629e8132df390ae692873c847d1c2f62c0James Dong  level for more fullsearch-like behavior with the price of heavier computation. */
9551cc31e629e8132df390ae692873c847d1c2f62c0James Dongvoid AVCMBMotionSearch(AVCEncObject *encvid, uint8 *cur, uint8 *best_cand[],
9561cc31e629e8132df390ae692873c847d1c2f62c0James Dong                       int i0, int j0, int type_pred, int FS_en, int *hp_guess)
9571cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
9581cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCCommonObj *video = encvid->common;
9591cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCPictureData *currPic = video->currPic;
9601cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCSeqParamSet *currSPS = video->currSeqParams;
9611cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCRateControl *rateCtrl = encvid->rateCtrl;
9621cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCMacroblock *currMB = video->currMB;
9631cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint8 *ref, *cand, *ncand;
9641cc31e629e8132df390ae692873c847d1c2f62c0James Dong    void *extra_info = encvid->sad_extra_info;
9651cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int mbnum = video->mbNum;
9661cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int width = currPic->width; /* 6/12/01, must be multiple of 16 */
9671cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int height = currPic->height;
9681cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCMV *mot16x16 = encvid->mot16x16;
9691cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int (*SAD_Macroblock)(uint8*, uint8*, int, void*) = encvid->functionPointer->SAD_Macroblock;
9701cc31e629e8132df390ae692873c847d1c2f62c0James Dong
9711cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int range = rateCtrl->mvRange;
9721cc31e629e8132df390ae692873c847d1c2f62c0James Dong
9731cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int lx = currPic->pitch; /*  padding */
9741cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int i, j, imin, jmin, ilow, ihigh, jlow, jhigh;
9751cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int d, dmin, dn[9];
9761cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int k;
9771cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int mvx[5], mvy[5];
9781cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int num_can, center_again;
9791cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int last_loc, new_loc = 0;
9801cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int step, max_step = range >> 1;
9811cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int next;
9821cc31e629e8132df390ae692873c847d1c2f62c0James Dong
9831cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int cmvx, cmvy; /* estimated predicted MV */
9841cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int lev_idx;
9851cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int lambda_motion = encvid->lambda_motion;
9861cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint8 *mvbits = encvid->mvbits;
9871cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int mvshift = 2;
9881cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int mvcost;
9891cc31e629e8132df390ae692873c847d1c2f62c0James Dong
9901cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int min_sad = 65535;
9911cc31e629e8132df390ae692873c847d1c2f62c0James Dong
9921cc31e629e8132df390ae692873c847d1c2f62c0James Dong    ref = video->RefPicList0[DEFAULT_REF_IDX]->Sl; /* origin of actual frame */
9931cc31e629e8132df390ae692873c847d1c2f62c0James Dong
9941cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* have to initialize these params, necessary for interprediction part */
9951cc31e629e8132df390ae692873c847d1c2f62c0James Dong    currMB->NumMbPart = 1;
9961cc31e629e8132df390ae692873c847d1c2f62c0James Dong    currMB->SubMbPartHeight[0] = 16;
9971cc31e629e8132df390ae692873c847d1c2f62c0James Dong    currMB->SubMbPartWidth[0] = 16;
9981cc31e629e8132df390ae692873c847d1c2f62c0James Dong    currMB->NumSubMbPart[0] = 1;
9991cc31e629e8132df390ae692873c847d1c2f62c0James Dong    currMB->ref_idx_L0[0] = currMB->ref_idx_L0[1] =
10001cc31e629e8132df390ae692873c847d1c2f62c0James Dong                                currMB->ref_idx_L0[2] = currMB->ref_idx_L0[3] = DEFAULT_REF_IDX;
10011cc31e629e8132df390ae692873c847d1c2f62c0James Dong    currMB->ref_idx_L1[0] = currMB->ref_idx_L1[1] =
10021cc31e629e8132df390ae692873c847d1c2f62c0James Dong                                currMB->ref_idx_L1[2] = currMB->ref_idx_L1[3] = DEFAULT_REF_IDX;
10031cc31e629e8132df390ae692873c847d1c2f62c0James Dong    currMB->RefIdx[0] = currMB->RefIdx[1] =
10041cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            currMB->RefIdx[2] = currMB->RefIdx[3] = video->RefPicList0[DEFAULT_REF_IDX]->RefIdx;
10051cc31e629e8132df390ae692873c847d1c2f62c0James Dong
10061cc31e629e8132df390ae692873c847d1c2f62c0James Dong    cur = encvid->currYMB; /* use smaller memory space for current MB */
10071cc31e629e8132df390ae692873c847d1c2f62c0James Dong
10081cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /*  find limit of the search (adjusting search range)*/
10091cc31e629e8132df390ae692873c847d1c2f62c0James Dong    lev_idx = mapLev2Idx[currSPS->level_idc];
10101cc31e629e8132df390ae692873c847d1c2f62c0James Dong
10111cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* we can make this part dynamic based on previous statistics */
10121cc31e629e8132df390ae692873c847d1c2f62c0James Dong    ilow = i0 - range;
10131cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (i0 - ilow > 2047) /* clip to conform with the standard */
10141cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
10151cc31e629e8132df390ae692873c847d1c2f62c0James Dong        ilow = i0 - 2047;
10161cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
10171cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (ilow < -13)  // change it from -15 to -13 because of 6-tap filter needs extra 2 lines.
10181cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
10191cc31e629e8132df390ae692873c847d1c2f62c0James Dong        ilow = -13;
10201cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
10211cc31e629e8132df390ae692873c847d1c2f62c0James Dong
10221cc31e629e8132df390ae692873c847d1c2f62c0James Dong    ihigh = i0 + range - 1;
10231cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (ihigh - i0 > 2047) /* clip to conform with the standard */
10241cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
10251cc31e629e8132df390ae692873c847d1c2f62c0James Dong        ihigh = i0 + 2047;
10261cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
10271cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (ihigh > width - 3)
10281cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
10291cc31e629e8132df390ae692873c847d1c2f62c0James Dong        ihigh = width - 3;  // change from width-1 to width-3 for the same reason as above
10301cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
10311cc31e629e8132df390ae692873c847d1c2f62c0James Dong
10321cc31e629e8132df390ae692873c847d1c2f62c0James Dong    jlow = j0 - range;
10331cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (j0 - jlow > MaxVmvR[lev_idx] - 1) /* clip to conform with the standard */
10341cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
10351cc31e629e8132df390ae692873c847d1c2f62c0James Dong        jlow = j0 - MaxVmvR[lev_idx] + 1;
10361cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
10371cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (jlow < -13)     // same reason as above
10381cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
10391cc31e629e8132df390ae692873c847d1c2f62c0James Dong        jlow = -13;
10401cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
10411cc31e629e8132df390ae692873c847d1c2f62c0James Dong
10421cc31e629e8132df390ae692873c847d1c2f62c0James Dong    jhigh = j0 + range - 1;
10431cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (jhigh - j0 > MaxVmvR[lev_idx] - 1) /* clip to conform with the standard */
10441cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
10451cc31e629e8132df390ae692873c847d1c2f62c0James Dong        jhigh = j0 + MaxVmvR[lev_idx] - 1;
10461cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
10471cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (jhigh > height - 3) // same reason as above
10481cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
10491cc31e629e8132df390ae692873c847d1c2f62c0James Dong        jhigh = height - 3;
10501cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
10511cc31e629e8132df390ae692873c847d1c2f62c0James Dong
10521cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* find initial motion vector & predicted MV*/
10531cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCCandidateSelection(mvx, mvy, &num_can, i0 >> 4, j0 >> 4, encvid, type_pred, &cmvx, &cmvy);
10541cc31e629e8132df390ae692873c847d1c2f62c0James Dong
10551cc31e629e8132df390ae692873c847d1c2f62c0James Dong    imin = i0;
10561cc31e629e8132df390ae692873c847d1c2f62c0James Dong    jmin = j0; /* needed for fullsearch */
10571cc31e629e8132df390ae692873c847d1c2f62c0James Dong    ncand = ref + i0 + j0 * lx;
10581cc31e629e8132df390ae692873c847d1c2f62c0James Dong
10591cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* for first row of MB, fullsearch can be used */
10601cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (FS_en)
10611cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
10621cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *hp_guess = 0; /* no guess for fast half-pel */
10631cc31e629e8132df390ae692873c847d1c2f62c0James Dong
10641cc31e629e8132df390ae692873c847d1c2f62c0James Dong        dmin =  AVCFullSearch(encvid, ref, cur, &imin, &jmin, ilow, ihigh, jlow, jhigh, cmvx, cmvy);
10651cc31e629e8132df390ae692873c847d1c2f62c0James Dong
10661cc31e629e8132df390ae692873c847d1c2f62c0James Dong        ncand = ref + imin + jmin * lx;
10671cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
10681cc31e629e8132df390ae692873c847d1c2f62c0James Dong    else
10691cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {   /*       fullsearch the top row to only upto (0,3) MB */
10701cc31e629e8132df390ae692873c847d1c2f62c0James Dong        /*       upto 30% complexity saving with the same complexity */
10711cc31e629e8132df390ae692873c847d1c2f62c0James Dong        if (video->PrevRefFrameNum == 0 && j0 == 0 && i0 <= 64 && type_pred != 1)
10721cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
10731cc31e629e8132df390ae692873c847d1c2f62c0James Dong            *hp_guess = 0; /* no guess for fast half-pel */
10741cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dmin =  AVCFullSearch(encvid, ref, cur, &imin, &jmin, ilow, ihigh, jlow, jhigh, cmvx, cmvy);
10751cc31e629e8132df390ae692873c847d1c2f62c0James Dong            ncand = ref + imin + jmin * lx;
10761cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
10771cc31e629e8132df390ae692873c847d1c2f62c0James Dong        else
10781cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
10791cc31e629e8132df390ae692873c847d1c2f62c0James Dong            /************** initialize candidate **************************/
10801cc31e629e8132df390ae692873c847d1c2f62c0James Dong
10811cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dmin = 65535;
10821cc31e629e8132df390ae692873c847d1c2f62c0James Dong
10831cc31e629e8132df390ae692873c847d1c2f62c0James Dong            /* check if all are equal */
10841cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (num_can == ALL_CAND_EQUAL)
10851cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
10861cc31e629e8132df390ae692873c847d1c2f62c0James Dong                i = i0 + mvx[0];
10871cc31e629e8132df390ae692873c847d1c2f62c0James Dong                j = j0 + mvy[0];
10881cc31e629e8132df390ae692873c847d1c2f62c0James Dong
10891cc31e629e8132df390ae692873c847d1c2f62c0James Dong                if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
10901cc31e629e8132df390ae692873c847d1c2f62c0James Dong                {
10911cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    cand = ref + i + j * lx;
10921cc31e629e8132df390ae692873c847d1c2f62c0James Dong
10931cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
10941cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    mvcost = MV_COST(lambda_motion, mvshift, i - i0, j - j0, cmvx, cmvy);
10951cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    d +=  mvcost;
10961cc31e629e8132df390ae692873c847d1c2f62c0James Dong
10971cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    if (d < dmin)
10981cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    {
10991cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        dmin = d;
11001cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        imin = i;
11011cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        jmin = j;
11021cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        ncand = cand;
11031cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        min_sad = d - mvcost; // for rate control
11041cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    }
11051cc31e629e8132df390ae692873c847d1c2f62c0James Dong                }
11061cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
11071cc31e629e8132df390ae692873c847d1c2f62c0James Dong            else
11081cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
11091cc31e629e8132df390ae692873c847d1c2f62c0James Dong                /************** evaluate unique candidates **********************/
11101cc31e629e8132df390ae692873c847d1c2f62c0James Dong                for (k = 0; k < num_can; k++)
11111cc31e629e8132df390ae692873c847d1c2f62c0James Dong                {
11121cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    i = i0 + mvx[k];
11131cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    j = j0 + mvy[k];
11141cc31e629e8132df390ae692873c847d1c2f62c0James Dong
11151cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
11161cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    {
11171cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        cand = ref + i + j * lx;
11181cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
11191cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        mvcost = MV_COST(lambda_motion, mvshift, i - i0, j - j0, cmvx, cmvy);
11201cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        d +=  mvcost;
11211cc31e629e8132df390ae692873c847d1c2f62c0James Dong
11221cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        if (d < dmin)
11231cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        {
11241cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            dmin = d;
11251cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            imin = i;
11261cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            jmin = j;
11271cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            ncand = cand;
11281cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            min_sad = d - mvcost; // for rate control
11291cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        }
11301cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    }
11311cc31e629e8132df390ae692873c847d1c2f62c0James Dong                }
11321cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
11331cc31e629e8132df390ae692873c847d1c2f62c0James Dong
11341cc31e629e8132df390ae692873c847d1c2f62c0James Dong            /******************* local refinement ***************************/
11351cc31e629e8132df390ae692873c847d1c2f62c0James Dong            center_again = 0;
11361cc31e629e8132df390ae692873c847d1c2f62c0James Dong            last_loc = new_loc = 0;
11371cc31e629e8132df390ae692873c847d1c2f62c0James Dong            //          ncand = ref + jmin*lx + imin;  /* center of the search */
11381cc31e629e8132df390ae692873c847d1c2f62c0James Dong            step = 0;
11391cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[0] = dmin;
11401cc31e629e8132df390ae692873c847d1c2f62c0James Dong            while (!center_again && step <= max_step)
11411cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
11421cc31e629e8132df390ae692873c847d1c2f62c0James Dong
11431cc31e629e8132df390ae692873c847d1c2f62c0James Dong                AVCMoveNeighborSAD(dn, last_loc);
11441cc31e629e8132df390ae692873c847d1c2f62c0James Dong
11451cc31e629e8132df390ae692873c847d1c2f62c0James Dong                center_again = 1;
11461cc31e629e8132df390ae692873c847d1c2f62c0James Dong                i = imin;
11471cc31e629e8132df390ae692873c847d1c2f62c0James Dong                j = jmin - 1;
11481cc31e629e8132df390ae692873c847d1c2f62c0James Dong                cand = ref + i + j * lx;
11491cc31e629e8132df390ae692873c847d1c2f62c0James Dong
11501cc31e629e8132df390ae692873c847d1c2f62c0James Dong                /*  starting from [0,-1] */
11511cc31e629e8132df390ae692873c847d1c2f62c0James Dong                /* spiral check one step at a time*/
11521cc31e629e8132df390ae692873c847d1c2f62c0James Dong                for (k = 2; k <= 8; k += 2)
11531cc31e629e8132df390ae692873c847d1c2f62c0James Dong                {
11541cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    if (!tab_exclude[last_loc][k]) /* exclude last step computation */
11551cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    {       /* not already computed */
11561cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
11571cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        {
11581cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
11591cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            mvcost = MV_COST(lambda_motion, mvshift, i - i0, j - j0, cmvx, cmvy);
11601cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            d += mvcost;
11611cc31e629e8132df390ae692873c847d1c2f62c0James Dong
11621cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            dn[k] = d; /* keep it for half pel use */
11631cc31e629e8132df390ae692873c847d1c2f62c0James Dong
11641cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            if (d < dmin)
11651cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            {
11661cc31e629e8132df390ae692873c847d1c2f62c0James Dong                                ncand = cand;
11671cc31e629e8132df390ae692873c847d1c2f62c0James Dong                                dmin = d;
11681cc31e629e8132df390ae692873c847d1c2f62c0James Dong                                imin = i;
11691cc31e629e8132df390ae692873c847d1c2f62c0James Dong                                jmin = j;
11701cc31e629e8132df390ae692873c847d1c2f62c0James Dong                                center_again = 0;
11711cc31e629e8132df390ae692873c847d1c2f62c0James Dong                                new_loc = k;
11721cc31e629e8132df390ae692873c847d1c2f62c0James Dong                                min_sad = d - mvcost; // for rate control
11731cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            }
11741cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        }
11751cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    }
11761cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    if (k == 8)  /* end side search*/
11771cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    {
11781cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        if (!center_again)
11791cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        {
11801cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            k = -1; /* start diagonal search */
11811cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            cand -= lx;
11821cc31e629e8132df390ae692873c847d1c2f62c0James Dong                            j--;
11831cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        }
11841cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    }
11851cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    else
11861cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    {
11871cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        next = refine_next[k][0];
11881cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        i += next;
11891cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        cand += next;
11901cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        next = refine_next[k][1];
11911cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        j += next;
11921cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        cand += lx * next;
11931cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    }
11941cc31e629e8132df390ae692873c847d1c2f62c0James Dong                }
11951cc31e629e8132df390ae692873c847d1c2f62c0James Dong                last_loc = new_loc;
11961cc31e629e8132df390ae692873c847d1c2f62c0James Dong                step ++;
11971cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
11981cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (!center_again)
11991cc31e629e8132df390ae692873c847d1c2f62c0James Dong                AVCMoveNeighborSAD(dn, last_loc);
12001cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12011cc31e629e8132df390ae692873c847d1c2f62c0James Dong            *hp_guess = AVCFindMin(dn);
12021cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12031cc31e629e8132df390ae692873c847d1c2f62c0James Dong            encvid->rateCtrl->MADofMB[mbnum] = min_sad / 256.0;
12041cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
12051cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
12061cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12071cc31e629e8132df390ae692873c847d1c2f62c0James Dong    mot16x16[mbnum].sad = dmin;
12081cc31e629e8132df390ae692873c847d1c2f62c0James Dong    mot16x16[mbnum].x = (imin - i0) << 2;
12091cc31e629e8132df390ae692873c847d1c2f62c0James Dong    mot16x16[mbnum].y = (jmin - j0) << 2;
12101cc31e629e8132df390ae692873c847d1c2f62c0James Dong    best_cand[0] = ncand;
12111cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12121cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (rateCtrl->subPelEnable) // always enable half-pel search
12131cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
12141cc31e629e8132df390ae692873c847d1c2f62c0James Dong        /* find half-pel resolution motion vector */
12151cc31e629e8132df390ae692873c847d1c2f62c0James Dong        min_sad = AVCFindHalfPelMB(encvid, cur, mot16x16 + mbnum, best_cand[0], i0, j0, *hp_guess, cmvx, cmvy);
12161cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12171cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->rateCtrl->MADofMB[mbnum] = min_sad / 256.0;
12181cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12191cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12201cc31e629e8132df390ae692873c847d1c2f62c0James Dong        if (encvid->best_qpel_pos == -1)
12211cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
12221cc31e629e8132df390ae692873c847d1c2f62c0James Dong            ncand = encvid->hpel_cand[encvid->best_hpel_pos];
12231cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
12241cc31e629e8132df390ae692873c847d1c2f62c0James Dong        else
12251cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
12261cc31e629e8132df390ae692873c847d1c2f62c0James Dong            ncand = encvid->qpel_cand[encvid->best_qpel_pos];
12271cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
12281cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
12291cc31e629e8132df390ae692873c847d1c2f62c0James Dong    else
12301cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
12311cc31e629e8132df390ae692873c847d1c2f62c0James Dong        encvid->rateCtrl->MADofMB[mbnum] = min_sad / 256.0;
12321cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
12331cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12341cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /** do motion comp here for now */
12351cc31e629e8132df390ae692873c847d1c2f62c0James Dong    ref = currPic->Sl + i0 + j0 * lx;
12361cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* copy from the best result to current Picture */
12371cc31e629e8132df390ae692873c847d1c2f62c0James Dong    for (j = 0; j < 16; j++)
12381cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
12391cc31e629e8132df390ae692873c847d1c2f62c0James Dong        for (i = 0; i < 16; i++)
12401cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
12411cc31e629e8132df390ae692873c847d1c2f62c0James Dong            *ref++ = *ncand++;
12421cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
12431cc31e629e8132df390ae692873c847d1c2f62c0James Dong        ref += (lx - 16);
12441cc31e629e8132df390ae692873c847d1c2f62c0James Dong        ncand += 8;
12451cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
12461cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12471cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return ;
12481cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
12491cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12501cc31e629e8132df390ae692873c847d1c2f62c0James Dong#endif
12511cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12521cc31e629e8132df390ae692873c847d1c2f62c0James Dong/*===============================================================================
12531cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Function:   AVCFullSearch
12541cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Date:       09/16/2000
12551cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Purpose:    Perform full-search motion estimation over the range of search
12561cc31e629e8132df390ae692873c847d1c2f62c0James Dong                region in a spiral-outward manner.
12571cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Input/Output:   VideoEncData, current Vol, previou Vop, pointer to the left corner of
12581cc31e629e8132df390ae692873c847d1c2f62c0James Dong                current VOP, current coord (also output), boundaries.
12591cc31e629e8132df390ae692873c847d1c2f62c0James Dong===============================================================================*/
12601cc31e629e8132df390ae692873c847d1c2f62c0James Dongint AVCFullSearch(AVCEncObject *encvid, uint8 *prev, uint8 *cur,
12611cc31e629e8132df390ae692873c847d1c2f62c0James Dong                  int *imin, int *jmin, int ilow, int ihigh, int jlow, int jhigh,
12621cc31e629e8132df390ae692873c847d1c2f62c0James Dong                  int cmvx, int cmvy)
12631cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
12641cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int range = encvid->rateCtrl->mvRange;
12651cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCPictureData *currPic = encvid->common->currPic;
12661cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint8 *cand;
12671cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int i, j, k, l;
12681cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int d, dmin;
12691cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int i0 = *imin; /* current position */
12701cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int j0 = *jmin;
12711cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int (*SAD_Macroblock)(uint8*, uint8*, int, void*) = encvid->functionPointer->SAD_Macroblock;
12721cc31e629e8132df390ae692873c847d1c2f62c0James Dong    void *extra_info = encvid->sad_extra_info;
12731cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int lx = currPic->pitch; /* with padding */
12741cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12751cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int offset = i0 + j0 * lx;
12761cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12771cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int lambda_motion = encvid->lambda_motion;
12781cc31e629e8132df390ae692873c847d1c2f62c0James Dong    uint8 *mvbits = encvid->mvbits;
12791cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int mvshift = 2;
12801cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int mvcost;
12811cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int min_sad;
12821cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12831cc31e629e8132df390ae692873c847d1c2f62c0James Dong    cand = prev + offset;
12841cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12851cc31e629e8132df390ae692873c847d1c2f62c0James Dong    dmin  = (*SAD_Macroblock)(cand, cur, (65535 << 16) | lx, (void*)extra_info);
12861cc31e629e8132df390ae692873c847d1c2f62c0James Dong    mvcost = MV_COST(lambda_motion, mvshift, 0, 0, cmvx, cmvy);
12871cc31e629e8132df390ae692873c847d1c2f62c0James Dong    min_sad = dmin;
12881cc31e629e8132df390ae692873c847d1c2f62c0James Dong    dmin += mvcost;
12891cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12901cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* perform spiral search */
12911cc31e629e8132df390ae692873c847d1c2f62c0James Dong    for (k = 1; k <= range; k++)
12921cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
12931cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12941cc31e629e8132df390ae692873c847d1c2f62c0James Dong        i = i0 - k;
12951cc31e629e8132df390ae692873c847d1c2f62c0James Dong        j = j0 - k;
12961cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12971cc31e629e8132df390ae692873c847d1c2f62c0James Dong        cand = prev + i + j * lx;
12981cc31e629e8132df390ae692873c847d1c2f62c0James Dong
12991cc31e629e8132df390ae692873c847d1c2f62c0James Dong        for (l = 0; l < 8*k; l++)
13001cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
13011cc31e629e8132df390ae692873c847d1c2f62c0James Dong            /* no need for boundary checking again */
13021cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
13031cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
13041cc31e629e8132df390ae692873c847d1c2f62c0James Dong                d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, (void*)extra_info);
13051cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvcost = MV_COST(lambda_motion, mvshift, i - i0, j - j0, cmvx, cmvy);
13061cc31e629e8132df390ae692873c847d1c2f62c0James Dong                d +=  mvcost;
13071cc31e629e8132df390ae692873c847d1c2f62c0James Dong
13081cc31e629e8132df390ae692873c847d1c2f62c0James Dong                if (d < dmin)
13091cc31e629e8132df390ae692873c847d1c2f62c0James Dong                {
13101cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    dmin = d;
13111cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    *imin = i;
13121cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    *jmin = j;
13131cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    min_sad = d - mvcost;
13141cc31e629e8132df390ae692873c847d1c2f62c0James Dong                }
13151cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
13161cc31e629e8132df390ae692873c847d1c2f62c0James Dong
13171cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (l < (k << 1))
13181cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
13191cc31e629e8132df390ae692873c847d1c2f62c0James Dong                i++;
13201cc31e629e8132df390ae692873c847d1c2f62c0James Dong                cand++;
13211cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
13221cc31e629e8132df390ae692873c847d1c2f62c0James Dong            else if (l < (k << 2))
13231cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
13241cc31e629e8132df390ae692873c847d1c2f62c0James Dong                j++;
13251cc31e629e8132df390ae692873c847d1c2f62c0James Dong                cand += lx;
13261cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
13271cc31e629e8132df390ae692873c847d1c2f62c0James Dong            else if (l < ((k << 2) + (k << 1)))
13281cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
13291cc31e629e8132df390ae692873c847d1c2f62c0James Dong                i--;
13301cc31e629e8132df390ae692873c847d1c2f62c0James Dong                cand--;
13311cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
13321cc31e629e8132df390ae692873c847d1c2f62c0James Dong            else
13331cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
13341cc31e629e8132df390ae692873c847d1c2f62c0James Dong                j--;
13351cc31e629e8132df390ae692873c847d1c2f62c0James Dong                cand -= lx;
13361cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
13371cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
13381cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
13391cc31e629e8132df390ae692873c847d1c2f62c0James Dong
13401cc31e629e8132df390ae692873c847d1c2f62c0James Dong    encvid->rateCtrl->MADofMB[encvid->common->mbNum] = (min_sad / 256.0); // for rate control
13411cc31e629e8132df390ae692873c847d1c2f62c0James Dong
13421cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return dmin;
13431cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
13441cc31e629e8132df390ae692873c847d1c2f62c0James Dong
13451cc31e629e8132df390ae692873c847d1c2f62c0James Dong/*===============================================================================
13461cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Function:   AVCCandidateSelection
13471cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Date:       09/16/2000
13481cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Purpose:    Fill up the list of candidate using spatio-temporal correlation
13491cc31e629e8132df390ae692873c847d1c2f62c0James Dong                among neighboring blocks.
13501cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Input/Output:   type_pred = 0: first pass, 1: second pass, or no SCD
13511cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Modified:   , 09/23/01, get rid of redundant candidates before passing back.
13521cc31e629e8132df390ae692873c847d1c2f62c0James Dong                , 09/11/07, added return for modified predicted MV, this will be
13531cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    needed for both fast search and fullsearch.
13541cc31e629e8132df390ae692873c847d1c2f62c0James Dong===============================================================================*/
13551cc31e629e8132df390ae692873c847d1c2f62c0James Dong
13561cc31e629e8132df390ae692873c847d1c2f62c0James Dongvoid AVCCandidateSelection(int *mvx, int *mvy, int *num_can, int imb, int jmb,
13571cc31e629e8132df390ae692873c847d1c2f62c0James Dong                           AVCEncObject *encvid, int type_pred, int *cmvx, int *cmvy)
13581cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
13591cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCCommonObj *video = encvid->common;
13601cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCMV *mot16x16 = encvid->mot16x16;
13611cc31e629e8132df390ae692873c847d1c2f62c0James Dong    AVCMV *pmot;
13621cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int mbnum = video->mbNum;
13631cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int mbwidth = video->PicWidthInMbs;
13641cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int mbheight = video->PicHeightInMbs;
13651cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int i, j, same, num1;
13661cc31e629e8132df390ae692873c847d1c2f62c0James Dong
13671cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* this part is for predicted MV */
13681cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int pmvA_x = 0, pmvA_y = 0, pmvB_x = 0, pmvB_y = 0, pmvC_x = 0, pmvC_y = 0;
13691cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int availA = 0, availB = 0, availC = 0;
13701cc31e629e8132df390ae692873c847d1c2f62c0James Dong
13711cc31e629e8132df390ae692873c847d1c2f62c0James Dong    *num_can = 0;
13721cc31e629e8132df390ae692873c847d1c2f62c0James Dong
13731cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (video->PrevRefFrameNum != 0) // previous frame is an IDR frame
13741cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
13751cc31e629e8132df390ae692873c847d1c2f62c0James Dong        /* Spatio-Temporal Candidate (five candidates) */
13761cc31e629e8132df390ae692873c847d1c2f62c0James Dong        if (type_pred == 0) /* first pass */
13771cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
13781cc31e629e8132df390ae692873c847d1c2f62c0James Dong            pmot = &mot16x16[mbnum]; /* same coordinate previous frame */
13791cc31e629e8132df390ae692873c847d1c2f62c0James Dong            mvx[(*num_can)] = (pmot->x) >> 2;
13801cc31e629e8132df390ae692873c847d1c2f62c0James Dong            mvy[(*num_can)++] = (pmot->y) >> 2;
13811cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (imb >= (mbwidth >> 1) && imb > 0)  /*left neighbor previous frame */
13821cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
13831cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum-1];
13841cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvx[(*num_can)] = (pmot->x) >> 2;
13851cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvy[(*num_can)++] = (pmot->y) >> 2;
13861cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
13871cc31e629e8132df390ae692873c847d1c2f62c0James Dong            else if (imb + 1 < mbwidth)   /*right neighbor previous frame */
13881cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
13891cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum+1];
13901cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvx[(*num_can)] = (pmot->x) >> 2;
13911cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvy[(*num_can)++] = (pmot->y) >> 2;
13921cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
13931cc31e629e8132df390ae692873c847d1c2f62c0James Dong
13941cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (jmb < mbheight - 1)  /*bottom neighbor previous frame */
13951cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
13961cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum+mbwidth];
13971cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvx[(*num_can)] = (pmot->x) >> 2;
13981cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvy[(*num_can)++] = (pmot->y) >> 2;
13991cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
14001cc31e629e8132df390ae692873c847d1c2f62c0James Dong            else if (jmb > 0)   /*upper neighbor previous frame */
14011cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
14021cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum-mbwidth];
14031cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvx[(*num_can)] = (pmot->x) >> 2;
14041cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvy[(*num_can)++] = (pmot->y) >> 2;
14051cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
14061cc31e629e8132df390ae692873c847d1c2f62c0James Dong
14071cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (imb > 0 && jmb > 0)  /* upper-left neighbor current frame*/
14081cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
14091cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum-mbwidth-1];
14101cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvx[(*num_can)] = (pmot->x) >> 2;
14111cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvy[(*num_can)++] = (pmot->y) >> 2;
14121cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
14131cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (jmb > 0 && imb < mbheight - 1)  /* upper right neighbor current frame*/
14141cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
14151cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum-mbwidth+1];
14161cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvx[(*num_can)] = (pmot->x) >> 2;
14171cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvy[(*num_can)++] = (pmot->y) >> 2;
14181cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
14191cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
14201cc31e629e8132df390ae692873c847d1c2f62c0James Dong        else    /* second pass */
14211cc31e629e8132df390ae692873c847d1c2f62c0James Dong            /* original ST1 algorithm */
14221cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
14231cc31e629e8132df390ae692873c847d1c2f62c0James Dong            pmot = &mot16x16[mbnum]; /* same coordinate previous frame */
14241cc31e629e8132df390ae692873c847d1c2f62c0James Dong            mvx[(*num_can)] = (pmot->x) >> 2;
14251cc31e629e8132df390ae692873c847d1c2f62c0James Dong            mvy[(*num_can)++] = (pmot->y) >> 2;
14261cc31e629e8132df390ae692873c847d1c2f62c0James Dong
14271cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (imb > 0)  /*left neighbor current frame */
14281cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
14291cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum-1];
14301cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvx[(*num_can)] = (pmot->x) >> 2;
14311cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvy[(*num_can)++] = (pmot->y) >> 2;
14321cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
14331cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (jmb > 0)  /*upper neighbor current frame */
14341cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
14351cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum-mbwidth];
14361cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvx[(*num_can)] = (pmot->x) >> 2;
14371cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvy[(*num_can)++] = (pmot->y) >> 2;
14381cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
14391cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (imb < mbwidth - 1)  /*right neighbor previous frame */
14401cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
14411cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum+1];
14421cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvx[(*num_can)] = (pmot->x) >> 2;
14431cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvy[(*num_can)++] = (pmot->y) >> 2;
14441cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
14451cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (jmb < mbheight - 1)  /*bottom neighbor previous frame */
14461cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
14471cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum+mbwidth];
14481cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvx[(*num_can)] = (pmot->x) >> 2;
14491cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvy[(*num_can)++] = (pmot->y) >> 2;
14501cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
14511cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
14521cc31e629e8132df390ae692873c847d1c2f62c0James Dong
14531cc31e629e8132df390ae692873c847d1c2f62c0James Dong        /* get predicted MV */
14541cc31e629e8132df390ae692873c847d1c2f62c0James Dong        if (imb > 0)    /* get MV from left (A) neighbor either on current or previous frame */
14551cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
14561cc31e629e8132df390ae692873c847d1c2f62c0James Dong            availA = 1;
14571cc31e629e8132df390ae692873c847d1c2f62c0James Dong            pmot = &mot16x16[mbnum-1];
14581cc31e629e8132df390ae692873c847d1c2f62c0James Dong            pmvA_x = pmot->x;
14591cc31e629e8132df390ae692873c847d1c2f62c0James Dong            pmvA_y = pmot->y;
14601cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
14611cc31e629e8132df390ae692873c847d1c2f62c0James Dong
14621cc31e629e8132df390ae692873c847d1c2f62c0James Dong        if (jmb > 0) /* get MV from top (B) neighbor either on current or previous frame */
14631cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
14641cc31e629e8132df390ae692873c847d1c2f62c0James Dong            availB = 1;
14651cc31e629e8132df390ae692873c847d1c2f62c0James Dong            pmot = &mot16x16[mbnum-mbwidth];
14661cc31e629e8132df390ae692873c847d1c2f62c0James Dong            pmvB_x = pmot->x;
14671cc31e629e8132df390ae692873c847d1c2f62c0James Dong            pmvB_y = pmot->y;
14681cc31e629e8132df390ae692873c847d1c2f62c0James Dong
14691cc31e629e8132df390ae692873c847d1c2f62c0James Dong            availC = 1;
14701cc31e629e8132df390ae692873c847d1c2f62c0James Dong
14711cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (imb < mbwidth - 1) /* get MV from top-right (C) neighbor of current frame */
14721cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
14731cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum-mbwidth+1];
14741cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
14751cc31e629e8132df390ae692873c847d1c2f62c0James Dong            else /* get MV from top-left (D) neighbor of current frame */
14761cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
14771cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum-mbwidth-1];
14781cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
14791cc31e629e8132df390ae692873c847d1c2f62c0James Dong            pmvC_x = pmot->x;
14801cc31e629e8132df390ae692873c847d1c2f62c0James Dong            pmvC_y = pmot->y;
14811cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
14821cc31e629e8132df390ae692873c847d1c2f62c0James Dong
14831cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
14841cc31e629e8132df390ae692873c847d1c2f62c0James Dong    else  /* only Spatial Candidate (four candidates)*/
14851cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
14861cc31e629e8132df390ae692873c847d1c2f62c0James Dong        if (type_pred == 0) /*first pass*/
14871cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
14881cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (imb > 1)  /* neighbor two blocks away to the left */
14891cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
14901cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum-2];
14911cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvx[(*num_can)] = (pmot->x) >> 2;
14921cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvy[(*num_can)++] = (pmot->y) >> 2;
14931cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
14941cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (imb > 0 && jmb > 0)  /* upper-left neighbor */
14951cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
14961cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum-mbwidth-1];
14971cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvx[(*num_can)] = (pmot->x) >> 2;
14981cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvy[(*num_can)++] = (pmot->y) >> 2;
14991cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
15001cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (jmb > 0 && imb < mbheight - 1)  /* upper right neighbor */
15011cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
15021cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum-mbwidth+1];
15031cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvx[(*num_can)] = (pmot->x) >> 2;
15041cc31e629e8132df390ae692873c847d1c2f62c0James Dong                mvy[(*num_can)++] = (pmot->y) >> 2;
15051cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
15061cc31e629e8132df390ae692873c847d1c2f62c0James Dong
15071cc31e629e8132df390ae692873c847d1c2f62c0James Dong            /* get predicted MV */
15081cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (imb > 1)    /* get MV from 2nd left (A) neighbor either of current frame */
15091cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
15101cc31e629e8132df390ae692873c847d1c2f62c0James Dong                availA = 1;
15111cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum-2];
15121cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmvA_x = pmot->x;
15131cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmvA_y = pmot->y;
15141cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
15151cc31e629e8132df390ae692873c847d1c2f62c0James Dong
15161cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (jmb > 0 && imb > 0) /* get MV from top-left (B) neighbor of current frame */
15171cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
15181cc31e629e8132df390ae692873c847d1c2f62c0James Dong                availB = 1;
15191cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum-mbwidth-1];
15201cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmvB_x = pmot->x;
15211cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmvB_y = pmot->y;
15221cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
15231cc31e629e8132df390ae692873c847d1c2f62c0James Dong
15241cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (jmb > 0 && imb < mbwidth - 1)
15251cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
15261cc31e629e8132df390ae692873c847d1c2f62c0James Dong                availC = 1;
15271cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum-mbwidth+1];
15281cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmvC_x = pmot->x;
15291cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmvC_y = pmot->y;
15301cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
15311cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
15321cc31e629e8132df390ae692873c847d1c2f62c0James Dong//#ifdef SCENE_CHANGE_DETECTION
15331cc31e629e8132df390ae692873c847d1c2f62c0James Dong        /* second pass (ST2 algorithm)*/
15341cc31e629e8132df390ae692873c847d1c2f62c0James Dong        else
15351cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
15361cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (type_pred == 1) /*  4/7/01 */
15371cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
15381cc31e629e8132df390ae692873c847d1c2f62c0James Dong                if (imb > 0)  /*left neighbor current frame */
15391cc31e629e8132df390ae692873c847d1c2f62c0James Dong                {
15401cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    pmot = &mot16x16[mbnum-1];
15411cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    mvx[(*num_can)] = (pmot->x) >> 2;
15421cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    mvy[(*num_can)++] = (pmot->y) >> 2;
15431cc31e629e8132df390ae692873c847d1c2f62c0James Dong                }
15441cc31e629e8132df390ae692873c847d1c2f62c0James Dong                if (jmb > 0)  /*upper neighbor current frame */
15451cc31e629e8132df390ae692873c847d1c2f62c0James Dong                {
15461cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    pmot = &mot16x16[mbnum-mbwidth];
15471cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    mvx[(*num_can)] = (pmot->x) >> 2;
15481cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    mvy[(*num_can)++] = (pmot->y) >> 2;
15491cc31e629e8132df390ae692873c847d1c2f62c0James Dong                }
15501cc31e629e8132df390ae692873c847d1c2f62c0James Dong                if (imb < mbwidth - 1)  /*right neighbor current frame */
15511cc31e629e8132df390ae692873c847d1c2f62c0James Dong                {
15521cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    pmot = &mot16x16[mbnum+1];
15531cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    mvx[(*num_can)] = (pmot->x) >> 2;
15541cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    mvy[(*num_can)++] = (pmot->y) >> 2;
15551cc31e629e8132df390ae692873c847d1c2f62c0James Dong                }
15561cc31e629e8132df390ae692873c847d1c2f62c0James Dong                if (jmb < mbheight - 1)  /*bottom neighbor current frame */
15571cc31e629e8132df390ae692873c847d1c2f62c0James Dong                {
15581cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    pmot = &mot16x16[mbnum+mbwidth];
15591cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    mvx[(*num_can)] = (pmot->x) >> 2;
15601cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    mvy[(*num_can)++] = (pmot->y) >> 2;
15611cc31e629e8132df390ae692873c847d1c2f62c0James Dong                }
15621cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
15631cc31e629e8132df390ae692873c847d1c2f62c0James Dong            //#else
15641cc31e629e8132df390ae692873c847d1c2f62c0James Dong            else /* original ST1 algorithm */
15651cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
15661cc31e629e8132df390ae692873c847d1c2f62c0James Dong                if (imb > 0)  /*left neighbor current frame */
15671cc31e629e8132df390ae692873c847d1c2f62c0James Dong                {
15681cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    pmot = &mot16x16[mbnum-1];
15691cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    mvx[(*num_can)] = (pmot->x) >> 2;
15701cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    mvy[(*num_can)++] = (pmot->y) >> 2;
15711cc31e629e8132df390ae692873c847d1c2f62c0James Dong
15721cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    if (jmb > 0)  /*upper-left neighbor current frame */
15731cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    {
15741cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        pmot = &mot16x16[mbnum-mbwidth-1];
15751cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        mvx[(*num_can)] = (pmot->x) >> 2;
15761cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        mvy[(*num_can)++] = (pmot->y) >> 2;
15771cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    }
15781cc31e629e8132df390ae692873c847d1c2f62c0James Dong
15791cc31e629e8132df390ae692873c847d1c2f62c0James Dong                }
15801cc31e629e8132df390ae692873c847d1c2f62c0James Dong                if (jmb > 0)  /*upper neighbor current frame */
15811cc31e629e8132df390ae692873c847d1c2f62c0James Dong                {
15821cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    pmot = &mot16x16[mbnum-mbwidth];
15831cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    mvx[(*num_can)] = (pmot->x) >> 2;
15841cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    mvy[(*num_can)++] = (pmot->y) >> 2;
15851cc31e629e8132df390ae692873c847d1c2f62c0James Dong
15861cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    if (imb < mbheight - 1)  /*upper-right neighbor current frame */
15871cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    {
15881cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        pmot = &mot16x16[mbnum-mbwidth+1];
15891cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        mvx[(*num_can)] = (pmot->x) >> 2;
15901cc31e629e8132df390ae692873c847d1c2f62c0James Dong                        mvy[(*num_can)++] = (pmot->y) >> 2;
15911cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    }
15921cc31e629e8132df390ae692873c847d1c2f62c0James Dong                }
15931cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
15941cc31e629e8132df390ae692873c847d1c2f62c0James Dong
15951cc31e629e8132df390ae692873c847d1c2f62c0James Dong            /* get predicted MV */
15961cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (imb > 0)    /* get MV from left (A) neighbor either on current or previous frame */
15971cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
15981cc31e629e8132df390ae692873c847d1c2f62c0James Dong                availA = 1;
15991cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum-1];
16001cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmvA_x = pmot->x;
16011cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmvA_y = pmot->y;
16021cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
16031cc31e629e8132df390ae692873c847d1c2f62c0James Dong
16041cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (jmb > 0) /* get MV from top (B) neighbor either on current or previous frame */
16051cc31e629e8132df390ae692873c847d1c2f62c0James Dong            {
16061cc31e629e8132df390ae692873c847d1c2f62c0James Dong                availB = 1;
16071cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmot = &mot16x16[mbnum-mbwidth];
16081cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmvB_x = pmot->x;
16091cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmvB_y = pmot->y;
16101cc31e629e8132df390ae692873c847d1c2f62c0James Dong
16111cc31e629e8132df390ae692873c847d1c2f62c0James Dong                availC = 1;
16121cc31e629e8132df390ae692873c847d1c2f62c0James Dong
16131cc31e629e8132df390ae692873c847d1c2f62c0James Dong                if (imb < mbwidth - 1) /* get MV from top-right (C) neighbor of current frame */
16141cc31e629e8132df390ae692873c847d1c2f62c0James Dong                {
16151cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    pmot = &mot16x16[mbnum-mbwidth+1];
16161cc31e629e8132df390ae692873c847d1c2f62c0James Dong                }
16171cc31e629e8132df390ae692873c847d1c2f62c0James Dong                else /* get MV from top-left (D) neighbor of current frame */
16181cc31e629e8132df390ae692873c847d1c2f62c0James Dong                {
16191cc31e629e8132df390ae692873c847d1c2f62c0James Dong                    pmot = &mot16x16[mbnum-mbwidth-1];
16201cc31e629e8132df390ae692873c847d1c2f62c0James Dong                }
16211cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmvC_x = pmot->x;
16221cc31e629e8132df390ae692873c847d1c2f62c0James Dong                pmvC_y = pmot->y;
16231cc31e629e8132df390ae692873c847d1c2f62c0James Dong            }
16241cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
16251cc31e629e8132df390ae692873c847d1c2f62c0James Dong//#endif
16261cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
16271cc31e629e8132df390ae692873c847d1c2f62c0James Dong
16281cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /*  3/23/01, remove redundant candidate (possible k-mean) */
16291cc31e629e8132df390ae692873c847d1c2f62c0James Dong    num1 = *num_can;
16301cc31e629e8132df390ae692873c847d1c2f62c0James Dong    *num_can = 1;
16311cc31e629e8132df390ae692873c847d1c2f62c0James Dong    for (i = 1; i < num1; i++)
16321cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
16331cc31e629e8132df390ae692873c847d1c2f62c0James Dong        same = 0;
16341cc31e629e8132df390ae692873c847d1c2f62c0James Dong        j = 0;
16351cc31e629e8132df390ae692873c847d1c2f62c0James Dong        while (!same && j < *num_can)
16361cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
16371cc31e629e8132df390ae692873c847d1c2f62c0James Dong#if (CANDIDATE_DISTANCE==0)
16381cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (mvx[i] == mvx[j] && mvy[i] == mvy[j])
16391cc31e629e8132df390ae692873c847d1c2f62c0James Dong#else
16401cc31e629e8132df390ae692873c847d1c2f62c0James Dong            // modified k-mean,  3/24/01, shouldn't be greater than 3
16411cc31e629e8132df390ae692873c847d1c2f62c0James Dong            if (AVC_ABS(mvx[i] - mvx[j]) + AVC_ABS(mvy[i] - mvy[j]) < CANDIDATE_DISTANCE)
16421cc31e629e8132df390ae692873c847d1c2f62c0James Dong#endif
16431cc31e629e8132df390ae692873c847d1c2f62c0James Dong                same = 1;
16441cc31e629e8132df390ae692873c847d1c2f62c0James Dong            j++;
16451cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
16461cc31e629e8132df390ae692873c847d1c2f62c0James Dong        if (!same)
16471cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
16481cc31e629e8132df390ae692873c847d1c2f62c0James Dong            mvx[*num_can] = mvx[i];
16491cc31e629e8132df390ae692873c847d1c2f62c0James Dong            mvy[*num_can] = mvy[i];
16501cc31e629e8132df390ae692873c847d1c2f62c0James Dong            (*num_can)++;
16511cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
16521cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
16531cc31e629e8132df390ae692873c847d1c2f62c0James Dong
16541cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (num1 == 5 && *num_can == 1)
16551cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *num_can = ALL_CAND_EQUAL; /* all are equal */
16561cc31e629e8132df390ae692873c847d1c2f62c0James Dong
16571cc31e629e8132df390ae692873c847d1c2f62c0James Dong    /* calculate predicted MV */
16581cc31e629e8132df390ae692873c847d1c2f62c0James Dong
16591cc31e629e8132df390ae692873c847d1c2f62c0James Dong    if (availA && !(availB || availC))
16601cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
16611cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *cmvx = pmvA_x;
16621cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *cmvy = pmvA_y;
16631cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
16641cc31e629e8132df390ae692873c847d1c2f62c0James Dong    else
16651cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
16661cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *cmvx = AVC_MEDIAN(pmvA_x, pmvB_x, pmvC_x);
16671cc31e629e8132df390ae692873c847d1c2f62c0James Dong        *cmvy = AVC_MEDIAN(pmvA_y, pmvB_y, pmvC_y);
16681cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
16691cc31e629e8132df390ae692873c847d1c2f62c0James Dong
16701cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return ;
16711cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
16721cc31e629e8132df390ae692873c847d1c2f62c0James Dong
16731cc31e629e8132df390ae692873c847d1c2f62c0James Dong
16741cc31e629e8132df390ae692873c847d1c2f62c0James Dong/*************************************************************
16751cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Function:   AVCMoveNeighborSAD
16761cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Date:       3/27/01
16771cc31e629e8132df390ae692873c847d1c2f62c0James Dong    Purpose:    Move neighboring SAD around when center has shifted
16781cc31e629e8132df390ae692873c847d1c2f62c0James Dong*************************************************************/
16791cc31e629e8132df390ae692873c847d1c2f62c0James Dong
16801cc31e629e8132df390ae692873c847d1c2f62c0James Dongvoid AVCMoveNeighborSAD(int dn[], int new_loc)
16811cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
16821cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int tmp[9];
16831cc31e629e8132df390ae692873c847d1c2f62c0James Dong    tmp[0] = dn[0];
16841cc31e629e8132df390ae692873c847d1c2f62c0James Dong    tmp[1] = dn[1];
16851cc31e629e8132df390ae692873c847d1c2f62c0James Dong    tmp[2] = dn[2];
16861cc31e629e8132df390ae692873c847d1c2f62c0James Dong    tmp[3] = dn[3];
16871cc31e629e8132df390ae692873c847d1c2f62c0James Dong    tmp[4] = dn[4];
16881cc31e629e8132df390ae692873c847d1c2f62c0James Dong    tmp[5] = dn[5];
16891cc31e629e8132df390ae692873c847d1c2f62c0James Dong    tmp[6] = dn[6];
16901cc31e629e8132df390ae692873c847d1c2f62c0James Dong    tmp[7] = dn[7];
16911cc31e629e8132df390ae692873c847d1c2f62c0James Dong    tmp[8] = dn[8];
16921cc31e629e8132df390ae692873c847d1c2f62c0James Dong    dn[0] = dn[1] = dn[2] = dn[3] = dn[4] = dn[5] = dn[6] = dn[7] = dn[8] = 65536;
16931cc31e629e8132df390ae692873c847d1c2f62c0James Dong
16941cc31e629e8132df390ae692873c847d1c2f62c0James Dong    switch (new_loc)
16951cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
16961cc31e629e8132df390ae692873c847d1c2f62c0James Dong        case 0:
16971cc31e629e8132df390ae692873c847d1c2f62c0James Dong            break;
16981cc31e629e8132df390ae692873c847d1c2f62c0James Dong        case 1:
16991cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[4] = tmp[2];
17001cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[5] = tmp[0];
17011cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[6] = tmp[8];
17021cc31e629e8132df390ae692873c847d1c2f62c0James Dong            break;
17031cc31e629e8132df390ae692873c847d1c2f62c0James Dong        case 2:
17041cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[4] = tmp[3];
17051cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[5] = tmp[4];
17061cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[6] = tmp[0];
17071cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[7] = tmp[8];
17081cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[8] = tmp[1];
17091cc31e629e8132df390ae692873c847d1c2f62c0James Dong            break;
17101cc31e629e8132df390ae692873c847d1c2f62c0James Dong        case 3:
17111cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[6] = tmp[4];
17121cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[7] = tmp[0];
17131cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[8] = tmp[2];
17141cc31e629e8132df390ae692873c847d1c2f62c0James Dong            break;
17151cc31e629e8132df390ae692873c847d1c2f62c0James Dong        case 4:
17161cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[1] = tmp[2];
17171cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[2] = tmp[3];
17181cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[6] = tmp[5];
17191cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[7] = tmp[6];
17201cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[8] = tmp[0];
17211cc31e629e8132df390ae692873c847d1c2f62c0James Dong            break;
17221cc31e629e8132df390ae692873c847d1c2f62c0James Dong        case 5:
17231cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[1] = tmp[0];
17241cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[2] = tmp[4];
17251cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[8] = tmp[6];
17261cc31e629e8132df390ae692873c847d1c2f62c0James Dong            break;
17271cc31e629e8132df390ae692873c847d1c2f62c0James Dong        case 6:
17281cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[1] = tmp[8];
17291cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[2] = tmp[0];
17301cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[3] = tmp[4];
17311cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[4] = tmp[5];
17321cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[8] = tmp[7];
17331cc31e629e8132df390ae692873c847d1c2f62c0James Dong            break;
17341cc31e629e8132df390ae692873c847d1c2f62c0James Dong        case 7:
17351cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[2] = tmp[8];
17361cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[3] = tmp[0];
17371cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[4] = tmp[6];
17381cc31e629e8132df390ae692873c847d1c2f62c0James Dong            break;
17391cc31e629e8132df390ae692873c847d1c2f62c0James Dong        case 8:
17401cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[2] = tmp[1];
17411cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[3] = tmp[2];
17421cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[4] = tmp[0];
17431cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[5] = tmp[6];
17441cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dn[6] = tmp[7];
17451cc31e629e8132df390ae692873c847d1c2f62c0James Dong            break;
17461cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
17471cc31e629e8132df390ae692873c847d1c2f62c0James Dong    dn[0] = tmp[new_loc];
17481cc31e629e8132df390ae692873c847d1c2f62c0James Dong
17491cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return ;
17501cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
17511cc31e629e8132df390ae692873c847d1c2f62c0James Dong
17521cc31e629e8132df390ae692873c847d1c2f62c0James Dong/*  3/28/01, find minimal of dn[9] */
17531cc31e629e8132df390ae692873c847d1c2f62c0James Dong
17541cc31e629e8132df390ae692873c847d1c2f62c0James Dongint AVCFindMin(int dn[])
17551cc31e629e8132df390ae692873c847d1c2f62c0James Dong{
17561cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int min, i;
17571cc31e629e8132df390ae692873c847d1c2f62c0James Dong    int dmin;
17581cc31e629e8132df390ae692873c847d1c2f62c0James Dong
17591cc31e629e8132df390ae692873c847d1c2f62c0James Dong    dmin = dn[1];
17601cc31e629e8132df390ae692873c847d1c2f62c0James Dong    min = 1;
17611cc31e629e8132df390ae692873c847d1c2f62c0James Dong    for (i = 2; i < 9; i++)
17621cc31e629e8132df390ae692873c847d1c2f62c0James Dong    {
17631cc31e629e8132df390ae692873c847d1c2f62c0James Dong        if (dn[i] < dmin)
17641cc31e629e8132df390ae692873c847d1c2f62c0James Dong        {
17651cc31e629e8132df390ae692873c847d1c2f62c0James Dong            dmin = dn[i];
17661cc31e629e8132df390ae692873c847d1c2f62c0James Dong            min = i;
17671cc31e629e8132df390ae692873c847d1c2f62c0James Dong        }
17681cc31e629e8132df390ae692873c847d1c2f62c0James Dong    }
17691cc31e629e8132df390ae692873c847d1c2f62c0James Dong
17701cc31e629e8132df390ae692873c847d1c2f62c0James Dong    return min;
17711cc31e629e8132df390ae692873c847d1c2f62c0James Dong}
17721cc31e629e8132df390ae692873c847d1c2f62c0James Dong
17731cc31e629e8132df390ae692873c847d1c2f62c0James Dong
17741cc31e629e8132df390ae692873c847d1c2f62c0James Dong
1775