[svn] / branches / dev-api-3 / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

Diff of /branches/dev-api-3/xvidcore/src/motion/motion_est.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 574, Wed Oct 2 10:16:36 2002 UTC revision 594, Sat Oct 12 13:56:16 2002 UTC
# Line 37  Line 37 
37  #include "../prediction/mbprediction.h"  #include "../prediction/mbprediction.h"
38  #include "../global.h"  #include "../global.h"
39  #include "../utils/timer.h"  #include "../utils/timer.h"
40    #include "../image/interpolate8x8.h"
41  #include "motion_est.h"  #include "motion_est.h"
42  #include "motion.h"  #include "motion.h"
43  #include "sad.h"  #include "sad.h"
# Line 51  Line 52 
52  #define CHECK_CANDIDATE(X,Y,D) { \  #define CHECK_CANDIDATE(X,Y,D) { \
53  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }  (*CheckCandidate)((const int)(X),(const int)(Y), (D), &iDirection, data ); }
54    
55    #define GET_REFERENCE(X, Y, REF) { \
56            switch ( ((X&1)<<1) + (Y&1) ) \
57            { \
58                    case 0 : REF = data->Ref + (X)/2 + ((Y)/2)*(data->iEdgedWidth); break; \
59                    case 1 : REF = data->RefV + (X)/2 + (((Y)-1)/2)*(data->iEdgedWidth); break; \
60                    case 2 : REF = data->RefH + ((X)-1)/2 + ((Y)/2)*(data->iEdgedWidth); break; \
61                    default : REF = data->RefHV + ((X)-1)/2 + (((Y)-1)/2)*(data->iEdgedWidth); break; \
62            } \
63    }
64    
65  #define iDiamondSize 2  #define iDiamondSize 2
66    
67  static __inline int  static __inline int
# Line 84  Line 95 
95  static void  static void
96  CheckCandidate16(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidate16(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
97  {  {
         int32_t * const sad = data->temp;  
98          int t;          int t;
99          const uint8_t * Reference;          const uint8_t * Reference;
100    
# Line 98  Line 108 
108                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;                  default : Reference = data->RefHV + (x-1)/2 + ((y-1)/2)*(data->iEdgedWidth); break;
109          }          }
110    
111          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, sad+1);          data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp + 1);
112    
113          t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);          t = d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
114          data->temp[0] += lambda_vec16[data->iQuant] * t;          data->temp[0] += lambda_vec16[data->iQuant] * t;
# Line 139  Line 149 
149    
150          sad = lambda_vec16[data->iQuant] *          sad = lambda_vec16[data->iQuant] *
151                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);                          d_mv_bits(x - data->predMV.x, y - data->predMV.y, data->iFcode);
152          sad += sad16(data->Cur, Reference, data->iEdgedWidth, 256*4096);          sad += sad16(data->Cur, Reference, data->iEdgedWidth, MV_MAX_ERROR);
153    
154          if (sad < *(data->iMinSAD)) {          if (sad < *(data->iMinSAD)) {
155                  *(data->iMinSAD) = sad;                  *(data->iMinSAD) = sad;
# Line 148  Line 158 
158  }  }
159    
160  static void  static void
161    CheckCandidate16_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
162    
163    // CheckCandidate16 variant which expects x and y in quarter pixel resolution
164    // Important: This is no general usable routine! x and y must be +/-1 (qpel resolution!)
165    // around currentMV!
166    {
167            int t;
168            uint8_t * Reference = (uint8_t *) data->RefQ;
169            const uint8_t *ref1, *ref2, *ref3, *ref4;
170            VECTOR halfpelMV = *(data->currentMV);
171    
172            int32_t iEdgedWidth = data->iEdgedWidth;
173            uint32_t rounding = data->rounding;
174    
175            if (( x > data->max_dx) || ( x < data->min_dx)
176                    || ( y > data->max_dy) || (y < data->min_dy)) return;
177    
178            switch( ((x&1)<<1) + (y&1) )
179            {
180            case 0: // pure halfpel position - shouldn't happen during a refinement step
181                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, (const uint8_t *) Reference);
182                    break;
183    
184            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
185                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
186                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
187    
188                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
189                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
190                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
191                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
192                    break;
193    
194            case 2: // x qpel, y halfpel - left or right during qpel refinement
195                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
196                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref2);
197    
198                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
199                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
200                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
201                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
202                    break;
203    
204            default: // x and y in qpel resolution - the "corners" (top left/right and
205                             // bottom left/right) during qpel refinement
206                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
207                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
208                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref3);
209                    GET_REFERENCE(x - halfpelMV.x, y - halfpelMV.y, ref4);
210    
211                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
212                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
213                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
214                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
215                    break;
216            }
217    
218            data->temp[0] = sad16v(data->Cur, Reference, data->iEdgedWidth, data->temp+1);
219    
220            t = d_mv_bits(x - data->predQMV.x, y - data->predQMV.y, data->iFcode);
221            data->temp[0] += lambda_vec16[data->iQuant] * t;
222            data->temp[1] += lambda_vec8[data->iQuant] * t;
223    
224            if (data->temp[0] < data->iMinSAD[0]) {
225                    data->iMinSAD[0] = data->temp[0];
226                    data->currentQMV[0].x = x; data->currentQMV[0].y = y;
227            /*      *dir = Direction;*/ }
228    
229            if (data->temp[1] < data->iMinSAD[1]) {
230                    data->iMinSAD[1] = data->temp[1]; data->currentQMV[1].x = x; data->currentQMV[1].y = y; }
231            if (data->temp[2] < data->iMinSAD[2]) {
232                    data->iMinSAD[2] = data->temp[2]; data->currentQMV[2].x = x; data->currentQMV[2].y = y; }
233            if (data->temp[3] < data->iMinSAD[3]) {
234                    data->iMinSAD[3] = data->temp[3]; data->currentQMV[3].x = x; data->currentQMV[3].y = y; }
235            if (data->temp[4] < data->iMinSAD[4]) {
236                    data->iMinSAD[4] = data->temp[4]; data->currentQMV[4].x = x; data->currentQMV[4].y = y; }
237    }
238    
239    static void
240    CheckCandidate16no4v_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
241    
242    // CheckCandidate16no4v variant which expects x and y in quarter pixel resolution
243    // Important: This is no general usable routine! x and y must be +/-1 (qpel resolution!)
244    // around currentMV!
245    {
246            int32_t sad;
247            uint8_t * Reference = (uint8_t *) data->RefQ;
248            const uint8_t *ref1, *ref2, *ref3, *ref4;
249            VECTOR halfpelMV = *(data->currentMV);
250    
251            int32_t iEdgedWidth = data->iEdgedWidth;
252            uint32_t rounding = data->rounding;
253    
254            if (( x > data->max_dx) || ( x < data->min_dx)
255                    || ( y > data->max_dy) || (y < data->min_dy)) return;
256    
257            switch( ((x&1)<<1) + (y&1) )
258            {
259            case 0: // pure halfpel position - shouldn't happen during a refinement step
260                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, (const uint8_t *) Reference);
261                    break;
262    
263            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
264                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
265                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
266    
267                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
268                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
269                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
270                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
271                    break;
272    
273            case 2: // x qpel, y halfpel - left or right during qpel refinement
274                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
275                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref2);
276    
277                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
278                    interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding);
279                    interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding);
280                    interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding);
281                    break;
282    
283            default: // x and y in qpel resolution - the "corners" (top left/right and
284                             // bottom left/right) during qpel refinement
285                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
286                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
287                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref3);
288                    GET_REFERENCE(x - halfpelMV.x, y - halfpelMV.y, ref4);
289    
290                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
291                    interpolate8x8_avg4(Reference+8, ref1+8, ref2+8, ref3+8, ref4+8, iEdgedWidth, rounding);
292                    interpolate8x8_avg4(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, ref3+8*iEdgedWidth, ref4+8*iEdgedWidth, iEdgedWidth, rounding);
293                    interpolate8x8_avg4(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, ref3+8*iEdgedWidth+8, ref4+8*iEdgedWidth+8, iEdgedWidth, rounding);
294                    break;
295            }
296    
297            sad = lambda_vec16[data->iQuant] *
298                            d_mv_bits(x - data->predQMV.x, y - data->predQMV.y, data->iFcode);
299            sad += sad16(data->Cur, Reference, data->iEdgedWidth, MV_MAX_ERROR);
300    
301            if (sad < *(data->iMinSAD)) {
302                    *(data->iMinSAD) = sad;
303                    data->currentQMV[0].x = x; data->currentQMV[0].y = y;
304    //              *dir = Direction;
305            }
306    }
307    
308    static void
309  CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)  CheckCandidate16no4vI(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
310  {  {
311          int32_t sad;          int32_t sad;
# Line 269  Line 427 
427          const uint8_t *ReferenceB;          const uint8_t *ReferenceB;
428          VECTOR mvs, b_mvs;          VECTOR mvs, b_mvs;
429    
430          if (( x > 31) || ( x < -31) || ( y > 31) || (y < -31)) return;          if (( x > 31) || ( x < -32) || ( y > 31) || (y < -32)) return;
431    
432                  sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);                  sad = lambda_vec16[data->iQuant] * d_mv_bits(x, y, 1);
433    
# Line 336  Line 494 
494                  *dir = Direction; }                  *dir = Direction; }
495  }  }
496    
497    static void
498    CheckCandidate8_qpel(const int x, const int y, const int Direction, int * const dir, const SearchData * const data)
499    // CheckCandidate16no4v variant which expects x and y in quarter pixel resolution
500    // Important: This is no general usable routine! x and y must be +/-1 (qpel resolution!)
501    // around currentMV!
502    
503    {
504            int32_t sad;
505            uint8_t *Reference = (uint8_t *) data->RefQ;
506            const uint8_t *ref1, *ref2, *ref3, *ref4;
507            VECTOR halfpelMV = *(data->currentMV);
508    
509            int32_t iEdgedWidth = data->iEdgedWidth;
510            uint32_t rounding = data->rounding;
511    
512            if (( x > data->max_dx) || ( x < data->min_dx)
513                    || ( y > data->max_dy) || (y < data->min_dy)) return;
514    
515            switch( ((x&1)<<1) + (y&1) )
516            {
517            case 0: // pure halfpel position - shouldn't happen during a refinement step
518                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, (const uint8_t *) Reference);
519                    break;
520    
521            case 1: // x halfpel, y qpel - top or bottom during qpel refinement
522                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
523                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
524    
525                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
526                    break;
527    
528            case 2: // x qpel, y halfpel - left or right during qpel refinement
529                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
530                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref2);
531    
532                    interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding);
533                    break;
534    
535            default: // x and y in qpel resolution - the "corners" (top left/right and
536                             // bottom left/right) during qpel refinement
537                    GET_REFERENCE(halfpelMV.x, halfpelMV.y, ref1);
538                    GET_REFERENCE(halfpelMV.x, y - halfpelMV.y, ref2);
539                    GET_REFERENCE(x - halfpelMV.x, halfpelMV.y, ref3);
540                    GET_REFERENCE(x - halfpelMV.x, y - halfpelMV.y, ref4);
541    
542                    interpolate8x8_avg4(Reference, ref1, ref2, ref3, ref4, iEdgedWidth, rounding);
543                    break;
544            }
545    
546            sad = sad8(data->Cur, Reference, data->iEdgedWidth);
547            sad += lambda_vec8[data->iQuant] * d_mv_bits(x - data->predQMV.x, y - data->predQMV.y, data->iFcode);
548    
549            if (sad < *(data->iMinSAD)) {
550                    *(data->iMinSAD) = sad;
551                    data->currentQMV->x = x; data->currentQMV->y = y;
552                    *dir = Direction; }
553    }
554    
555  /* CHECK_CANDIATE FUNCTIONS END */  /* CHECK_CANDIATE FUNCTIONS END */
556    
557  /* MAINSEARCH FUNCTIONS START */  /* MAINSEARCH FUNCTIONS START */
# Line 504  Line 720 
720          CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);          CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);
721  }  }
722    
723    
724    static void
725    QuarterpelRefine(const SearchData * const data)
726    {
727    /* Perform quarter pixel refinement*/
728    
729            VECTOR backupMV = *(data->currentQMV);
730            int iDirection; //not needed
731    
732            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y - 1, 0);
733            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y - 1, 0);
734            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y + 1, 0);
735            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y + 1, 0);
736    
737            CHECK_CANDIDATE(backupMV.x - 1, backupMV.y, 0);
738            CHECK_CANDIDATE(backupMV.x + 1, backupMV.y, 0);
739    
740            CHECK_CANDIDATE(backupMV.x, backupMV.y + 1, 0);
741            CHECK_CANDIDATE(backupMV.x, backupMV.y - 1, 0);
742    
743    }
744    
745  static __inline int  static __inline int
746  SkipDecisionP(const IMAGE * current, const IMAGE * reference,  SkipDecisionP(const IMAGE * current, const IMAGE * reference,
747                                                          const int x, const int y,                                                          const int x, const int y,
# Line 530  Line 768 
768          pMB->mode = MODE_NOT_CODED;          pMB->mode = MODE_NOT_CODED;
769          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;          pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;
770          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;          pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;
771    
772            pMB->qmvs[0].x = pMB->qmvs[1].x = pMB->qmvs[2].x = pMB->qmvs[3].x = 0;
773            pMB->qmvs[0].y = pMB->qmvs[1].y = pMB->qmvs[2].y = pMB->qmvs[3].y = 0;
774    
775          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad;          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = sad;
776  }  }
777    
# Line 551  Line 793 
793          uint32_t x, y;          uint32_t x, y;
794          uint32_t iIntra = 0;          uint32_t iIntra = 0;
795          int32_t InterBias, quant = current->quant;          int32_t InterBias, quant = current->quant;
796            uint8_t *qimage;
797    
798          // some pre-initialized thingies for SearchP          // some pre-initialized thingies for SearchP
799          int32_t temp[5];          int32_t temp[5];
800          VECTOR currentMV[5];          VECTOR currentMV[5];
801            VECTOR currentQMV[5];
802          int32_t iMinSAD[5];          int32_t iMinSAD[5];
803          SearchData Data;          SearchData Data;
804          Data.iEdgedWidth = pParam->edged_width;          Data.iEdgedWidth = pParam->edged_width;
805          Data.currentMV = currentMV;          Data.currentMV = currentMV;
806            Data.currentQMV = currentQMV;
807          Data.iMinSAD = iMinSAD;          Data.iMinSAD = iMinSAD;
808          Data.temp = temp;          Data.temp = temp;
809          Data.iFcode = current->fcode;          Data.iFcode = current->fcode;
810            Data.rounding = pParam->m_rounding_type;
811    
812            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
813                    return 1; // allocate some mem for qpel interpolated blocks
814                                      // somehow this is dirty since I think we shouldn't use malloc outside
815                                      // encoder_create() - so please fix me!
816    
817          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
818    
# Line 592  Line 843 
843                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {                                  if (pMB->sad16 < pMB->quant * INITIAL_SKIP_THRESH) {
844                                                  SkipMacroblockP(pMB, sad00);                                                  SkipMacroblockP(pMB, sad00);
845                                                  continue;                                                  continue;
846                                            sad00 = 256 * 4096;
847                                  }                                  }
848                          } else sad00 = 256*4096; // skip not allowed - for final skip decision                          } else sad00 = 256*4096; // skip not allowed - for final skip decision
849    
850                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, x,                          SearchP(pRef->y, pRefH->y, pRefV->y, pRefHV->y, qimage, pCurrent, x,
851                                                  y, current->motion_flags, pMB->quant,                                                  y, current->motion_flags, pMB->quant,
852                                                  &Data, pParam, pMBs, reference->mbs,                                                  &Data, pParam, pMBs, reference->mbs,
853                                                  current->global_flags & XVID_INTER4V, pMB);                                                  current->global_flags & XVID_INTER4V, pMB);
# Line 620  Line 872 
872                                                    pParam->edged_width);                                                    pParam->edged_width);
873    
874                                  if (deviation < (pMB->sad16 - InterBias)) {                                  if (deviation < (pMB->sad16 - InterBias)) {
875                                          if (++iIntra >= iLimit) return 1;                                          if (++iIntra >= iLimit) { free(qimage); return 1; }
876                                          pMB->mode = MODE_INTRA;                                          pMB->mode = MODE_INTRA;
877                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =                                          pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] =
878                                                          pMB->mvs[3] = zeroMV;                                                          pMB->mvs[3] = zeroMV;
879                                            pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] =
880                                                            pMB->qmvs[3] = zeroMV;
881                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =                                          pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] =
882                                                  pMB->sad8[3] = 0;                                                  pMB->sad8[3] = 0;
883                                  }                                  }
884                          }                          }
885                  }                  }
886          }          }
887            free(qimage);
888          return 0;          return 0;
889  }  }
890    
# Line 691  Line 946 
946                  const uint8_t * const pRefH,                  const uint8_t * const pRefH,
947                  const uint8_t * const pRefV,                  const uint8_t * const pRefV,
948                  const uint8_t * const pRefHV,                  const uint8_t * const pRefHV,
949                    const uint8_t * const pRefQ,
950                  const IMAGE * const pCur,                  const IMAGE * const pCur,
951                  const int x,                  const int x,
952                  const int y,                  const int y,
# Line 707  Line 963 
963          int i, iDirection = 255, mask, threshA;          int i, iDirection = 255, mask, threshA;
964          VECTOR pmv[7];          VECTOR pmv[7];
965    
966            Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x, y, 0);
967    
968          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()          get_pmvdata2(pMBs, pParam->mb_width, 0, x, y, 0, pmv, Data->temp);  //has to be changed to get_pmv(2)()
969          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
970                                  pParam->width, pParam->height, Data->iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
971    
972          Data->predMV = pmv[0];          Data->predMV = pmv[0];
973    
974          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * Data->iEdgedWidth) * 16;
975          Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;          Data->Ref = pRef + (x + Data->iEdgedWidth*y)*16;
976          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;          Data->RefH = pRefH + (x + Data->iEdgedWidth*y) * 16;
977          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;          Data->RefV = pRefV + (x + Data->iEdgedWidth*y) * 16;
978          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;          Data->RefHV = pRefHV + (x + Data->iEdgedWidth*y) * 16;
979            Data->RefQ = pRefQ;
980    
981          Data->iQuant = iQuant;          Data->iQuant = iQuant;
982    
# Line 731  Line 991 
991          if (inter4v) CheckCandidate = CheckCandidate16;          if (inter4v) CheckCandidate = CheckCandidate16;
992          else CheckCandidate = CheckCandidate16no4v;          else CheckCandidate = CheckCandidate16no4v;
993    
994          for(i = 0;  i < 5; i++) Data->currentMV[i].x = Data->currentMV[i].y = 0;          for(i = 0;  i < 5; i++)
995                    Data->currentMV[i].x = Data->currentMV[i].y = 0;
996    
997          i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);          i = d_mv_bits(Data->predMV.x, Data->predMV.y, Data->iFcode);
998          Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;          Data->iMinSAD[0] = pMB->sad16 + lambda_vec16[iQuant] * i;
# Line 810  Line 1071 
1071    
1072          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1073    
1074            for(i = 0; i < 5; i++) {
1075                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1076                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1077            }
1078    
1079            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1080    
1081                    if(inter4v)
1082                            CheckCandidate = CheckCandidate16_qpel;
1083                    else
1084                            CheckCandidate = CheckCandidate16no4v_qpel;
1085    
1086                            Data->iMinSAD[0] -= lambda_vec16[iQuant] *
1087                                    d_mv_bits(Data->predMV.x - Data->currentMV[0].x, Data->predMV.y - Data->currentMV[0].y, Data->iFcode);
1088                            Data->iMinSAD[1] -= lambda_vec8[iQuant] *
1089                                    d_mv_bits(Data->predMV.x - Data->currentMV[1].x, Data->predMV.y - Data->currentMV[1].y, Data->iFcode);
1090    
1091                            Data->iMinSAD[0] += lambda_vec16[iQuant] *
1092                                    d_mv_bits(Data->predQMV.x - Data->currentQMV[0].x, Data->predMV.y - Data->currentQMV[0].y, Data->iFcode);
1093                            Data->iMinSAD[1] += lambda_vec8[iQuant] *
1094                                    d_mv_bits(Data->predQMV.x - Data->currentQMV[1].x, Data->predMV.y - Data->currentQMV[1].y, Data->iFcode);
1095    
1096                            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1097                                    pParam->width, pParam->height, Data->iFcode, 0);
1098    
1099                    QuarterpelRefine(Data);
1100            }
1101    
1102          if (inter4v) {          if (inter4v) {
1103                  SearchData Data8;                  SearchData Data8;
1104                  Data8.iFcode = Data->iFcode;                  Data8.iFcode = Data->iFcode;
# Line 829  Line 1118 
1118                  pMB->mvs[0] = pMB->mvs[1]                  pMB->mvs[0] = pMB->mvs[1]
1119                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];                          = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0];
1120    
1121                    pMB->qmvs[0] = pMB->qmvs[1]
1122                            = pMB->qmvs[2] = pMB->qmvs[3] = Data->currentQMV[0];
1123    
1124                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =                  pMB->sad16 = pMB->sad8[0] = pMB->sad8[1] =
1125                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];                          pMB->sad8[2] = pMB->sad8[3] =  Data->iMinSAD[0];
1126    
1127                    if(pParam->m_quarterpel) {
1128                            pMB->pmvs[0].x = Data->currentQMV[0].x - Data->predQMV.x;
1129                            pMB->pmvs[0].y = Data->currentQMV[0].y - Data->predQMV.y;
1130                    }
1131                    else {
1132                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;                  pMB->pmvs[0].x = Data->currentMV[0].x - Data->predMV.x;
1133                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;                  pMB->pmvs[0].y = Data->currentMV[0].y - Data->predMV.y;
1134                    }
1135          } else {          } else {
1136  // INTER4V MODE; all other things are already set in Search8  // INTER4V MODE; all other things are already set in Search8
1137                  pMB->mode = MODE_INTER4V;                  pMB->mode = MODE_INTER4V;
1138                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +                  pMB->sad16 = Data->iMinSAD[1] + Data->iMinSAD[2] +
1139                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;                          Data->iMinSAD[3] + Data->iMinSAD[4] + IMV16X16 * iQuant;
1140          }          }
   
1141  }  }
1142    
1143  static void  static void
# Line 854  Line 1151 
1151                  SearchData * const Data)                  SearchData * const Data)
1152  {  {
1153          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1154            Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1155          Data->iMinSAD = OldData->iMinSAD + 1 + block;          Data->iMinSAD = OldData->iMinSAD + 1 + block;
1156          Data->currentMV = OldData->currentMV + 1 + block;          Data->currentMV = OldData->currentMV + 1 + block;
1157            Data->currentQMV = OldData->currentQMV + 1 + block;
1158    
1159            if(pParam->m_quarterpel) {
1160                    //it is qpel. substract d_mv_bits[qpel] from 0, add d_mv_bits[hpel] everywhere
1161                    if (block == 0)
1162                            *(Data->iMinSAD) -= lambda_vec8[Data->iQuant] *
1163                                                                            d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1164                                                                                                    Data->currentQMV->y - Data->predQMV.y,
1165                                                                                                    Data->iFcode);
1166    
         if (block != 0)  
1167                  *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *                  *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *
1168                                                                  d_mv_bits(      Data->currentMV->x - Data->predMV.x,                                                                  d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1169                                                                                          Data->currentMV->y - Data->predMV.y,                                                                                          Data->currentMV->y - Data->predMV.y,
1170                                                                                          Data->iFcode);                                                                                          Data->iFcode);
1171            } else //it is not qpel. add d_mv_bits[hpel] everywhere but not in 0 (it's already there)
1172                    if (block != 0) *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *
1173                                                                            d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1174                                                                                                    Data->currentMV->y - Data->predMV.y,
1175                                                                                                    Data->iFcode);
1176    
1177    
1178          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {          if (MotionFlags & (PMV_EXTSEARCH8|PMV_HALFPELREFINE8)) {
1179    
# Line 869  Line 1181 
1181                  Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1182                  Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1183                  Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1184                    Data->RefQ = OldData->RefQ;
1185    
1186                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                  Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
1187    
1188                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,                  get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1189                                  pParam->width, pParam->height, OldData->iFcode);                                  pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1190    
1191                  CheckCandidate = CheckCandidate8;                  CheckCandidate = CheckCandidate8;
1192    
1193                  if (MotionFlags & PMV_EXTSEARCH8) {                  if (MotionFlags & PMV_EXTSEARCH8) {
1194                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1195    
1196                          MainSearchFunc *MainSearchPtr;                          MainSearchFunc *MainSearchPtr;
1197                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;                          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1198                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1199                                          else MainSearchPtr = DiamondSearch;                                          else MainSearchPtr = DiamondSearch;
1200    
1201                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);    }                          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1202    
1203                            if(*(Data->iMinSAD) < temp_sad) {
1204                                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1205                                            Data->currentQMV->y = 2 * Data->currentMV->y;
1206                            }
1207                    }
1208    
1209                    if (MotionFlags & PMV_HALFPELREFINE8) {
1210                            int32_t temp_sad = *(Data->iMinSAD); // store current MinSAD
1211    
1212                            HalfpelRefine(Data); // perform halfpel refine of current best vector
1213    
1214                            if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1215                                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1216                                    Data->currentQMV->y = 2 * Data->currentMV->y;
1217                            }
1218                    }
1219    
1220                    if(pParam->m_quarterpel) {
1221                            if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1222                                    (MotionFlags & PMV_QUARTERPELREFINE8)) {
1223    
1224                  if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(Data);                                  CheckCandidate = CheckCandidate8_qpel;
1225                            Data->iMinSAD[0] -= lambda_vec8[Data->iQuant] *
1226                                    d_mv_bits(Data->predMV.x - Data->currentMV[0].x, Data->predMV.y - Data->currentMV[0].y, Data->iFcode);
1227    
1228                            Data->iMinSAD[0] += lambda_vec8[Data->iQuant] *
1229                                    d_mv_bits(Data->predQMV.x - Data->currentQMV[0].x, Data->predQMV.y - Data->currentQMV[0].y, Data->iFcode);
1230    
1231                                    QuarterpelRefine(Data);
1232                            }
1233                    }
1234          }          }
1235    
1236            if(pParam->m_quarterpel) {
1237                    pMB->pmvs[block].x = Data->currentQMV->x - Data->predQMV.x;
1238                    pMB->pmvs[block].y = Data->currentQMV->y - Data->predQMV.y;
1239            }
1240            else {
1241          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;          pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1242          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;          pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1243            }
1244    
1245          pMB->mvs[block] = *(Data->currentMV);          pMB->mvs[block] = *(Data->currentMV);
1246          pMB->sad8[block] =  4 * (*Data->iMinSAD);          pMB->qmvs[block] = *(Data->currentQMV);
1247    
1248            pMB->sad8[block] =  4 * (*Data->iMinSAD);
1249  }  }
1250    
1251  /* B-frames code starts here */  /* B-frames code starts here */
# Line 979  Line 1331 
1331          Data->predMV = *predMV;          Data->predMV = *predMV;
1332    
1333          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1334                                  pParam->width, pParam->height, iFcode);                                  pParam->width, pParam->height, iFcode, pParam->m_quarterpel);
1335    
1336          pmv[0] = Data->predMV;          pmv[0] = Data->predMV;
1337          PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);          PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current);
# Line 1094  Line 1446 
1446    
1447  // skip decision  // skip decision
1448          if (*Data->iMinSAD - 2 * lambda_vec16[Data->iQuant] < (int32_t)Data->iQuant * SKIP_THRESH_B) {          if (*Data->iMinSAD - 2 * lambda_vec16[Data->iQuant] < (int32_t)Data->iQuant * SKIP_THRESH_B) {
1449                  //checking chroma. everything copied from MC                  //possible skip - checking chroma. everything copied from MC
1450                  //this is not full chroma compensation, only it's fullpel approximation. should work though                  //this is not full chroma compensation, only it's fullpel approximation. should work though
1451                  int sum, dx, dy, b_dx, b_dy;                  int sum, dx, dy, b_dx, b_dy;
1452    
# Line 1216  Line 1568 
1568    
1569          fData->currentMV[0] = pMB->mvs[0];          fData->currentMV[0] = pMB->mvs[0];
1570          fData->currentMV[1] = pMB->b_mvs[0];          fData->currentMV[1] = pMB->b_mvs[0];
1571          get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode);          get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, pParam->m_quarterpel);
1572          get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode);          get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, pParam->m_quarterpel);
1573    
1574          if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;          if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx;
1575          if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dy;          if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dy;
# Line 1404  Line 1756 
1756    
1757  /* Hinted ME starts here */  /* Hinted ME starts here */
1758    
1759  static __inline void  static void
1760  Search8hinted(  const SearchData * const OldData,  Search8hinted(  const SearchData * const OldData,
1761                                  const int x, const int y,                                  const int x, const int y,
1762                                  const uint32_t MotionFlags,                                  const uint32_t MotionFlags,
1763                                  const MBParam * const pParam,                                  const MBParam * const pParam,
1764                                  MACROBLOCK * const pMB,                                  MACROBLOCK * const pMB,
1765                                  const MACROBLOCK * const pMBs,                                  const MACROBLOCK * const pMBs,
1766                                  const int block)                  const int block,
1767                    SearchData * const Data)
1768  {  {
1769          SearchData Data;          int32_t temp_sad;
1770          MainSearchFunc *MainSearchPtr;          MainSearchFunc *MainSearchPtr;
1771            Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1772            Data->predQMV = get_qpmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);
1773            Data->iMinSAD = OldData->iMinSAD + 1 + block;
1774            Data->currentMV = OldData->currentMV + 1 + block;
1775            Data->currentQMV = OldData->currentQMV + 1 + block;
1776    
1777          Data.predMV = get_pmv2(pMBs, pParam->mb_width, 0, x/2 , y/2, block);          if (block != 0) {
1778          Data.iMinSAD = OldData->iMinSAD + 1 + block;                  if(pParam->m_quarterpel) {
1779          Data.currentMV = OldData->currentMV+1+block;                          *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *
1780          Data.iFcode = OldData->iFcode;                                                                          d_mv_bits(      Data->currentQMV->x - Data->predQMV.x,
1781          Data.iQuant = OldData->iQuant;                                                                                                  Data->currentQMV->y - Data->predQMV.y,
1782                                                                                                    Data->iFcode);
1783          Data.Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));                  }
1784          Data.RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));                  else {
1785          Data.RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));                          *(Data->iMinSAD) += lambda_vec8[Data->iQuant] *
1786          Data.RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));                                                                          d_mv_bits(      Data->currentMV->x - Data->predMV.x,
1787          Data.iEdgedWidth = pParam->edged_width;                                                                                                  Data->currentMV->y - Data->predMV.y,
1788          Data.Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));                                                                                                  Data->iFcode);
1789                    }
1790            }
1791    
         CheckCandidate = CheckCandidate8;  
1792    
1793          if (block != 0)          Data->Ref = OldData->Ref + 8 * ((block&1) + pParam->edged_width*(block>>1));
1794                  *(Data.iMinSAD) += lambda_vec8[Data.iQuant] *          Data->RefH = OldData->RefH + 8 * ((block&1) + pParam->edged_width*(block>>1));
1795                                                                  d_mv_bits(      Data.currentMV->x - Data.predMV.x,          Data->RefV = OldData->RefV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1796                                                                                          Data.currentMV->y - Data.predMV.y,          Data->RefHV = OldData->RefHV + 8 * ((block&1) + pParam->edged_width*(block>>1));
1797                                                                                          Data.iFcode);          Data->RefQ = OldData->RefQ;
1798    
1799            Data->Cur = OldData->Cur + 8 * ((block&1) + pParam->edged_width*(block>>1));
1800    
1801            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 8,
1802                                    pParam->width, pParam->height, OldData->iFcode, pParam->m_quarterpel);
1803    
1804          get_range(&Data.min_dx, &Data.max_dx, &Data.min_dy, &Data.max_dy, x, y, 8,          CheckCandidate = CheckCandidate8;
1805                                  pParam->width, pParam->height, OldData->iFcode);  
1806            temp_sad = *(Data->iMinSAD); // store current MinSAD
         if (pMB->mode == MODE_INTER4V) {  
                 int dummy;  
                 CheckCandidate8(pMB->mvs[block].x, pMB->mvs[block].y, 0, &dummy, &Data); }  
1807    
1808          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;          if (MotionFlags & PMV_USESQUARES8) MainSearchPtr = SquareSearch;
1809                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;                  else if (MotionFlags & PMV_ADVANCEDDIAMOND8) MainSearchPtr = AdvDiamondSearch;
1810                          else MainSearchPtr = DiamondSearch;                          else MainSearchPtr = DiamondSearch;
1811    
1812          (*MainSearchPtr)(Data.currentMV->x, Data.currentMV->y, &Data, 255);          (*MainSearchPtr)(Data->currentMV->x, Data->currentMV->y, Data, 255);
1813    
1814            if(*(Data->iMinSAD) < temp_sad) {
1815                    Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1816                    Data->currentQMV->y = 2 * Data->currentMV->y;
1817            }
1818    
1819            if (MotionFlags & PMV_HALFPELREFINE8) {
1820                    temp_sad = *(Data->iMinSAD); // store current MinSAD
1821    
1822                    HalfpelRefine(Data); // perform halfpel refine of current best vector
1823    
1824                    if(*(Data->iMinSAD) < temp_sad) { // we have found a better match
1825                            Data->currentQMV->x = 2 * Data->currentMV->x; // update our qpel vector
1826                            Data->currentQMV->y = 2 * Data->currentMV->y;
1827                    }
1828            }
1829    
1830          if (MotionFlags & PMV_HALFPELREFINE8) HalfpelRefine(&Data);          if(pParam->m_quarterpel) {
1831                    if((!(Data->currentQMV->x & 1)) && (!(Data->currentQMV->y & 1)) &&
1832                            (MotionFlags & PMV_QUARTERPELREFINE8)) {
1833                                    CheckCandidate = CheckCandidate8_qpel;
1834                                    QuarterpelRefine(Data);
1835                    }
1836            }
1837    
1838          pMB->pmvs[block].x = Data.currentMV->x - Data.predMV.x;          if(pParam->m_quarterpel) {
1839          pMB->pmvs[block].y = Data.currentMV->y - Data.predMV.y;                  pMB->pmvs[block].x = Data->currentQMV->x - Data->predQMV.x;
1840          pMB->mvs[block] = *(Data.currentMV);                  pMB->pmvs[block].y = Data->currentQMV->y - Data->predQMV.y;
1841          pMB->sad8[block] =  4 * (*(Data.iMinSAD));          }
1842            else {
1843                    pMB->pmvs[block].x = Data->currentMV->x - Data->predMV.x;
1844                    pMB->pmvs[block].y = Data->currentMV->y - Data->predMV.y;
1845            }
1846    
1847            pMB->mvs[block] = *(Data->currentMV);
1848            pMB->qmvs[block] = *(Data->currentQMV);
1849    
1850            pMB->sad8[block] =  4 * (*Data->iMinSAD);
1851  }  }
1852    
1853    
# Line 1484  Line 1875 
1875    
1876          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
1877          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
1878                                  pParam->width, pParam->height, Data->iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
1879    
1880          Data->Cur = pCur->y + (x + y * iEdgedWidth) * 16;          Data->Cur = pCur->y + (x + y * iEdgedWidth) * 16;
1881          Data->Ref = pRef + (x + iEdgedWidth*y)*16;          Data->Ref = pRef + (x + iEdgedWidth*y)*16;
# Line 1536  Line 1927 
1927    
1928          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);          if (MotionFlags & PMV_HALFPELREFINE16) HalfpelRefine(Data);
1929    
1930            for(i = 0; i < 5; i++) {
1931                    Data->currentQMV[i].x = 2 * Data->currentMV[i].x; // initialize qpel vectors
1932                    Data->currentQMV[i].y = 2 * Data->currentMV[i].y;
1933            }
1934    
1935            if((pParam->m_quarterpel) && (MotionFlags & PMV_QUARTERPELREFINE16)) {
1936    
1937          if (inter4v)          if (inter4v)
1938                  for(i = 0; i < 4; i++)                          CheckCandidate = CheckCandidate16_qpel;
1939                          Search8hinted(Data, 2*x+(i&1), 2*y+(i>>1), MotionFlags, pParam, pMB, pMBs, i);                  else
1940                            CheckCandidate = CheckCandidate16no4v_qpel;
1941    
1942                    QuarterpelRefine(Data);
1943            }
1944    
1945    
1946            if (inter4v) {
1947                    SearchData Data8;
1948                    Data8.iFcode = Data->iFcode;
1949                    Data8.iQuant = Data->iQuant;
1950                    Data8.iEdgedWidth = Data->iEdgedWidth;
1951                    Search8hinted(Data, 2*x, 2*y, MotionFlags, pParam, pMB, pMBs, 0, &Data8);
1952                    Search8hinted(Data, 2*x + 1, 2*y, MotionFlags, pParam, pMB, pMBs, 1, &Data8);
1953                    Search8hinted(Data, 2*x, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 2, &Data8);
1954                    Search8hinted(Data, 2*x + 1, 2*y + 1, MotionFlags, pParam, pMB, pMBs, 3, &Data8);
1955            }
1956    
1957          if (!(inter4v) ||          if (!(inter4v) ||
1958                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3] +                  (Data->iMinSAD[0] < Data->iMinSAD[1] + Data->iMinSAD[2] + Data->iMinSAD[3] +
# Line 1576  Line 1990 
1990          const IMAGE *const pRef = &reference->image;          const IMAGE *const pRef = &reference->image;
1991    
1992          uint32_t x, y;          uint32_t x, y;
1993            int8_t * qimage;
1994          int32_t temp[5], quant = current->quant;          int32_t temp[5], quant = current->quant;
1995          int32_t iMinSAD[5];          int32_t iMinSAD[5];
1996          VECTOR currentMV[5];          VECTOR currentMV[5];
# Line 1585  Line 2000 
2000          Data.iMinSAD = iMinSAD;          Data.iMinSAD = iMinSAD;
2001          Data.temp = temp;          Data.temp = temp;
2002          Data.iFcode = current->fcode;          Data.iFcode = current->fcode;
2003            Data.rounding = pParam->m_rounding_type;
2004    
2005            if((qimage = (uint8_t *) malloc(32 * pParam->edged_width)) == NULL)
2006                    return; // allocate some mem for qpel interpolated blocks
2007                                      // somehow this is dirty since I think we shouldn't use malloc outside
2008                                      // encoder_create() - so please fix me!
2009    
2010            Data.RefQ = qimage;
2011    
2012          if (sadInit) (*sadInit) ();          if (sadInit) (*sadInit) ();
2013    
# Line 1615  Line 2038 
2038    
2039                  }                  }
2040          }          }
2041            free(qimage);
2042  }  }
2043    
2044  static __inline int  static __inline int
# Line 1634  Line 2058 
2058          *(Data->iMinSAD) = MV_MAX_ERROR;          *(Data->iMinSAD) = MV_MAX_ERROR;
2059          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);
2060          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,          get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16,
2061                                  pParam->width, pParam->height, Data->iFcode);                                  pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel);
2062    
2063          Data->Cur = pCur + (x + y * pParam->edged_width) * 16;          Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
2064          Data->Ref = pRef + (x + y * pParam->edged_width) * 16;          Data->Ref = pRef + (x + y * pParam->edged_width) * 16;
# Line 1711  Line 2135 
2135          return 0; // B frame          return 0; // B frame
2136    
2137  }  }
2138    
2139    int
2140    FindFcode(      const MBParam * const pParam,
2141                            const FRAMEINFO * const current)
2142    {
2143            uint32_t x, y;
2144            int max = 0, min = 0, i;
2145    
2146            for (y = 0; y < pParam->mb_height; y++) {
2147                    for (x = 0; x < pParam->mb_width; x++) {
2148    
2149                            MACROBLOCK *pMB = &current->mbs[x + y * pParam->mb_width];
2150                            for(i = 0; i < (pMB->mode == MODE_INTER4V ? 4:1); i++) {
2151                                    if (pMB->mvs[i].x > max) max = pMB->mvs[i].x;
2152                                    if (pMB->mvs[i].y > max) max = pMB->mvs[i].y;
2153    
2154                                    if (pMB->mvs[i].x < min) min = pMB->mvs[i].x;
2155                                    if (pMB->mvs[i].y < min) min = pMB->mvs[i].y;
2156                            }
2157                    }
2158            }
2159    
2160            min = -min;
2161            max += 1;
2162            if (min > max) max = min;
2163    
2164            for (i = 1; (max > 32 << (i - 1)); i++);
2165            return i;
2166    }

Legend:
Removed from v.574  
changed lines
  Added in v.594

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4