1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 #include "mp4def.h"
19 #include "mp4enc_lib.h"
20 #include "mp4lib_int.h"
21 #include "m4venc_oscl.h"
22
23 //#define PRINT_MV
24 #define MIN_GOP 1 /* minimum size of GOP, 1/23/01, need to be tested */
25
26 #define CANDIDATE_DISTANCE 0 /* distance candidate from one another to consider as a distinct one */
27 /* shouldn't be more than 3 */
28
29 #define ZERO_MV_PREF 0 /* 0: bias (0,0)MV before full-pel search, lowest complexity*/
30 /* 1: bias (0,0)MV after full-pel search, before half-pel, highest comp */
31 /* 2: bias (0,0)MV after half-pel, high comp, better PSNR */
32
33 #define RASTER_REFRESH /* instead of random INTRA refresh, do raster scan, 2/26/01 */
34
35 #ifdef RASTER_REFRESH
36 #define TARGET_REFRESH_PER_REGION 4 /* , no. MB per frame to be INTRA refreshed */
37 #else
38 #define TARGET_REFRESH_PER_REGION 1 /* , no. MB per region to be INTRA refreshed */
39 #endif
40
41 #define ALL_CAND_EQUAL 10 /* any number greater than 5 will work */
42
43 #define NumPixelMB 256 /* number of pixels used in SAD calculation */
44
45 #define DEF_8X8_WIN 3 /* search region for 8x8 MVs around the 16x16 MV */
46 #define MB_Nb 256
47
48 #define PREF_NULL_VEC 129 /* for zero vector bias */
49 #define PREF_16_VEC 129 /* 1MV bias versus 4MVs*/
50 #define PREF_INTRA 512 /* bias for INTRA coding */
51
52 const static Int tab_exclude[9][9] = // [last_loc][curr_loc]
53 {
54 {0, 0, 0, 0, 0, 0, 0, 0, 0},
55 {0, 0, 0, 0, 1, 1, 1, 0, 0},
56 {0, 0, 0, 0, 1, 1, 1, 1, 1},
57 {0, 0, 0, 0, 0, 0, 1, 1, 1},
58 {0, 1, 1, 0, 0, 0, 1, 1, 1},
59 {0, 1, 1, 0, 0, 0, 0, 0, 1},
60 {0, 1, 1, 1, 1, 0, 0, 0, 1},
61 {0, 0, 1, 1, 1, 0, 0, 0, 0},
62 {0, 0, 1, 1, 1, 1, 1, 0, 0}
63 }; //to decide whether to continue or compute
64
65 const static Int refine_next[8][2] = /* [curr_k][increment] */
66 {
67 {0, 0}, {2, 0}, {1, 1}, {0, 2}, { -1, 1}, { -2, 0}, { -1, -1}, {0, -2}
68 };
69
70 #ifdef __cplusplus
71 extern "C"
72 {
73 #endif
74
75 void MBMotionSearch(VideoEncData *video, UChar *cur, UChar *best_cand[],
76 Int i0, Int j0, Int type_pred, Int fullsearch, Int *hp_guess);
77
78 Int fullsearch(VideoEncData *video, Vol *currVol, UChar *ref, UChar *cur,
79 Int *imin, Int *jmin, Int ilow, Int ihigh, Int jlow, Int jhigh);
80 Int fullsearchBlk(VideoEncData *video, Vol *currVol, UChar *cent, UChar *cur,
81 Int *imin, Int *jmin, Int ilow, Int ihigh, Int jlow, Int jhigh, Int range);
82 void CandidateSelection(Int *mvx, Int *mvy, Int *num_can, Int imb, Int jmb,
83 VideoEncData *video, Int type_pred);
84 void RasterIntraUpdate(UChar *intraArray, UChar *Mode, Int totalMB, Int numRefresh);
85 void ResetIntraUpdate(UChar *intraArray, Int totalMB);
86 void ResetIntraUpdateRegion(UChar *intraArray, Int start_i, Int rwidth,
87 Int start_j, Int rheight, Int mbwidth, Int mbheight);
88
89 void MoveNeighborSAD(Int dn[], Int new_loc);
90 Int FindMin(Int dn[]);
91 void PrepareCurMB(VideoEncData *video, UChar *cur);
92
93 #ifdef __cplusplus
94 }
95 #endif
96
97 /***************************************/
98 /* 2/28/01, for HYPOTHESIS TESTING */
99 #ifdef HTFM /* defined in mp4def.h */
100 #ifdef __cplusplus
101 extern "C"
102 {
103 #endif
104 void CalcThreshold(double pf, double exp_lamda[], Int nrmlz_th[]);
105 void HTFMPrepareCurMB(VideoEncData *video, HTFM_Stat *htfm_stat, UChar *cur);
106 #ifdef __cplusplus
107 }
108 #endif
109
110
111 #define HTFM_Pf 0.25 /* 3/2/1, probability of false alarm, can be varied from 0 to 0.5 */
112 /***************************************/
113 #endif
114
115 #ifdef _SAD_STAT
116 ULong num_MB = 0;
117 ULong num_HP_MB = 0;
118 ULong num_Blk = 0;
119 ULong num_HP_Blk = 0;
120 ULong num_cand = 0;
121 ULong num_better_hp = 0;
122 ULong i_dist_from_guess = 0;
123 ULong j_dist_from_guess = 0;
124 ULong num_hp_not_zero = 0;
125 #endif
126
127
128
129 /*==================================================================
130 Function: MotionEstimation
131 Date: 10/3/2000
132 Purpose: Go through all macroblock for motion search and
133 determine scene change detection.
134 ====================================================================*/
135
MotionEstimation(VideoEncData * video)136 void MotionEstimation(VideoEncData *video)
137 {
138 UChar use_4mv = video->encParams->MV8x8_Enabled;
139 Vol *currVol = video->vol[video->currLayer];
140 Vop *currVop = video->currVop;
141 VideoEncFrameIO *currFrame = video->input;
142 Int i, j, comp;
143 Int mbwidth = currVol->nMBPerRow;
144 Int mbheight = currVol->nMBPerCol;
145 Int totalMB = currVol->nTotalMB;
146 Int width = currFrame->pitch;
147 UChar *mode_mb, *Mode = video->headerInfo.Mode;
148 MOT *mot_mb, **mot = video->mot;
149 UChar *intraArray = video->intraArray;
150 Int FS_en = video->encParams->FullSearch_Enabled;
151 void (*ComputeMBSum)(UChar *, Int, MOT *) = video->functionPointer->ComputeMBSum;
152 void (*ChooseMode)(UChar*, UChar*, Int, Int) = video->functionPointer->ChooseMode;
153
154 Int numIntra, start_i, numLoop, incr_i;
155 Int mbnum, offset;
156 UChar *cur, *best_cand[5];
157 Int sad8 = 0, sad16 = 0;
158 Int totalSAD = 0; /* average SAD for rate control */
159 Int skip_halfpel_4mv;
160 Int f_code_p, f_code_n, max_mag = 0, min_mag = 0;
161 Int type_pred;
162 Int xh[5] = {0, 0, 0, 0, 0};
163 Int yh[5] = {0, 0, 0, 0, 0}; /* half-pel */
164 UChar hp_mem4MV[17*17*4];
165
166 #ifdef HTFM
167 /***** HYPOTHESIS TESTING ********/ /* 2/28/01 */
168 Int collect = 0;
169 HTFM_Stat htfm_stat;
170 double newvar[16];
171 double exp_lamda[15];
172 /*********************************/
173 #endif
174 Int hp_guess = 0;
175 #ifdef PRINT_MV
176 FILE *fp_debug;
177 #endif
178
179 // FILE *fstat;
180 // static int frame_num = 0;
181
182 offset = 0;
183
184 if (video->currVop->predictionType == I_VOP)
185 { /* compute the SAV */
186 mbnum = 0;
187 cur = currFrame->yChan;
188
189 for (j = 0; j < mbheight; j++)
190 {
191 for (i = 0; i < mbwidth; i++)
192 {
193 video->mbnum = mbnum;
194 mot_mb = mot[mbnum];
195
196 (*ComputeMBSum)(cur + (i << 4), width, mot_mb);
197
198 totalSAD += mot_mb[0].sad;
199
200 mbnum++;
201 }
202 cur += (width << 4);
203 }
204
205 video->sumMAD = (float)totalSAD / (float)NumPixelMB;
206
207 ResetIntraUpdate(intraArray, totalMB);
208
209 return ;
210 }
211
212 /* 09/20/05 */
213 if (video->prevBaseVop->padded == 0 && !video->encParams->H263_Enabled)
214 {
215 PaddingEdge(video->prevBaseVop);
216 video->prevBaseVop->padded = 1;
217 }
218
219 /* Random INTRA update */
220 /* suggest to do it in CodeMB */
221 /* 2/21/2001 */
222 //if(video->encParams->RC_Type == CBR_1 || video->encParams->RC_Type == CBR_2)
223 if (video->currLayer == 0 && video->encParams->Refresh)
224 {
225 RasterIntraUpdate(intraArray, Mode, totalMB, video->encParams->Refresh);
226 }
227
228 video->sad_extra_info = NULL;
229
230 #ifdef HTFM
231 /***** HYPOTHESIS TESTING ********/ /* 2/28/01 */
232 InitHTFM(video, &htfm_stat, newvar, &collect);
233 /*********************************/
234 #endif
235
236 if ((video->encParams->SceneChange_Det == 1) /*&& video->currLayer==0 */
237 && ((video->encParams->LayerFrameRate[0] < 5.0) || (video->numVopsInGOP > MIN_GOP)))
238 /* do not try to detect a new scene if low frame rate and too close to previous I-frame */
239 {
240 incr_i = 2;
241 numLoop = 2;
242 start_i = 1;
243 type_pred = 0; /* for initial candidate selection */
244 }
245 else
246 {
247 incr_i = 1;
248 numLoop = 1;
249 start_i = 0;
250 type_pred = 2;
251 }
252
253 /* First pass, loop thru half the macroblock */
254 /* determine scene change */
255 /* Second pass, for the rest of macroblocks */
256 numIntra = 0;
257 while (numLoop--)
258 {
259 for (j = 0; j < mbheight; j++)
260 {
261 if (incr_i > 1)
262 start_i = (start_i == 0 ? 1 : 0) ; /* toggle 0 and 1 */
263
264 offset = width * (j << 4) + (start_i << 4);
265
266 mbnum = j * mbwidth + start_i;
267
268 for (i = start_i; i < mbwidth; i += incr_i)
269 {
270 video->mbnum = mbnum;
271 mot_mb = mot[mbnum];
272 mode_mb = Mode + mbnum;
273
274 cur = currFrame->yChan + offset;
275
276
277 if (*mode_mb != MODE_INTRA)
278 {
279 #if defined(HTFM)
280 HTFMPrepareCurMB(video, &htfm_stat, cur);
281 #else
282 PrepareCurMB(video, cur);
283 #endif
284 /************************************************************/
285 /******** full-pel 1MV and 4MVs search **********************/
286
287 #ifdef _SAD_STAT
288 num_MB++;
289 #endif
290 MBMotionSearch(video, cur, best_cand, i << 4, j << 4, type_pred,
291 FS_en, &hp_guess);
292
293 #ifdef PRINT_MV
294 fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
295 fprintf(fp_debug, "#%d (%d,%d,%d) : ", mbnum, mot_mb[0].x, mot_mb[0].y, mot_mb[0].sad);
296 fprintf(fp_debug, "(%d,%d,%d) : (%d,%d,%d) : (%d,%d,%d) : (%d,%d,%d) : ==>\n",
297 mot_mb[1].x, mot_mb[1].y, mot_mb[1].sad,
298 mot_mb[2].x, mot_mb[2].y, mot_mb[2].sad,
299 mot_mb[3].x, mot_mb[3].y, mot_mb[3].sad,
300 mot_mb[4].x, mot_mb[4].y, mot_mb[4].sad);
301 fclose(fp_debug);
302 #endif
303 sad16 = mot_mb[0].sad;
304 #ifdef NO_INTER4V
305 sad8 = sad16;
306 #else
307 sad8 = mot_mb[1].sad + mot_mb[2].sad + mot_mb[3].sad + mot_mb[4].sad;
308 #endif
309
310 /* choose between INTRA or INTER */
311 (*ChooseMode)(mode_mb, cur, width, ((sad8 < sad16) ? sad8 : sad16));
312 }
313 else /* INTRA update, use for prediction 3/23/01 */
314 {
315 mot_mb[0].x = mot_mb[0].y = 0;
316 }
317
318 if (*mode_mb == MODE_INTRA)
319 {
320 numIntra++ ;
321
322 /* compute SAV for rate control and fast DCT, 11/28/00 */
323 (*ComputeMBSum)(cur, width, mot_mb);
324
325 /* leave mot_mb[0] as it is for fast motion search */
326 /* set the 4 MVs to zeros */
327 for (comp = 1; comp <= 4; comp++)
328 {
329 mot_mb[comp].x = 0;
330 mot_mb[comp].y = 0;
331 }
332 #ifdef PRINT_MV
333 fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
334 fprintf(fp_debug, "\n");
335 fclose(fp_debug);
336 #endif
337 }
338 else /* *mode_mb = MODE_INTER;*/
339 {
340 if (video->encParams->HalfPel_Enabled)
341 {
342 #ifdef _SAD_STAT
343 num_HP_MB++;
344 #endif
345 /* find half-pel resolution motion vector */
346 FindHalfPelMB(video, cur, mot_mb, best_cand[0],
347 i << 4, j << 4, xh, yh, hp_guess);
348 #ifdef PRINT_MV
349 fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
350 fprintf(fp_debug, "(%d,%d), %d\n", mot_mb[0].x, mot_mb[0].y, mot_mb[0].sad);
351 fclose(fp_debug);
352 #endif
353 skip_halfpel_4mv = ((sad16 - mot_mb[0].sad) <= (MB_Nb >> 1) + 1);
354 sad16 = mot_mb[0].sad;
355
356 #ifndef NO_INTER4V
357 if (use_4mv && !skip_halfpel_4mv)
358 {
359 /* Also decide 1MV or 4MV !!!!!!!!*/
360 sad8 = FindHalfPelBlk(video, cur, mot_mb, sad16,
361 best_cand, mode_mb, i << 4, j << 4, xh, yh, hp_mem4MV);
362
363 #ifdef PRINT_MV
364 fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
365 fprintf(fp_debug, " (%d,%d,%d) : (%d,%d,%d) : (%d,%d,%d) : (%d,%d,%d) \n",
366 mot_mb[1].x, mot_mb[1].y, mot_mb[1].sad,
367 mot_mb[2].x, mot_mb[2].y, mot_mb[2].sad,
368 mot_mb[3].x, mot_mb[3].y, mot_mb[3].sad,
369 mot_mb[4].x, mot_mb[4].y, mot_mb[4].sad);
370 fclose(fp_debug);
371 #endif
372 }
373 #endif /* NO_INTER4V */
374 }
375 else /* HalfPel_Enabled ==0 */
376 {
377 #ifndef NO_INTER4V
378 //if(sad16 < sad8-PREF_16_VEC)
379 if (sad16 - PREF_16_VEC > sad8)
380 {
381 *mode_mb = MODE_INTER4V;
382 }
383 #endif
384 }
385 #if (ZERO_MV_PREF==2) /* use mot_mb[7].sad as d0 computed in MBMotionSearch*/
386 /******************************************************/
387 if (mot_mb[7].sad - PREF_NULL_VEC < sad16 && mot_mb[7].sad - PREF_NULL_VEC < sad8)
388 {
389 mot_mb[0].sad = mot_mb[7].sad - PREF_NULL_VEC;
390 mot_mb[0].x = mot_mb[0].y = 0;
391 *mode_mb = MODE_INTER;
392 }
393 /******************************************************/
394 #endif
395 if (*mode_mb == MODE_INTER)
396 {
397 if (mot_mb[0].x == 0 && mot_mb[0].y == 0) /* use zero vector */
398 mot_mb[0].sad += PREF_NULL_VEC; /* add back the bias */
399
400 mot_mb[1].sad = mot_mb[2].sad = mot_mb[3].sad = mot_mb[4].sad = (mot_mb[0].sad + 2) >> 2;
401 mot_mb[1].x = mot_mb[2].x = mot_mb[3].x = mot_mb[4].x = mot_mb[0].x;
402 mot_mb[1].y = mot_mb[2].y = mot_mb[3].y = mot_mb[4].y = mot_mb[0].y;
403
404 }
405 }
406
407 /* find maximum magnitude */
408 /* compute average SAD for rate control, 11/28/00 */
409 if (*mode_mb == MODE_INTER)
410 {
411 #ifdef PRINT_MV
412 fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
413 fprintf(fp_debug, "%d MODE_INTER\n", mbnum);
414 fclose(fp_debug);
415 #endif
416 totalSAD += mot_mb[0].sad;
417 if (mot_mb[0].x > max_mag)
418 max_mag = mot_mb[0].x;
419 if (mot_mb[0].y > max_mag)
420 max_mag = mot_mb[0].y;
421 if (mot_mb[0].x < min_mag)
422 min_mag = mot_mb[0].x;
423 if (mot_mb[0].y < min_mag)
424 min_mag = mot_mb[0].y;
425 }
426 else if (*mode_mb == MODE_INTER4V)
427 {
428 #ifdef PRINT_MV
429 fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
430 fprintf(fp_debug, "%d MODE_INTER4V\n", mbnum);
431 fclose(fp_debug);
432 #endif
433 totalSAD += sad8;
434 for (comp = 1; comp <= 4; comp++)
435 {
436 if (mot_mb[comp].x > max_mag)
437 max_mag = mot_mb[comp].x;
438 if (mot_mb[comp].y > max_mag)
439 max_mag = mot_mb[comp].y;
440 if (mot_mb[comp].x < min_mag)
441 min_mag = mot_mb[comp].x;
442 if (mot_mb[comp].y < min_mag)
443 min_mag = mot_mb[comp].y;
444 }
445 }
446 else /* MODE_INTRA */
447 {
448 #ifdef PRINT_MV
449 fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
450 fprintf(fp_debug, "%d MODE_INTRA\n", mbnum);
451 fclose(fp_debug);
452 #endif
453 totalSAD += mot_mb[0].sad;
454 }
455 mbnum += incr_i;
456 offset += (incr_i << 4);
457
458 }
459 }
460
461 if (incr_i > 1 && numLoop) /* scene change on and first loop */
462 {
463 //if(numIntra > ((totalMB>>3)<<1) + (totalMB>>3)) /* 75% of 50%MBs */
464 if (numIntra > (0.30*(totalMB / 2.0))) /* 15% of 50%MBs */
465 {
466 /******** scene change detected *******************/
467 currVop->predictionType = I_VOP;
468 M4VENC_MEMSET(Mode, MODE_INTRA, sizeof(UChar)*totalMB); /* set this for MB level coding*/
469 currVop->quantizer = video->encParams->InitQuantIvop[video->currLayer];
470
471 /* compute the SAV for rate control & fast DCT */
472 totalSAD = 0;
473 offset = 0;
474 mbnum = 0;
475 cur = currFrame->yChan;
476
477 for (j = 0; j < mbheight; j++)
478 {
479 for (i = 0; i < mbwidth; i++)
480 {
481 video->mbnum = mbnum;
482 mot_mb = mot[mbnum];
483
484
485 (*ComputeMBSum)(cur + (i << 4), width, mot_mb);
486 totalSAD += mot_mb[0].sad;
487
488 mbnum++;
489 }
490 cur += (width << 4);
491 }
492
493 video->sumMAD = (float)totalSAD / (float)NumPixelMB;
494 ResetIntraUpdate(intraArray, totalMB);
495 /* video->numVopsInGOP=0; 3/13/01 move it to vop.c*/
496
497 return ;
498 }
499 }
500 /******** no scene change, continue motion search **********************/
501 start_i = 0;
502 type_pred++; /* second pass */
503 }
504
505 video->sumMAD = (float)totalSAD / (float)NumPixelMB; /* avg SAD */
506
507 /* find f_code , 10/27/2000 */
508 f_code_p = 1;
509 while ((max_mag >> (4 + f_code_p)) > 0)
510 f_code_p++;
511
512 f_code_n = 1;
513 min_mag *= -1;
514 while ((min_mag - 1) >> (4 + f_code_n) > 0)
515 f_code_n++;
516
517 currVop->fcodeForward = (f_code_p > f_code_n ? f_code_p : f_code_n);
518
519 #ifdef HTFM
520 /***** HYPOTHESIS TESTING ********/ /* 2/28/01 */
521 if (collect)
522 {
523 collect = 0;
524 UpdateHTFM(video, newvar, exp_lamda, &htfm_stat);
525 }
526 /*********************************/
527 #endif
528
529 return ;
530 }
531
532
533 #ifdef HTFM
InitHTFM(VideoEncData * video,HTFM_Stat * htfm_stat,double * newvar,Int * collect)534 void InitHTFM(VideoEncData *video, HTFM_Stat *htfm_stat, double *newvar, Int *collect)
535 {
536 Int i;
537 Int lx = video->currVop->width; // padding
538 Int lx2 = lx << 1;
539 Int lx3 = lx2 + lx;
540 Int rx = video->currVop->pitch;
541 Int rx2 = rx << 1;
542 Int rx3 = rx2 + rx;
543
544 Int *offset, *offset2;
545
546 /* 4/11/01, collect data every 30 frames, doesn't have to be base layer */
547 if (((Int)video->numVopsInGOP) % 30 == 1)
548 {
549
550 *collect = 1;
551
552 htfm_stat->countbreak = 0;
553 htfm_stat->abs_dif_mad_avg = 0;
554
555 for (i = 0; i < 16; i++)
556 {
557 newvar[i] = 0.0;
558 }
559 // video->functionPointer->SAD_MB_PADDING = &SAD_MB_PADDING_HTFM_Collect;
560 video->functionPointer->SAD_Macroblock = &SAD_MB_HTFM_Collect;
561 video->functionPointer->SAD_MB_HalfPel[0] = NULL;
562 video->functionPointer->SAD_MB_HalfPel[1] = &SAD_MB_HP_HTFM_Collectxh;
563 video->functionPointer->SAD_MB_HalfPel[2] = &SAD_MB_HP_HTFM_Collectyh;
564 video->functionPointer->SAD_MB_HalfPel[3] = &SAD_MB_HP_HTFM_Collectxhyh;
565 video->sad_extra_info = (void*)(htfm_stat);
566 offset = htfm_stat->offsetArray;
567 offset2 = htfm_stat->offsetRef;
568 }
569 else
570 {
571 // video->functionPointer->SAD_MB_PADDING = &SAD_MB_PADDING_HTFM;
572 video->functionPointer->SAD_Macroblock = &SAD_MB_HTFM;
573 video->functionPointer->SAD_MB_HalfPel[0] = NULL;
574 video->functionPointer->SAD_MB_HalfPel[1] = &SAD_MB_HP_HTFMxh;
575 video->functionPointer->SAD_MB_HalfPel[2] = &SAD_MB_HP_HTFMyh;
576 video->functionPointer->SAD_MB_HalfPel[3] = &SAD_MB_HP_HTFMxhyh;
577 video->sad_extra_info = (void*)(video->nrmlz_th);
578 offset = video->nrmlz_th + 16;
579 offset2 = video->nrmlz_th + 32;
580 }
581
582 offset[0] = 0;
583 offset[1] = lx2 + 2;
584 offset[2] = 2;
585 offset[3] = lx2;
586 offset[4] = lx + 1;
587 offset[5] = lx3 + 3;
588 offset[6] = lx + 3;
589 offset[7] = lx3 + 1;
590 offset[8] = lx;
591 offset[9] = lx3 + 2;
592 offset[10] = lx3 ;
593 offset[11] = lx + 2 ;
594 offset[12] = 1;
595 offset[13] = lx2 + 3;
596 offset[14] = lx2 + 1;
597 offset[15] = 3;
598
599 offset2[0] = 0;
600 offset2[1] = rx2 + 2;
601 offset2[2] = 2;
602 offset2[3] = rx2;
603 offset2[4] = rx + 1;
604 offset2[5] = rx3 + 3;
605 offset2[6] = rx + 3;
606 offset2[7] = rx3 + 1;
607 offset2[8] = rx;
608 offset2[9] = rx3 + 2;
609 offset2[10] = rx3 ;
610 offset2[11] = rx + 2 ;
611 offset2[12] = 1;
612 offset2[13] = rx2 + 3;
613 offset2[14] = rx2 + 1;
614 offset2[15] = 3;
615
616 return ;
617 }
618
UpdateHTFM(VideoEncData * video,double * newvar,double * exp_lamda,HTFM_Stat * htfm_stat)619 void UpdateHTFM(VideoEncData *video, double *newvar, double *exp_lamda, HTFM_Stat *htfm_stat)
620 {
621 if (htfm_stat->countbreak == 0)
622 htfm_stat->countbreak = 1;
623
624 newvar[0] = (double)(htfm_stat->abs_dif_mad_avg) / (htfm_stat->countbreak * 16.);
625
626 if (newvar[0] < 0.001)
627 {
628 newvar[0] = 0.001; /* to prevent floating overflow */
629 }
630 exp_lamda[0] = 1 / (newvar[0] * 1.4142136);
631 exp_lamda[1] = exp_lamda[0] * 1.5825;
632 exp_lamda[2] = exp_lamda[0] * 2.1750;
633 exp_lamda[3] = exp_lamda[0] * 3.5065;
634 exp_lamda[4] = exp_lamda[0] * 3.1436;
635 exp_lamda[5] = exp_lamda[0] * 3.5315;
636 exp_lamda[6] = exp_lamda[0] * 3.7449;
637 exp_lamda[7] = exp_lamda[0] * 4.5854;
638 exp_lamda[8] = exp_lamda[0] * 4.6191;
639 exp_lamda[9] = exp_lamda[0] * 5.4041;
640 exp_lamda[10] = exp_lamda[0] * 6.5974;
641 exp_lamda[11] = exp_lamda[0] * 10.5341;
642 exp_lamda[12] = exp_lamda[0] * 10.0719;
643 exp_lamda[13] = exp_lamda[0] * 12.0516;
644 exp_lamda[14] = exp_lamda[0] * 15.4552;
645
646 CalcThreshold(HTFM_Pf, exp_lamda, video->nrmlz_th);
647 return ;
648 }
649
650
CalcThreshold(double pf,double exp_lamda[],Int nrmlz_th[])651 void CalcThreshold(double pf, double exp_lamda[], Int nrmlz_th[])
652 {
653 Int i;
654 double temp[15];
655 // printf("\nLamda: ");
656
657 /* parametric PREMODELling */
658 for (i = 0; i < 15; i++)
659 {
660 // printf("%g ",exp_lamda[i]);
661 if (pf < 0.5)
662 temp[i] = 1 / exp_lamda[i] * M4VENC_LOG(2 * pf);
663 else
664 temp[i] = -1 / exp_lamda[i] * M4VENC_LOG(2 * (1 - pf));
665 }
666
667 nrmlz_th[15] = 0;
668 for (i = 0; i < 15; i++) /* scale upto no.pixels */
669 nrmlz_th[i] = (Int)(temp[i] * ((i + 1) << 4) + 0.5);
670
671 return ;
672 }
673
HTFMPrepareCurMB(VideoEncData * video,HTFM_Stat * htfm_stat,UChar * cur)674 void HTFMPrepareCurMB(VideoEncData *video, HTFM_Stat *htfm_stat, UChar *cur)
675 {
676 void* tmp = (void*)(video->currYMB);
677 ULong *htfmMB = (ULong*)tmp;
678 UChar *ptr, byte;
679 Int *offset;
680 Int i;
681 ULong word;
682 Int width = video->currVop->width;
683
684 if (((Int)video->numVopsInGOP) % 30 == 1)
685 {
686 offset = htfm_stat->offsetArray;
687 }
688 else
689 {
690 offset = video->nrmlz_th + 16;
691 }
692
693 for (i = 0; i < 16; i++)
694 {
695 ptr = cur + offset[i];
696 word = ptr[0];
697 byte = ptr[4];
698 word |= (byte << 8);
699 byte = ptr[8];
700 word |= (byte << 16);
701 byte = ptr[12];
702 word |= (byte << 24);
703 *htfmMB++ = word;
704
705 word = *(ptr += (width << 2));
706 byte = ptr[4];
707 word |= (byte << 8);
708 byte = ptr[8];
709 word |= (byte << 16);
710 byte = ptr[12];
711 word |= (byte << 24);
712 *htfmMB++ = word;
713
714 word = *(ptr += (width << 2));
715 byte = ptr[4];
716 word |= (byte << 8);
717 byte = ptr[8];
718 word |= (byte << 16);
719 byte = ptr[12];
720 word |= (byte << 24);
721 *htfmMB++ = word;
722
723 word = *(ptr += (width << 2));
724 byte = ptr[4];
725 word |= (byte << 8);
726 byte = ptr[8];
727 word |= (byte << 16);
728 byte = ptr[12];
729 word |= (byte << 24);
730 *htfmMB++ = word;
731 }
732
733 return ;
734 }
735
736
737 #endif
738
PrepareCurMB(VideoEncData * video,UChar * cur)739 void PrepareCurMB(VideoEncData *video, UChar *cur)
740 {
741 void* tmp = (void*)(video->currYMB);
742 ULong *currYMB = (ULong*)tmp;
743 Int i;
744 Int width = video->currVop->width;
745
746 cur -= width;
747
748 for (i = 0; i < 16; i++)
749 {
750 *currYMB++ = *((ULong*)(cur += width));
751 *currYMB++ = *((ULong*)(cur + 4));
752 *currYMB++ = *((ULong*)(cur + 8));
753 *currYMB++ = *((ULong*)(cur + 12));
754 }
755
756 return ;
757 }
758
759
760 /*==================================================================
761 Function: MBMotionSearch
762 Date: 09/06/2000
763 Purpose: Perform motion estimation for a macroblock.
764 Find 1MV and 4MVs in half-pels resolutions.
765 Using ST1 algorithm provided by Chalidabhongse and Kuo
766 CSVT March'98.
767
768 ==================================================================*/
769
MBMotionSearch(VideoEncData * video,UChar * cur,UChar * best_cand[],Int i0,Int j0,Int type_pred,Int FS_en,Int * hp_guess)770 void MBMotionSearch(VideoEncData *video, UChar *cur, UChar *best_cand[],
771 Int i0, Int j0, Int type_pred, Int FS_en, Int *hp_guess)
772 {
773 Vol *currVol = video->vol[video->currLayer];
774 UChar *ref, *cand, *ncand = NULL, *cur8;
775 void *extra_info = video->sad_extra_info;
776 Int mbnum = video->mbnum;
777 Int width = video->currVop->width; /* 6/12/01, must be multiple of 16 */
778 Int height = video->currVop->height;
779 MOT **mot = video->mot;
780 UChar use_4mv = video->encParams->MV8x8_Enabled;
781 UChar h263_mode = video->encParams->H263_Enabled;
782 Int(*SAD_Macroblock)(UChar*, UChar*, Int, void*) = video->functionPointer->SAD_Macroblock;
783 Int(*SAD_Block)(UChar*, UChar*, Int, Int, void*) = video->functionPointer->SAD_Block;
784 VideoEncParams *encParams = video->encParams;
785 Int range = encParams->SearchRange;
786
787 Int lx = video->currVop->pitch; /* padding */
788 Int comp;
789 Int i, j, imin, jmin, ilow, ihigh, jlow, jhigh, iorg, jorg;
790 Int d, dmin, dn[9];
791 #if (ZERO_MV_PREF==1) /* compute (0,0) MV at the end */
792 Int d0;
793 #endif
794 Int k;
795 Int mvx[5], mvy[5], imin0, jmin0;
796 Int num_can, center_again;
797 Int last_loc, new_loc = 0;
798 Int step, max_step = range >> 1;
799 Int next;
800
801 ref = video->forwardRefVop->yChan; /* origin of actual frame */
802
803 cur = video->currYMB; /* use smaller memory space for current MB */
804
805 /* find limit of the search (adjusting search range)*/
806
807 if (!h263_mode)
808 {
809 ilow = i0 - range;
810 if (ilow < -15)
811 ilow = -15;
812 ihigh = i0 + range - 1;
813 if (ihigh > width - 1)
814 ihigh = width - 1;
815 jlow = j0 - range;
816 if (jlow < -15)
817 jlow = -15;
818 jhigh = j0 + range - 1;
819 if (jhigh > height - 1)
820 jhigh = height - 1;
821 }
822 else
823 {
824 ilow = i0 - range;
825 if (ilow < 0)
826 ilow = 0;
827 ihigh = i0 + range - 1;
828 if (ihigh > width - 16)
829 ihigh = width - 16;
830 jlow = j0 - range;
831 if (jlow < 0)
832 jlow = 0;
833 jhigh = j0 + range - 1;
834 if (jhigh > height - 16)
835 jhigh = height - 16;
836 }
837
838 imin = i0;
839 jmin = j0; /* needed for fullsearch */
840 ncand = ref + imin + jmin * lx;
841
842 /* for first row of MB, fullsearch can be used */
843 if (FS_en)
844 {
845 *hp_guess = 0; /* no guess for fast half-pel */
846
847 dmin = fullsearch(video, currVol, ref, cur, &imin, &jmin, ilow, ihigh, jlow, jhigh);
848
849 ncand = ref + imin + jmin * lx;
850
851 mot[mbnum][0].sad = dmin;
852 mot[mbnum][0].x = (imin - i0) << 1;
853 mot[mbnum][0].y = (jmin - j0) << 1;
854 imin0 = imin << 1; /* 16x16 MV in half-pel resolution */
855 jmin0 = jmin << 1;
856 best_cand[0] = ncand;
857 }
858 else
859 { /* 4/7/01, modified this testing for fullsearch the top row to only upto (0,3) MB */
860 /* upto 30% complexity saving with the same complexity */
861 if (video->forwardRefVop->predictionType == I_VOP && j0 == 0 && i0 <= 64 && type_pred != 1)
862 {
863 *hp_guess = 0; /* no guess for fast half-pel */
864 dmin = fullsearch(video, currVol, ref, cur, &imin, &jmin, ilow, ihigh, jlow, jhigh);
865 ncand = ref + imin + jmin * lx;
866 }
867 else
868 {
869 /************** initialize candidate **************************/
870 /* find initial motion vector */
871 CandidateSelection(mvx, mvy, &num_can, i0 >> 4, j0 >> 4, video, type_pred);
872
873 dmin = 65535;
874
875 /* check if all are equal */
876 if (num_can == ALL_CAND_EQUAL)
877 {
878 i = i0 + mvx[0];
879 j = j0 + mvy[0];
880
881 if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
882 {
883 cand = ref + i + j * lx;
884
885 d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
886
887 if (d < dmin)
888 {
889 dmin = d;
890 imin = i;
891 jmin = j;
892 ncand = cand;
893 }
894 }
895 }
896 else
897 {
898 /************** evaluate unique candidates **********************/
899 for (k = 0; k < num_can; k++)
900 {
901 i = i0 + mvx[k];
902 j = j0 + mvy[k];
903
904 if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
905 {
906 cand = ref + i + j * lx;
907 d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
908
909 if (d < dmin)
910 {
911 dmin = d;
912 imin = i;
913 jmin = j;
914 ncand = cand;
915 }
916 else if ((d == dmin) && PV_ABS(mvx[k]) + PV_ABS(mvy[k]) < PV_ABS(i0 - imin) + PV_ABS(j0 - jmin))
917 {
918 dmin = d;
919 imin = i;
920 jmin = j;
921 ncand = cand;
922 }
923 }
924 }
925 }
926 if (num_can == 0 || dmin == 65535) /* no candidate selected */
927 {
928 ncand = ref + i0 + j0 * lx; /* use (0,0) MV as initial value */
929 mot[mbnum][7].sad = dmin = (*SAD_Macroblock)(ncand, cur, (65535 << 16) | lx, extra_info);
930 #if (ZERO_MV_PREF==1) /* compute (0,0) MV at the end */
931 d0 = dmin;
932 #endif
933 imin = i0;
934 jmin = j0;
935 }
936
937 #if (ZERO_MV_PREF==0) /* COMPUTE ZERO VECTOR FIRST !!!!!*/
938 dmin -= PREF_NULL_VEC;
939 #endif
940
941 /******************* local refinement ***************************/
942 center_again = 0;
943 last_loc = new_loc = 0;
944 // ncand = ref + jmin*lx + imin; /* center of the search */
945 step = 0;
946 dn[0] = dmin;
947 while (!center_again && step <= max_step)
948 {
949
950 MoveNeighborSAD(dn, last_loc);
951
952 center_again = 1;
953 i = imin;
954 j = jmin - 1;
955 cand = ref + i + j * lx;
956
957 /* starting from [0,-1] */
958 /* spiral check one step at a time*/
959 for (k = 2; k <= 8; k += 2)
960 {
961 if (!tab_exclude[last_loc][k]) /* exclude last step computation */
962 { /* not already computed */
963 if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
964 {
965 d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
966 dn[k] = d; /* keep it for half pel use */
967
968 if (d < dmin)
969 {
970 ncand = cand;
971 dmin = d;
972 imin = i;
973 jmin = j;
974 center_again = 0;
975 new_loc = k;
976 }
977 else if ((d == dmin) && PV_ABS(i0 - i) + PV_ABS(j0 - j) < PV_ABS(i0 - imin) + PV_ABS(j0 - jmin))
978 {
979 ncand = cand;
980 imin = i;
981 jmin = j;
982 center_again = 0;
983 new_loc = k;
984 }
985 }
986 }
987 if (k == 8) /* end side search*/
988 {
989 if (!center_again)
990 {
991 k = -1; /* start diagonal search */
992 cand -= lx;
993 j--;
994 }
995 }
996 else
997 {
998 next = refine_next[k][0];
999 i += next;
1000 cand += next;
1001 next = refine_next[k][1];
1002 j += next;
1003 cand += lx * next;
1004 }
1005 }
1006 last_loc = new_loc;
1007 step ++;
1008 }
1009 if (!center_again)
1010 MoveNeighborSAD(dn, last_loc);
1011
1012 *hp_guess = FindMin(dn);
1013
1014 }
1015
1016 #if (ZERO_MV_PREF==1) /* compute (0,0) MV at the end */
1017 if (d0 - PREF_NULL_VEC < dmin)
1018 {
1019 ncand = ref + i0 + j0 * lx;
1020 dmin = d0;
1021 imin = i0;
1022 jmin = j0;
1023 }
1024 #endif
1025 mot[mbnum][0].sad = dmin;
1026 mot[mbnum][0].x = (imin - i0) << 1;
1027 mot[mbnum][0].y = (jmin - j0) << 1;
1028 imin0 = imin << 1; /* 16x16 MV in half-pel resolution */
1029 jmin0 = jmin << 1;
1030 best_cand[0] = ncand;
1031 }
1032 /* imin and jmin is the best 1 MV */
1033 #ifndef NO_INTER4V
1034 /******************* Find 4 motion vectors ****************************/
1035 if (use_4mv && !h263_mode)
1036 {
1037 #ifdef _SAD_STAT
1038 num_Blk += 4;
1039 #endif
1040 /* starting from the best 1MV */
1041 //offset = imin + jmin*lx;
1042 iorg = i0;
1043 jorg = j0;
1044
1045 for (comp = 0; comp < 4; comp++)
1046 {
1047 i0 = iorg + ((comp & 1) << 3);
1048 j0 = jorg + ((comp & 2) << 2);
1049
1050 imin = (imin0 >> 1) + ((comp & 1) << 3); /* starting point from 16x16 MV */
1051 jmin = (jmin0 >> 1) + ((comp & 2) << 2);
1052 ncand = ref + imin + jmin * lx;
1053
1054 cur8 = cur + ((comp & 1) << 3) + (((comp & 2) << 2) << 4) ; /* 11/30/05, smaller cache */
1055
1056 /* find limit of the search (adjusting search range)*/
1057 ilow = i0 - range;
1058 ihigh = i0 + range - 1 ;/* 4/9/01 */
1059 if (ilow < -15)
1060 ilow = -15;
1061 if (ihigh > width - 1)
1062 ihigh = width - 1;
1063 jlow = j0 - range;
1064 jhigh = j0 + range - 1 ;/* 4/9/01 */
1065 if (jlow < -15)
1066 jlow = -15;
1067 if (jhigh > height - 1)
1068 jhigh = height - 1;
1069
1070 SAD_Block = video->functionPointer->SAD_Block;
1071
1072 if (FS_en) /* fullsearch enable, center around 16x16 MV */
1073 {
1074 dmin = fullsearchBlk(video, currVol, ncand, cur8, &imin, &jmin, ilow, ihigh, jlow, jhigh, range);
1075 ncand = ref + imin + jmin * lx;
1076
1077 mot[mbnum][comp+1].sad = dmin;
1078 mot[mbnum][comp+1].x = (imin - i0) << 1;
1079 mot[mbnum][comp+1].y = (jmin - j0) << 1;
1080 best_cand[comp+1] = ncand;
1081 }
1082 else /* no fullsearch, do local search */
1083 {
1084 /* starting point from 16x16 */
1085 dmin = (*SAD_Block)(ncand, cur8, 65536, lx, extra_info);
1086
1087 /******************* local refinement ***************************/
1088 center_again = 0;
1089 last_loc = 0;
1090
1091 while (!center_again)
1092 {
1093 center_again = 1;
1094 i = imin;
1095 j = jmin - 1;
1096 cand = ref + i + j * lx;
1097
1098 /* starting from [0,-1] */
1099 /* spiral check one step at a time*/
1100 for (k = 2; k <= 8; k += 2)
1101 {
1102 if (!tab_exclude[last_loc][k]) /* exclude last step computation */
1103 { /* not already computed */
1104 if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
1105 {
1106 d = (*SAD_Block)(cand, cur8, dmin, lx, extra_info);
1107
1108 if (d < dmin)
1109 {
1110 ncand = cand;
1111 dmin = d;
1112 imin = i;
1113 jmin = j;
1114 center_again = 0;
1115 new_loc = k;
1116 }
1117 else if ((d == dmin) &&
1118 PV_ABS(i0 - i) + PV_ABS(j0 - j) < PV_ABS(i0 - imin) + PV_ABS(j0 - jmin))
1119 {
1120 ncand = cand;
1121 imin = i;
1122 jmin = j;
1123 center_again = 0;
1124 new_loc = k;
1125 }
1126 }
1127 }
1128 if (k == 8) /* end side search*/
1129 {
1130 if (!center_again)
1131 {
1132 k = -1; /* start diagonal search */
1133 if (j <= height - 1 && j > 0) cand -= lx;
1134 j--;
1135 }
1136 }
1137 else
1138 {
1139 next = refine_next[k][0];
1140 cand += next;
1141 i += next;
1142 next = refine_next[k][1];
1143 cand += lx * next;
1144 j += next;
1145 }
1146 }
1147 last_loc = new_loc;
1148 }
1149 mot[mbnum][comp+1].sad = dmin;
1150 mot[mbnum][comp+1].x = (imin - i0) << 1;
1151 mot[mbnum][comp+1].y = (jmin - j0) << 1;
1152 best_cand[comp+1] = ncand;
1153 }
1154 /********************************************/
1155 }
1156 }
1157 else
1158 #endif /* NO_INTER4V */
1159 {
1160 mot[mbnum][1].sad = mot[mbnum][2].sad = mot[mbnum][3].sad = mot[mbnum][4].sad = (dmin + 2) >> 2;
1161 mot[mbnum][1].x = mot[mbnum][2].x = mot[mbnum][3].x = mot[mbnum][4].x = mot[mbnum][0].x;
1162 mot[mbnum][1].y = mot[mbnum][2].y = mot[mbnum][3].y = mot[mbnum][4].y = mot[mbnum][0].y;
1163 best_cand[1] = best_cand[2] = best_cand[3] = best_cand[4] = ncand;
1164
1165 }
1166 return ;
1167 }
1168
1169
1170 /*===============================================================================
1171 Function: fullsearch
1172 Date: 09/16/2000
1173 Purpose: Perform full-search motion estimation over the range of search
1174 region in a spiral-outward manner.
1175 Input/Output: VideoEncData, current Vol, previou Vop, pointer to the left corner of
1176 current VOP, current coord (also output), boundaries.
1177 ===============================================================================*/
1178
fullsearch(VideoEncData * video,Vol * currVol,UChar * prev,UChar * cur,Int * imin,Int * jmin,Int ilow,Int ihigh,Int jlow,Int jhigh)1179 Int fullsearch(VideoEncData *video, Vol *currVol, UChar *prev, UChar *cur,
1180 Int *imin, Int *jmin, Int ilow, Int ihigh, Int jlow, Int jhigh)
1181 {
1182 Int range = video->encParams->SearchRange;
1183 UChar *cand;
1184 Int i, j, k, l;
1185 Int d, dmin;
1186 Int i0 = *imin; /* current position */
1187 Int j0 = *jmin;
1188 Int(*SAD_Macroblock)(UChar*, UChar*, Int, void*) = video->functionPointer->SAD_Macroblock;
1189 void *extra_info = video->sad_extra_info;
1190 // UChar h263_mode = video->encParams->H263_Enabled;
1191 Int lx = video->currVop->pitch; /* with padding */
1192
1193 Int offset = i0 + j0 * lx;
1194
1195 OSCL_UNUSED_ARG(currVol);
1196
1197 cand = prev + offset;
1198
1199 dmin = (*SAD_Macroblock)(cand, cur, (65535 << 16) | lx, (void*)extra_info) - PREF_NULL_VEC;
1200
1201 /* perform spiral search */
1202 for (k = 1; k <= range; k++)
1203 {
1204
1205 i = i0 - k;
1206 j = j0 - k;
1207
1208 cand = prev + i + j * lx;
1209
1210 for (l = 0; l < 8*k; l++)
1211 {
1212 /* no need for boundary checking again */
1213 if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
1214 {
1215 d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, (void*)extra_info);
1216
1217 if (d < dmin)
1218 {
1219 dmin = d;
1220 *imin = i;
1221 *jmin = j;
1222 }
1223 else if ((d == dmin) && PV_ABS(i0 - i) + PV_ABS(j0 - j) < PV_ABS(i0 - *imin) + PV_ABS(j0 - *jmin))
1224 {
1225 dmin = d;
1226 *imin = i;
1227 *jmin = j;
1228 }
1229 }
1230
1231 if (l < (k << 1))
1232 {
1233 i++;
1234 cand++;
1235 }
1236 else if (l < (k << 2))
1237 {
1238 j++;
1239 cand += lx;
1240 }
1241 else if (l < ((k << 2) + (k << 1)))
1242 {
1243 i--;
1244 cand--;
1245 }
1246 else
1247 {
1248 j--;
1249 cand -= lx;
1250 }
1251 }
1252 }
1253
1254 return dmin;
1255 }
1256
1257 #ifndef NO_INTER4V
1258 /*===============================================================================
1259 Function: fullsearchBlk
1260 Date: 01/9/2001
1261 Purpose: Perform full-search motion estimation of an 8x8 block over the range
1262 of search region in a spiral-outward manner centered at the 16x16 MV.
1263 Input/Output: VideoEncData, MB coordinate, pointer to the initial MV on the
1264 reference, pointer to coor of current block, search range.
1265 ===============================================================================*/
fullsearchBlk(VideoEncData * video,Vol * currVol,UChar * cent,UChar * cur,Int * imin,Int * jmin,Int ilow,Int ihigh,Int jlow,Int jhigh,Int range)1266 Int fullsearchBlk(VideoEncData *video, Vol *currVol, UChar *cent, UChar *cur,
1267 Int *imin, Int *jmin, Int ilow, Int ihigh, Int jlow, Int jhigh, Int range)
1268 {
1269 UChar *cand, *ref;
1270 Int i, j, k, l, istart, jstart;
1271 Int d, dmin;
1272 Int lx = video->currVop->pitch; /* with padding */
1273 Int(*SAD_Block)(UChar*, UChar*, Int, Int, void*) = video->functionPointer->SAD_Block;
1274 void *extra_info = video->sad_extra_info;
1275
1276 OSCL_UNUSED_ARG(currVol);
1277
1278 /* starting point centered at 16x16 MV */
1279 ref = cent;
1280 istart = *imin;
1281 jstart = *jmin;
1282
1283 dmin = (*SAD_Block)(ref, cur, 65536, lx, (void*)extra_info);
1284
1285 cand = ref;
1286 /* perform spiral search */
1287 for (k = 1; k <= range; k++)
1288 {
1289
1290 i = istart - k;
1291 j = jstart - k;
1292 cand -= (lx + 1); /* candidate region */
1293
1294 for (l = 0; l < 8*k; l++)
1295 {
1296 /* no need for boundary checking again */
1297 if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
1298 {
1299 d = (*SAD_Block)(cand, cur, dmin, lx, (void*)extra_info);
1300
1301 if (d < dmin)
1302 {
1303 dmin = d;
1304 *imin = i;
1305 *jmin = j;
1306 }
1307 else if ((d == dmin) &&
1308 PV_ABS(istart - i) + PV_ABS(jstart - j) < PV_ABS(istart - *imin) + PV_ABS(jstart - *jmin))
1309 {
1310 dmin = d;
1311 *imin = i;
1312 *jmin = j;
1313 }
1314 }
1315
1316 if (l < (k << 1))
1317 {
1318 i++;
1319 cand++;
1320 }
1321 else if (l < (k << 2))
1322 {
1323 j++;
1324 cand += lx;
1325 }
1326 else if (l < ((k << 2) + (k << 1)))
1327 {
1328 i--;
1329 cand--;
1330 }
1331 else
1332 {
1333 j--;
1334 cand -= lx;
1335 }
1336 }
1337 }
1338
1339 return dmin;
1340 }
1341 #endif /* NO_INTER4V */
1342
1343 /*===============================================================================
1344 Function: CandidateSelection
1345 Date: 09/16/2000
1346 Purpose: Fill up the list of candidate using spatio-temporal correlation
1347 among neighboring blocks.
1348 Input/Output: type_pred = 0: first pass, 1: second pass, or no SCD
1349 Modified: 09/23/01, get rid of redundant candidates before passing back.
1350 ===============================================================================*/
1351
CandidateSelection(Int * mvx,Int * mvy,Int * num_can,Int imb,Int jmb,VideoEncData * video,Int type_pred)1352 void CandidateSelection(Int *mvx, Int *mvy, Int *num_can, Int imb, Int jmb,
1353 VideoEncData *video, Int type_pred)
1354 {
1355 MOT **mot = video->mot;
1356 MOT *pmot;
1357 Int mbnum = video->mbnum;
1358 Vol *currVol = video->vol[video->currLayer];
1359 Int mbwidth = currVol->nMBPerRow;
1360 Int mbheight = currVol->nMBPerCol;
1361 Int i, j, same, num1;
1362
1363 *num_can = 0;
1364
1365 if (video->forwardRefVop->predictionType == P_VOP)
1366 {
1367 /* Spatio-Temporal Candidate (five candidates) */
1368 if (type_pred == 0) /* first pass */
1369 {
1370 pmot = &mot[mbnum][0]; /* same coordinate previous frame */
1371 mvx[(*num_can)] = (pmot->x) >> 1;
1372 mvy[(*num_can)++] = (pmot->y) >> 1;
1373 if (imb >= (mbwidth >> 1) && imb > 0) /*left neighbor previous frame */
1374 {
1375 pmot = &mot[mbnum-1][0];
1376 mvx[(*num_can)] = (pmot->x) >> 1;
1377 mvy[(*num_can)++] = (pmot->y) >> 1;
1378 }
1379 else if (imb + 1 < mbwidth) /*right neighbor previous frame */
1380 {
1381 pmot = &mot[mbnum+1][0];
1382 mvx[(*num_can)] = (pmot->x) >> 1;
1383 mvy[(*num_can)++] = (pmot->y) >> 1;
1384 }
1385
1386 if (jmb < mbheight - 1) /*bottom neighbor previous frame */
1387 {
1388 pmot = &mot[mbnum+mbwidth][0];
1389 mvx[(*num_can)] = (pmot->x) >> 1;
1390 mvy[(*num_can)++] = (pmot->y) >> 1;
1391 }
1392 else if (jmb > 0) /*upper neighbor previous frame */
1393 {
1394 pmot = &mot[mbnum-mbwidth][0];
1395 mvx[(*num_can)] = (pmot->x) >> 1;
1396 mvy[(*num_can)++] = (pmot->y) >> 1;
1397 }
1398
1399 if (imb > 0 && jmb > 0) /* upper-left neighbor current frame*/
1400 {
1401 pmot = &mot[mbnum-mbwidth-1][0];
1402 mvx[(*num_can)] = (pmot->x) >> 1;
1403 mvy[(*num_can)++] = (pmot->y) >> 1;
1404 }
1405 if (jmb > 0 && imb < mbheight - 1) /* upper right neighbor current frame*/
1406 {
1407 pmot = &mot[mbnum-mbwidth+1][0];
1408 mvx[(*num_can)] = (pmot->x) >> 1;
1409 mvy[(*num_can)++] = (pmot->y) >> 1;
1410 }
1411 }
1412 else /* second pass */
1413 /* original ST1 algorithm */
1414 {
1415 pmot = &mot[mbnum][0]; /* same coordinate previous frame */
1416 mvx[(*num_can)] = (pmot->x) >> 1;
1417 mvy[(*num_can)++] = (pmot->y) >> 1;
1418
1419 if (imb > 0) /*left neighbor current frame */
1420 {
1421 pmot = &mot[mbnum-1][0];
1422 mvx[(*num_can)] = (pmot->x) >> 1;
1423 mvy[(*num_can)++] = (pmot->y) >> 1;
1424 }
1425 if (jmb > 0) /*upper neighbor current frame */
1426 {
1427 pmot = &mot[mbnum-mbwidth][0];
1428 mvx[(*num_can)] = (pmot->x) >> 1;
1429 mvy[(*num_can)++] = (pmot->y) >> 1;
1430 }
1431 if (imb < mbwidth - 1) /*right neighbor previous frame */
1432 {
1433 pmot = &mot[mbnum+1][0];
1434 mvx[(*num_can)] = (pmot->x) >> 1;
1435 mvy[(*num_can)++] = (pmot->y) >> 1;
1436 }
1437 if (jmb < mbheight - 1) /*bottom neighbor previous frame */
1438 {
1439 pmot = &mot[mbnum+mbwidth][0];
1440 mvx[(*num_can)] = (pmot->x) >> 1;
1441 mvy[(*num_can)++] = (pmot->y) >> 1;
1442 }
1443 }
1444 }
1445 else /* only Spatial Candidate (four candidates)*/
1446 {
1447 if (type_pred == 0) /*first pass*/
1448 {
1449 if (imb > 1) /* neighbor two blocks away to the left */
1450 {
1451 pmot = &mot[mbnum-2][0];
1452 mvx[(*num_can)] = (pmot->x) >> 1;
1453 mvy[(*num_can)++] = (pmot->y) >> 1;
1454 }
1455 if (imb > 0 && jmb > 0) /* upper-left neighbor */
1456 {
1457 pmot = &mot[mbnum-mbwidth-1][0];
1458 mvx[(*num_can)] = (pmot->x) >> 1;
1459 mvy[(*num_can)++] = (pmot->y) >> 1;
1460 }
1461 if (jmb > 0 && imb < mbheight - 1) /* upper right neighbor */
1462 {
1463 pmot = &mot[mbnum-mbwidth+1][0];
1464 mvx[(*num_can)] = (pmot->x) >> 1;
1465 mvy[(*num_can)++] = (pmot->y) >> 1;
1466 }
1467 }
1468 //#ifdef SCENE_CHANGE_DETECTION
1469 /* second pass (ST2 algorithm)*/
1470 else if (type_pred == 1) /* 4/7/01 */
1471 {
1472 if (imb > 0) /*left neighbor current frame */
1473 {
1474 pmot = &mot[mbnum-1][0];
1475 mvx[(*num_can)] = (pmot->x) >> 1;
1476 mvy[(*num_can)++] = (pmot->y) >> 1;
1477 }
1478 if (jmb > 0) /*upper neighbor current frame */
1479 {
1480 pmot = &mot[mbnum-mbwidth][0];
1481 mvx[(*num_can)] = (pmot->x) >> 1;
1482 mvy[(*num_can)++] = (pmot->y) >> 1;
1483 }
1484 if (imb < mbwidth - 1) /*right neighbor current frame */
1485 {
1486 pmot = &mot[mbnum+1][0];
1487 mvx[(*num_can)] = (pmot->x) >> 1;
1488 mvy[(*num_can)++] = (pmot->y) >> 1;
1489 }
1490 if (jmb < mbheight - 1) /*bottom neighbor current frame */
1491 {
1492 pmot = &mot[mbnum+mbwidth][0];
1493 mvx[(*num_can)] = (pmot->x) >> 1;
1494 mvy[(*num_can)++] = (pmot->y) >> 1;
1495 }
1496 }
1497 //#else
1498 else /* original ST1 algorithm */
1499 {
1500 if (imb > 0) /*left neighbor current frame */
1501 {
1502 pmot = &mot[mbnum-1][0];
1503 mvx[(*num_can)] = (pmot->x) >> 1;
1504 mvy[(*num_can)++] = (pmot->y) >> 1;
1505
1506 if (jmb > 0) /*upper-left neighbor current frame */
1507 {
1508 pmot = &mot[mbnum-mbwidth-1][0];
1509 mvx[(*num_can)] = (pmot->x) >> 1;
1510 mvy[(*num_can)++] = (pmot->y) >> 1;
1511 }
1512
1513 }
1514 if (jmb > 0) /*upper neighbor current frame */
1515 {
1516 pmot = &mot[mbnum-mbwidth][0];
1517 mvx[(*num_can)] = (pmot->x) >> 1;
1518 mvy[(*num_can)++] = (pmot->y) >> 1;
1519
1520 if (imb < mbheight - 1) /*upper-right neighbor current frame */
1521 {
1522 pmot = &mot[mbnum-mbwidth+1][0];
1523 mvx[(*num_can)] = (pmot->x) >> 1;
1524 mvy[(*num_can)++] = (pmot->y) >> 1;
1525 }
1526 }
1527 }
1528 //#endif
1529 }
1530
1531 /* 3/23/01, remove redundant candidate (possible k-mean) */
1532 num1 = *num_can;
1533 *num_can = 1;
1534 for (i = 1; i < num1; i++)
1535 {
1536 same = 0;
1537 j = 0;
1538 while (!same && j < *num_can)
1539 {
1540 #if (CANDIDATE_DISTANCE==0)
1541 if (mvx[i] == mvx[j] && mvy[i] == mvy[j])
1542 #else
1543 // modified k-mean, 3/24/01, shouldn't be greater than 3
1544 if (PV_ABS(mvx[i] - mvx[j]) + PV_ABS(mvy[i] - mvy[j]) < CANDIDATE_DISTANCE)
1545 #endif
1546 same = 1;
1547 j++;
1548 }
1549 if (!same)
1550 {
1551 mvx[*num_can] = mvx[i];
1552 mvy[*num_can] = mvy[i];
1553 (*num_can)++;
1554 }
1555 }
1556
1557 #ifdef _SAD_STAT
1558 num_cand += (*num_can);
1559 #endif
1560
1561 if (num1 == 5 && *num_can == 1)
1562 *num_can = ALL_CAND_EQUAL; /* all are equal */
1563
1564 return ;
1565 }
1566
1567 /*===========================================================================
1568 Function: RasterIntraUpdate
1569 Date: 2/26/01
1570 Purpose: To raster-scan assign INTRA-update .
1571 N macroblocks are updated (also was programmable).
1572 ===========================================================================*/
RasterIntraUpdate(UChar * intraArray,UChar * Mode,Int totalMB,Int numRefresh)1573 void RasterIntraUpdate(UChar *intraArray, UChar *Mode, Int totalMB, Int numRefresh)
1574 {
1575 Int indx, i;
1576
1577 /* find the last refresh MB */
1578 indx = 0;
1579 while (intraArray[indx] == 1 && indx < totalMB)
1580 indx++;
1581
1582 /* add more */
1583 for (i = 0; i < numRefresh && indx < totalMB; i++)
1584 {
1585 Mode[indx] = MODE_INTRA;
1586 intraArray[indx++] = 1;
1587 }
1588
1589 /* if read the end of frame, reset and loop around */
1590 if (indx >= totalMB - 1)
1591 {
1592 ResetIntraUpdate(intraArray, totalMB);
1593 indx = 0;
1594 while (i < numRefresh && indx < totalMB)
1595 {
1596 intraArray[indx] = 1;
1597 Mode[indx++] = MODE_INTRA;
1598 i++;
1599 }
1600 }
1601
1602 return ;
1603 }
1604
1605 /*===========================================================================
1606 Function: ResetIntraUpdate
1607 Date: 11/28/00
1608 Purpose: Reset already intra updated flags to all zero
1609 ===========================================================================*/
1610
ResetIntraUpdate(UChar * intraArray,Int totalMB)1611 void ResetIntraUpdate(UChar *intraArray, Int totalMB)
1612 {
1613 M4VENC_MEMSET(intraArray, 0, sizeof(UChar)*totalMB);
1614 return ;
1615 }
1616
1617 /*===========================================================================
1618 Function: ResetIntraUpdateRegion
1619 Date: 12/1/00
1620 Purpose: Reset already intra updated flags in one region to all zero
1621 ===========================================================================*/
ResetIntraUpdateRegion(UChar * intraArray,Int start_i,Int rwidth,Int start_j,Int rheight,Int mbwidth,Int mbheight)1622 void ResetIntraUpdateRegion(UChar *intraArray, Int start_i, Int rwidth,
1623 Int start_j, Int rheight, Int mbwidth, Int mbheight)
1624 {
1625 Int indx, j;
1626
1627 if (start_i + rwidth >= mbwidth)
1628 rwidth = mbwidth - start_i;
1629 if (start_j + rheight >= mbheight)
1630 rheight = mbheight - start_j;
1631
1632 for (j = start_j; j < start_j + rheight; j++)
1633 {
1634 indx = j * mbwidth;
1635 M4VENC_MEMSET(intraArray + indx + start_i, 0, sizeof(UChar)*rwidth);
1636 }
1637
1638 return ;
1639 }
1640
1641 /*************************************************************
1642 Function: MoveNeighborSAD
1643 Date: 3/27/01
1644 Purpose: Move neighboring SAD around when center has shifted
1645 *************************************************************/
1646
MoveNeighborSAD(Int dn[],Int new_loc)1647 void MoveNeighborSAD(Int dn[], Int new_loc)
1648 {
1649 Int tmp[9];
1650 tmp[0] = dn[0];
1651 tmp[1] = dn[1];
1652 tmp[2] = dn[2];
1653 tmp[3] = dn[3];
1654 tmp[4] = dn[4];
1655 tmp[5] = dn[5];
1656 tmp[6] = dn[6];
1657 tmp[7] = dn[7];
1658 tmp[8] = dn[8];
1659 dn[0] = dn[1] = dn[2] = dn[3] = dn[4] = dn[5] = dn[6] = dn[7] = dn[8] = 65536;
1660
1661 switch (new_loc)
1662 {
1663 case 0:
1664 break;
1665 case 1:
1666 dn[4] = tmp[2];
1667 dn[5] = tmp[0];
1668 dn[6] = tmp[8];
1669 break;
1670 case 2:
1671 dn[4] = tmp[3];
1672 dn[5] = tmp[4];
1673 dn[6] = tmp[0];
1674 dn[7] = tmp[8];
1675 dn[8] = tmp[1];
1676 break;
1677 case 3:
1678 dn[6] = tmp[4];
1679 dn[7] = tmp[0];
1680 dn[8] = tmp[2];
1681 break;
1682 case 4:
1683 dn[1] = tmp[2];
1684 dn[2] = tmp[3];
1685 dn[6] = tmp[5];
1686 dn[7] = tmp[6];
1687 dn[8] = tmp[0];
1688 break;
1689 case 5:
1690 dn[1] = tmp[0];
1691 dn[2] = tmp[4];
1692 dn[8] = tmp[6];
1693 break;
1694 case 6:
1695 dn[1] = tmp[8];
1696 dn[2] = tmp[0];
1697 dn[3] = tmp[4];
1698 dn[4] = tmp[5];
1699 dn[8] = tmp[7];
1700 break;
1701 case 7:
1702 dn[2] = tmp[8];
1703 dn[3] = tmp[0];
1704 dn[4] = tmp[6];
1705 break;
1706 case 8:
1707 dn[2] = tmp[1];
1708 dn[3] = tmp[2];
1709 dn[4] = tmp[0];
1710 dn[5] = tmp[6];
1711 dn[6] = tmp[7];
1712 break;
1713 }
1714 dn[0] = tmp[new_loc];
1715
1716 return ;
1717 }
1718
1719 /* 3/28/01, find minimal of dn[9] */
1720
FindMin(Int dn[])1721 Int FindMin(Int dn[])
1722 {
1723 Int min, i;
1724 Int dmin;
1725
1726 dmin = dn[1];
1727 min = 1;
1728 for (i = 2; i < 9; i++)
1729 {
1730 if (dn[i] < dmin)
1731 {
1732 dmin = dn[i];
1733 min = i;
1734 }
1735 }
1736
1737 return min;
1738 }
1739
1740
1741
1742