⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fame_motion_pmvfast.c

📁 一个很好用的MPEG1/4的开源编码器
💻 C
📖 第 1 页 / 共 3 页
字号:
    /* Updates the motion vector and the location in the window ("current") */    if((best_dx | best_dy) != 0)    {      mv->dx += best_dx;      mv->dy += best_dy;      if(--count)	current_table = &(table[last_motion]);      else	return;    } else      return;  }}static fame_motion_coding_t pmvfast_estimation(fame_motion_t *motion,					       int mb_x, int mb_y,					       fame_motion_vector_t *vectors,					       unsigned char quant){  int k;  int pitch;  int x, y, width, height;  int offset[4];  int edged_offset[4];  compute_error_t eval_error;  fame_motion_vector_t pmv;  fame_motion_vector_t *pvector;  fame_motion_vector_t *plast;  fame_motion_vector_t *pvector_left, *pvector_topleft;  fame_motion_vector_t *pvector_top, *pvector_topright;  unsigned int weight_left, weight_top, weight_topright;  unsigned char *shape;  unsigned char *current;  fame_yuv_t **ref;  int use_median;  int threshold0;  int threshold1;  int threshold2;  int sad_inter4v, sad_inter, mad_inter, count;  int range;  int pred_same;  int fcode;  int is_left, is_top, is_topright;  int diamond_count;  int sad_last;  int unrestricted;  fame_motion_coding_t motion_coding;  fcode = motion->fcode;#if DEBUG  fprintf(debug_log, "\n***** macroblock : mb_y=%u mb_x=%u *****\n", mb_y, mb_x);#endif  /* ***** Initialization ***** */  eval_error = motion->MAE8x8;  x = mb_x << 4;  y = mb_y << 4;  width  = motion->mb_width << 4;  height = motion->mb_height << 4;  shape = motion->shape;  current = motion->current->y;  pitch = motion->current->p;  ref = motion->ref;  range = motion->search_range;  unrestricted = (motion->flags & FAME_MOTION_UNRESTRICTED_SEARCH)?1:0;  offset[0] = y * pitch + x;  offset[1] = y * pitch + x+8;  offset[2] = (y+8) * pitch + x;  offset[3] = (y+8) * pitch + x+8;  edged_offset[0] = y * (pitch+32) + x;  edged_offset[1] = y * (pitch+32) + x+8;  edged_offset[2] = (y+8) * (pitch+32) + x;  edged_offset[3] = (y+8) * (pitch+32) + x+8;  if(motion->shape) {    vectors[0].count = mad_withmask(current+offset[0], shape+offset[0], pitch, &vectors[0].deviation);    vectors[1].count = mad_withmask(current+offset[1], shape+offset[1], pitch, &vectors[1].deviation);    vectors[2].count = mad_withmask(current+offset[2], shape+offset[2], pitch, &vectors[2].deviation);    vectors[3].count = mad_withmask(current+offset[3], shape+offset[3], pitch, &vectors[3].deviation);  } else {    vectors[0].count = mad_withoutmask(current+offset[0], pitch, &vectors[0].deviation);    vectors[1].count = mad_withoutmask(current+offset[1], pitch, &vectors[1].deviation);    vectors[2].count = mad_withoutmask(current+offset[2], pitch, &vectors[2].deviation);    vectors[3].count = mad_withoutmask(current+offset[3], pitch, &vectors[3].deviation);  }      /* integer sample search */  /* Step1 : vectors around the current macroblock */  pvector = FAME_MOTION_PMVFAST(motion)->vectors[0] + (mb_y*motion->mb_width + mb_x)*4;  plast = FAME_MOTION_PMVFAST(motion)->vectors[0] + (mb_y*motion->mb_width + mb_x)*4;  pvector_left     = pvector - 4;  pvector_topleft  = pvector - 4*motion->mb_width - 4;  pvector_top      = pvector - 4*motion->mb_width;  pvector_topright = pvector - 4*motion->mb_width + 4;  is_left = mb_x > 0;  is_top = mb_y > 0;  is_topright = is_top & (mb_x < motion->mb_width - 1);  pred_same = 0;  diamond_count = 2*range;  if(is_left && is_topright /* && is_top */) {    /* all vectors are valid */    if(pvector_left->dx == pvector_top->dx &&       pvector_left->dy == pvector_top->dy &&       pvector_left->dx == pvector_topright->dx &&       pvector_left->dy == pvector_topright->dy)      /* all vectors are equal : do only one diamond search step */      diamond_count = 1;  }  /* Compute the weighted mean vector :                             */  /*   dx = (f(e1)*dx1 + f(e2)*dx2 + f(e3)*dx3) / (dx1 + dx2 + dx3) */  /*  weight_left = 65536 - (unsigned int)(macroblock_vector_left->error);  weight_left = 65536 - (unsigned int)(macroblock_vector_top->error);  weight_topright = 65536 - (unsigned int)(macroblock_vector_topright->error);  macroblock_vector_barycentre.dx = (weight_left * macroblock_vector_left->dx +				     weight_top * macroblock_vector_top->dx +				     weight_topright * macroblock_vector_topright->dx				     ) / (weight_left + weight_top + weight_topright);  macroblock_vector_barycentre.dy = (weight_left * macroblock_vector_left->dy +				     weight_top * macroblock_vector_top->dy +				     weight_topright * macroblock_vector_topright->dy				     ) / (weight_left + weight_top + weight_topright);  */  /* saturate prediction to borders */  if(unrestricted) {    if((x<<1)+vectors[0].dx<(-16<<1)) vectors[0].dx = (-16-x)<<1;    if((y<<1)+vectors[0].dy<(-16<<1)) vectors[0].dy = (-16-y)<<1;    if((x<<1)+vectors[0].dx>(width<<1)) vectors[0].dx = (width-x)<<1;    if((y<<1)+vectors[0].dy>(height<<1)) vectors[0].dy = (height-y)<<1;  } else {    if((x<<1)+vectors[0].dx<0) vectors[0].dx = (-x)<<1;    if((y<<1)+vectors[0].dy<0) vectors[0].dy = (-y)<<1;    if((x<<1)+vectors[0].dx>((width-16)<<1)) vectors[0].dx = (width-16-x)<<1;    if((y<<1)+vectors[0].dy>((height-16)<<1)) vectors[0].dy = (height-16-y)<<1;  }  /* Step2 : Calculate the thresholds */  threshold1 = INFINITE_ERROR;  if(mb_x>0)    threshold1 = fame_min(threshold1, pvector_left[0].error+pvector_left[1].error+pvector_left[2].error+pvector_left[3].error);  if(mb_y>0)    threshold1 = fame_min(threshold1, pvector_top[0].error+pvector_top[1].error+pvector_top[2].error+pvector_top[3].error);  if(mb_y>0 && mb_x<motion->mb_width-1)    threshold1 = fame_min(threshold1, pvector_topright[0].error+pvector_topright[1].error+pvector_topright[2].error+pvector_topright[3].error);  threshold0 = vectors[0].count + vectors[1].count + vectors[2].count + vectors[3].count;  threshold2 = threshold1 + threshold0;  if(threshold1<LOWER_LIMIT_THRESHOLD1)    threshold1 = LOWER_LIMIT_THRESHOLD1;  if(threshold1>UPPER_LIMIT_THRESHOLD1)    threshold1 = UPPER_LIMIT_THRESHOLD1;  if(threshold2>UPPER_LIMIT_THRESHOLD2)    threshold2 = UPPER_LIMIT_THRESHOLD2;#if DEBUG  fprintf(debug_log, "threshold0 = %u\n", threshold0);  fprintf(debug_log, "threshold1 = %u\n", threshold1);  fprintf(debug_log, "threshold2 = %u\n", threshold2);#endif  /* Step3 : Process a set of vectors whose matching probability is very high*/  /*         i.e. median, zero, prev, left, top, topright vector             */  /* Check the median vector */  pmv.dx = vectors[3].dx = vectors[2].dx = vectors[1].dx = vectors[0].dx;  pmv.dy = vectors[3].dy = vectors[2].dy = vectors[1].dy = vectors[0].dy;  get_error(ref, current, shape, vectors, offset, edged_offset, pitch, eval_error, 4);   sad_inter = vectors[0].error+vectors[1].error+              vectors[2].error+vectors[3].error;  sad_last = plast[0].error+plast[1].error+             plast[2].error+plast[3].error+             mv_overhead(&pmv, plast[0].dx, plast[0].dy, fcode, quant);  if((sad_inter<threshold0) ||     (vectors->dx == plast->dx &&      vectors->dy == plast->dy &&      sad_inter < sad_last))  {    /* keep predicted vector */#if STAT    motionstat.num_median++;#endif    memcpy(pvector, vectors, 4*sizeof(fame_motion_vector_t));    if((vectors[0].dx ^ vectors[1].dx) +       (vectors[0].dx ^ vectors[2].dx) +       (vectors[0].dx ^ vectors[3].dx) +       (vectors[0].dy ^ vectors[1].dy) +       (vectors[0].dy ^ vectors[2].dy) +       (vectors[0].dy ^ vectors[3].dy))      return(motion_inter4v);    else      return(motion_inter);  }#if DEBUG  fprintf(debug_log, "Median vector : dx=%d dy=%d error=%d\n",	  vectors[0].dx, vectors[0].dy, vectors[0].error+vectors[1].error+vectors[2].error+vectors[3].error);#endif  /* TODO: check performance of current 4MV prediction compared to 1MV */  /* Check the zero vector */  use_median = check_zero_vector(ref, current, shape,				 x, y, width, height,				 vectors,				 offset, edged_offset, pitch, eval_error,				 &pmv, fcode, quant);  /* Check the previous vector */  /* fcode may have changed, make sure the vector is within the search range */  if(plast->dx >= -(range<<1) && plast->dx <= (range<<1)-1 &&     plast->dy >= -(range<<1) && plast->dy <= (range<<1)-1)    use_median = check_vector(ref, current, shape,			      x, y, width, height,			      plast, vectors,			      offset, edged_offset, pitch, eval_error,			      &pmv, fcode, quant, unrestricted);  /* Check the left vector */  if(!pred_same && is_left) {    use_median &= check_vector(ref, current, shape,			       x, y, width, height,			       pvector_left, vectors,			       offset, edged_offset, pitch, eval_error,			       &pmv, fcode, quant, unrestricted);  }  /* Check the top vector */  if(!pred_same && is_top) {    use_median &= check_vector(ref, current, shape,			       x, y, width, height,			       pvector_top, vectors,			       offset, edged_offset, pitch, eval_error,			       &pmv, fcode, quant, unrestricted);  }  /* Check the topright vector */  if(!pred_same && is_topright) {    use_median &= check_vector(ref, current, shape,			       x, y, width, height,			       pvector_topright, vectors,			       offset, edged_offset, pitch, eval_error,			       &pmv, fcode, quant, unrestricted);  }#if DEBUG  fprintf(debug_log, "Best vector of the set : dx=%d  dy=%d error=%u\n",	  vectors[0].dx, vectors[0].dy, vectors[0].error+vectors[1].error+vectors[2].error+vectors[3].error);#endif  /* Step4 : check early exit */  sad_inter = vectors[0].error+vectors[1].error+              vectors[2].error+vectors[3].error+              mv_overhead(&pmv, vectors[0].dx, vectors[0].dy, fcode, quant);  if(sad_inter < threshold1 ||     (vectors->dx == plast->dx &&      vectors->dy == plast->dy &&      sad_inter < sad_last))   {#if DEBUG    fprintf(debug_log, "Early exit\n");#endif    memcpy(pvector, vectors, 4*sizeof(fame_motion_vector_t));#if STAT    motionstat.num_early++;#endif    if((vectors[0].dx ^ vectors[1].dx) +       (vectors[0].dx ^ vectors[2].dx) +       (vectors[0].dx ^ vectors[3].dx) +       (vectors[0].dy ^ vectors[1].dy) +       (vectors[0].dy ^ vectors[2].dy) +       (vectors[0].dy ^ vectors[3].dy))      return(motion_inter4v);    else      return(motion_inter);  }  /* integer sample search *//* Step5 : The previous attempts were not successfull     -> apply the diamond search algorithm with the initial vector equal to the best previous vector found */  if(pred_same || pmv.dx != 0 || pmv.dy != 0 ||     threshold2<THRESHOLD_SMALLDIAMOND)  {#if DEBUG    fprintf(debug_log, "Choice for 16x16 mb search : small diamond\n");#endif    /* pelwise small diamond */    find_macroblockvector(ref, current, shape, offset, edged_offset,			  x, y, width, height, pitch,			  td_block_smalldiamond,			  range, 1, diamond_count, eval_error, vectors,			  &pmv, fcode, quant, unrestricted);#if STAT    motionstat.num_smalldiamond++;#endif  }  else  {#if DEBUG    fprintf(debug_log, "Choice for 16x16 mb search : large diamond\n");#endif    /* pelwise large diamond */    find_macroblockvector(ref, current, shape, offset, edged_offset, 			  x, y, width, height, pitch,			  td_block_largediamond,			  range, 1, diamond_count, eval_error, vectors,			  &pmv, fcode, quant, unrestricted);#if STAT    motionstat.num_largediamond++;#endif  }  /* ***** Make the intra/inter mode decision ***** */  sad_inter = vectors[0].error + vectors[1].error + vectors[2].error + vectors[3].error+mv_overhead(&pmv, vectors[0].dx, vectors[0].dy, fcode, quant);  mad_inter = vectors[0].deviation + vectors[1].deviation +               vectors[2].deviation + vectors[3].deviation;  count = vectors[0].count + vectors[1].count + vectors[2].count + vectors[3].count;#if DEBUG  fprintf(debug_log, "Best 16x16 vector found (integer pixel) : dx=%d  dy=%d  error=%u\n",	  vectors->dx, vectors->dy, sad_inter);#endif  /* store vectors for future prediction */  memcpy(pvector, vectors, 4*sizeof(fame_motion_vector_t));  /* intra/inter mode decision */  /*        -> 1  - COMPUTE THE VARIANCE OF THE MACROBLOCK                */  /*           (estimated by absolute difference and not square diff.)    */  /*           The number of bits (at a given quality) needed by the DCT  */  /*           depends on the variance (in a first approximation)         */  /*        -> 2 - COMPARE WITH THE COVARIANCE GIVEN BY THE MOTION VECTOR */  /*           The number of bits to code residual macroblock             */  /*           depends on the covariance (in a first approximation)       */  /*        -> If (1) < (2) - 2*N : Choose INTRA                          */  /*           Substract 2*N to favour INTER mode when there is no        */  /*           significant difference                                     */  /* TODO: maybe move half pel before decision */  if(mad_inter + count + count < sad_inter) {#if DEBUG    fprintf(debug_log, "Coding = intra\n");#endif    memset(pvector, 0, 4*sizeof(fame_motion_vector_t));    return(motion_intra);  }  /* subvector (8x8) search */  if(motion->flags & FAME_MOTION_BLOCK_SEARCH) {    for(k = 0; k < 4; k++) { /* TODO: k depends on shape */      /* integer sample search */      find_blockvector(ref, current, shape, offset[k], edged_offset[k],		       x, y, width, height, pitch, 		       td_block_bbgds,		       range, 1, diamond_count, eval_error, &vectors[k],		       &pmv, fcode, quant, unrestricted);      /* half sample search */      find_blockvector(ref, current, shape, offset[k], edged_offset[k],		       x, y, width, height, pitch,		       td_block_bbgds,		       range, 0, 1, eval_error, &vectors[k],		       &pmv, fcode, quant, unrestricted);    }#if DEBUG    for(i=0; i<4; i++)      fprintf(debug_log, "Best 8x8 vector found (integer pixel) for the block %d: dx=%d  dy=%d  error=%u\n",	      i, vectors[i].dx, vectors[i].dy, vectors[i].error);#endif  }  /* half sample search */  find_macroblockvector(ref, current, shape, offset, edged_offset,			x, y, width, height, pitch, 			td_block_bbgds,			range, 0, 1, eval_error, pvector,			&pmv, fcode, quant, unrestricted);#if DEBUG  fprintf(debug_log, "After half pixel search on the macroblock : dx=%d dy=%d error=%u\n",	  pvector->dx, pvector->dy, pvector[0].error+pvector[1].error+pvector[2].error+pvector[3].error);#endif  /* inter4v / inter decision */  sad_inter = pvector[0].error + pvector[1].error + pvector[2].error + pvector[3].error+mv_overhead(&pmv, pvector[0].dx, pvector[0].dy, fcode, quant);  mad_inter = vectors[0].deviation + vectors[1].deviation +               vectors[2].deviation + vectors[3].deviation;  count = vectors[0].count + vectors[1].count + vectors[2].count + vectors[3].count;  sad_inter4v =     vectors[0].error +    vectors[1].error +    vectors[2].error +    vectors[3].error +    mv_overhead(&pmv, vectors[0].dx, vectors[0].dy, fcode, quant) +    mv_overhead(&pmv, vectors[1].dx, vectors[1].dy, fcode, quant) +    mv_overhead(&pmv, vectors[2].dx, vectors[2].dy, fcode, quant) +    mv_overhead(&pmv, vectors[3].dx, vectors[3].dy, fcode, quant);  #if DEBUG  fprintf(debug_log, "Best 16x16 vector found : dx=%d  dy=%d  error=%u\n",	  pvector->dx, pvector->dy, pvector[0].error+pvector[1].error+pvector[2].error+pvector[3].error);  for(i=0; i<4; i++)  {    fprintf(debug_log, "Best 8x8 vector found for the block %d : dx=%d  dy=%d  error=%u\n",	    i, vectors[i].dx, vectors[i].dy, vectors[i].error);  }#endif  /* inter4v/inter mode decision */  if((motion->flags & FAME_MOTION_BLOCK_SEARCH) &&     (sad_inter4v + ((count>>1)+1) < sad_inter)) {#if DEBUG    fprintf(debug_log, "4 vectors\n");#endif    /* inter4v prediction */    sad_inter = sad_inter4v;    motion_coding = motion_inter4v;  } else   {    memcpy(vectors, pvector, 4*sizeof(fame_motion_vector_t));    motion_coding = motion_inter;  }#if DEBUG  fprintf(debug_log, "Coding = inter\n");#endif  return(motion_coding);}/* End of motion_pmvfast.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -