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

📄 fame_motion_pmvfast.c

📁 一个很好用的MPEG1/4的开源编码器
💻 C
📖 第 1 页 / 共 3 页
字号:
			 int mb_height,			 unsigned int flags){  FAME_MOTION_PMVFAST(motion)->FAME_OVERLOADED(init)(motion,						     mb_width,						     mb_height,						     flags);#if DEBUG  debug_log = fopen("pmvfast_debug.log", "wb");#endif#if STAT  stat_log = fopen("pmvfast_stat.log", "wb");  motionstat.num_picture = 0;#endif  /* double buffered motion vectors */  FAME_MOTION_PMVFAST(motion)->vectors[0] = (fame_motion_vector_t *)    fame_malloc(mb_width*2*mb_height*2*sizeof(fame_motion_vector_t));  FAME_MOTION_PMVFAST(motion)->vectors[1] = (fame_motion_vector_t *)    fame_malloc(mb_width*2*mb_height*2*sizeof(fame_motion_vector_t));}static void pmvfast_close(fame_motion_t *motion){  FAME_MOTION_PMVFAST(motion)->FAME_OVERLOADED(close)(motion);#if DEBUG  fclose(debug_log);#endif  fame_free(FAME_MOTION_PMVFAST(motion)->vectors[0]);  fame_free(FAME_MOTION_PMVFAST(motion)->vectors[1]);}static void pmvfast_enter(fame_motion_t *motion,			  fame_yuv_t **ref,			  fame_yuv_t *current,			  unsigned char *shape,			  int search_range){  FAME_MOTION_PMVFAST(motion)->FAME_OVERLOADED(enter)(motion,						      ref,						      current,						      shape,						      search_range);#if DEBUG  fprintf(debug_log, "********** NEW PICTURE **********\n");#endif#if STAT  motionstat.num_eval = 0;  motionstat.num_intra = 0;  motionstat.num_median = 0;  motionstat.num_early = 0;  motionstat.num_16x16 = 0;  motionstat.num_8x8 = 0;  motionstat.num_largediamond = 0;  motionstat.num_smalldiamond = 0;#endif}static void pmvfast_leave(fame_motion_t *motion){  fame_motion_vector_t *tmp;  FAME_MOTION_PMVFAST(motion)->FAME_OVERLOADED(leave)(motion);#if STAT  fprintf(stat_log, "\n********** PICTURE %d **********\n", motionstat.num_picture);  fprintf(stat_log, "Number of SAD8x8 : %d\n", motionstat.num_eval);  fprintf(stat_log, "Use of median vector: %d times\n", motionstat.num_median);  fprintf(stat_log, "Early exit : %d times\n", motionstat.num_early);  fprintf(stat_log, "Large diamond : %d times\n", motionstat.num_largediamond);  fprintf(stat_log, "Small diamond : %d times\n", motionstat.num_smalldiamond);  motionstat.num_picture++;#endif  /* swap motion buffers */  tmp = FAME_MOTION_PMVFAST(motion)->vectors[1];  FAME_MOTION_PMVFAST(motion)->vectors[1] = FAME_MOTION_PMVFAST(motion)->vectors[0];  FAME_MOTION_PMVFAST(motion)->vectors[0] = tmp;}static inline void get_error(fame_yuv_t **ref,			     unsigned char *current,			     unsigned char *shape,			     fame_motion_vector_t *vectors,			     int offset[4],			     int edged_offset[4],			     int pitch,			     compute_error_t eval_error,			     int number){  int i;  int residual, motion;  for(i = 0; i < number; i++) {    residual = (vectors[i].dx & 1) + ((vectors[i].dy & 1) << 1);    motion = (vectors[i].dx >> 1) + (vectors[i].dy >> 1) * (pitch+32);    vectors[i].error = eval_error(ref[residual]->y+motion+edged_offset[i],				  current+offset[i],				  shape+offset[i],				  pitch);  }#if STAT  motionstat.num_eval+=number;#endif}static inline int check_vector(fame_yuv_t **ref,			       unsigned char *current,			       unsigned char *shape,			       int x,			       int y,			       int width,			       int height,			       fame_motion_vector_t *pvector,			       fame_motion_vector_t *vectors,			       int offset[4],			       int edged_offset[4],			       int pitch,			       compute_error_t eval_error,			       fame_motion_vector_t *pmv,			       int fcode,			       int quant,			       int unrestricted){  int edge;  const int dx = pvector->dx;  const int dy = pvector->dy;  edge = unrestricted << 4; /* unrestricted ? 16 : 0 */  if(((x+edge)<<1)+dx >= 0 &&     ((y+edge)<<1)+dy >= 0 &&     ((x-edge)<<1)+dx < ((width-16)<<1) &&     ((y-edge)<<1)+dy < ((height-16)<<1))  {    int i;    int residual, motion;    int errors[4];    unsigned char *r;    residual = (dx & 1) + ((dy & 1) << 1);    motion = (dx >> 1) + (dy >> 1) * (pitch + 32);    r = ref[residual]->y;    for(i = 0; i < 4; i++) {      errors[i] = eval_error(r+motion+edged_offset[i],			     current+offset[i],			     shape+offset[i],			     pitch);#if STAT      motionstat.num_eval++;#endif    }    if(errors[0]+errors[1]+errors[2]+errors[3]+       mv_overhead(pmv, pvector[0].dx, pvector[0].dy, fcode, quant) <       vectors[0].error+vectors[1].error+vectors[2].error+vectors[3].error+       mv_overhead(pmv, vectors[0].dx, vectors[0].dy,fcode, quant))    {      /* use checked vector */      memcpy(vectors, pvector, 4*sizeof(fame_motion_vector_t));      vectors[0].error = errors[0];      vectors[1].error = errors[1];      vectors[2].error = errors[2];      vectors[3].error = errors[3];      return(0);    }  }  return(1);}static inline int check_zero_vector(fame_yuv_t **ref,				    unsigned char *current,				    unsigned char *shape,				    int x,				    int y,				    int width,				    int height,				    fame_motion_vector_t *vectors,				    int offset[4],				    int edged_offset[4],				    int pitch,				    compute_error_t eval_error,				    fame_motion_vector_t *pmv,				    int fcode,				    int quant){  int i;  int errors[4];  int total_error;    for(i = 0; i < 4; i++) {    errors[i] = eval_error(ref[0]->y+edged_offset[i],			   current+offset[i],			   shape+offset[i],			   pitch);#if STAT      motionstat.num_eval++;#endif  }  total_error = errors[0]+errors[1]+errors[2]+errors[3]+    mv_overhead(pmv, 0, 0, fcode, quant);  if(total_error < quant * 96) {    /* favor the 0 vector & small error to favor skip mode */    total_error -= 128;    errors[0] -= 32;    errors[1] -= 32;    errors[2] -= 32;    errors[3] -= 32;  }  if(total_error <     vectors[0].error+vectors[1].error+vectors[2].error+vectors[3].error+     mv_overhead(pmv, vectors[0].dx, vectors[0].dy, fcode, quant))  {    /* use checked vector */    vectors[0].dx = vectors[0].dy = 0;    vectors[1].dx = vectors[1].dy = 0;    vectors[2].dx = vectors[2].dy = 0;    vectors[3].dx = vectors[3].dy = 0;    vectors[0].error = errors[0];    vectors[1].error = errors[1];    vectors[2].error = errors[2];    vectors[3].error = errors[3];    return(0);  }    return(1);}static void find_macroblockvector(fame_yuv_t **ref,				  unsigned char *current,				  unsigned char *shape,				  int offset[4],				  int edged_offset[4],				  int x,				  int y,				  int width,				  int height,				  int pitch,				  tab_direction_t *table,				  int search_range,				  int step,				  int count,				  compute_error_t eval_error,				  fame_motion_vector_t *mv,				  fame_motion_vector_t *pmv,				  int fcode,				  int quant,				  int unrestricted){  int i;  int last_motion;  tab_direction_t *current_table;  int test_dx, test_dy, test_total;  int best_dx, best_dy, best_total;  int test_error0, test_error1, test_error2, test_error3;  int subpel;  int min_dx, max_dx, min_dy, max_dy;  int motion, residual;  unsigned char *location;  subpel = 1; /* default (half-pel) */  last_motion = 1;  current_table = &(table[last_motion]);  best_total = mv[0].error + mv[1].error + mv[2].error + mv[3].error +    mv_overhead(pmv, mv->dx, mv->dy, fcode, quant);  if(unrestricted) {    min_dx = -fame_min((x+16)<<subpel, (search_range<<subpel));    min_dy = -fame_min((y+16)<<subpel, (search_range<<subpel));    max_dx = fame_min((width-x)<<subpel, (search_range<<subpel)-1);    max_dy = fame_min((height-y)<<subpel, (search_range<<subpel)-1);  } else {    min_dx = -fame_min(x<<subpel, (search_range<<subpel));    min_dy = -fame_min(y<<subpel, (search_range<<subpel));    max_dx = fame_min((width-16-x)<<subpel, (search_range<<subpel)-1);    max_dy = fame_min((height-16-y)<<subpel, (search_range<<subpel)-1);  }  /* Start the macroblock motion vector search with the small diamond patern */  while(1)  {    last_motion = NULL_MOTION;    best_dx = 0;    best_dy = 0;    /* Search the best motion vector from the current point */    for(i = 0; i < current_table->nbre; i++)    {      test_dx = mv->dx+(current_table->directions[i].dx << step);      test_dy = mv->dy+(current_table->directions[i].dy << step);      if (test_dx >= min_dx && 	  test_dy >= min_dy && 	  test_dx <= max_dx &&	  test_dy <= max_dy) {	/* Find the SAD for the blocks (8x8) */	motion = (test_dx >> subpel) + (test_dy >> subpel) * (pitch + 32);	residual = (test_dx & ((1<<subpel)-1)) | ((test_dy & ((1<<subpel)-1)) << subpel);	location = ref[residual]->y+motion;	test_error0 = eval_error(location+edged_offset[0], current+offset[0], shape+offset[0], pitch);	test_error1 = eval_error(location+edged_offset[1], current+offset[1], shape+offset[1], pitch);	test_error2 = eval_error(location+edged_offset[2], current+offset[2], shape+offset[2], pitch);	test_error3 = eval_error(location+edged_offset[3], current+offset[3], shape+offset[3], pitch);	test_total = test_error0 + test_error1 + test_error2 + test_error3 +	  mv_overhead(pmv, test_dx, test_dy, fcode, quant);#if STAT	motionstat.num_eval+=4;#endif      } else {	test_total = INFINITE_ERROR;	test_error0 = test_error1 = test_error2 = test_error3 = INFINITE_ERROR;      }#if DEBUG      fprintf(debug_log, "errorBBGDS=%u\n",test_total);#endif      /* Check if the current SAD (for the macroblock) if lesser than the SAD of the previous "best" macroblock */      if(test_total < best_total)      {	last_motion = current_table->directions[i].index_direction;	best_dx = test_dx - mv->dx;	best_dy = test_dy - mv->dy;	best_total = test_total;	mv[0].error = test_error0;	mv[1].error = test_error1;	mv[2].error = test_error2;	mv[3].error = test_error3;      }    }    /* 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;      mv[3].dx = mv[2].dx = mv[1].dx = mv->dx;      mv[3].dy = mv[2].dy = mv[1].dy = mv->dy;      if(--count)	current_table = &(table[last_motion]);      else	return;    } else      return;  }}static void find_blockvector(fame_yuv_t **ref,			     unsigned char *current,			     unsigned char *shape,			     int offset,			     int edged_offset,			     int x,			     int y,			     int width,			     int height,			     int pitch,			     tab_direction_t *table,			     int search_range,			     int step,			     int count,			     compute_error_t eval_error,			     fame_motion_vector_t *mv,			     fame_motion_vector_t *pmv,			     int fcode,			     int quant,			     int unrestricted){  int i;  int last_motion;  tab_direction_t *current_table;  int test_dx, test_dy, test_error;  int best_dx, best_dy, best_error;  int min_dx, max_dx, min_dy, max_dy;  int subpel;  int motion, residual;  subpel = 1; /* default (half-pel) */  last_motion = 1;  current_table = &(table[last_motion]);  best_error = mv->error + mv_overhead(pmv, mv->dx, mv->dy, fcode, quant);  if(unrestricted) {    min_dx = -fame_min((x+16)<<subpel, (search_range<<subpel));    min_dy = -fame_min((y+16)<<subpel, (search_range<<subpel));    max_dx = fame_min((width-x)<<subpel, (search_range<<subpel)-1);    max_dy = fame_min((height-y)<<subpel, (search_range<<subpel)-1);  } else {    min_dx = -fame_min(x<<subpel, (search_range<<subpel));    min_dy = -fame_min(y<<subpel, (search_range<<subpel));    max_dx = fame_min((width-16-x)<<subpel, (search_range<<subpel)-1);    max_dy = fame_min((height-16-y)<<subpel, (search_range<<subpel)-1);  }  /* Start the macroblock motion vector search with the small diamond patern */  while(1)  {    last_motion = NULL_MOTION;    best_dx = 0;    best_dy = 0;    /* Search the best motion vector from the current point */    for(i = 0; i < current_table->nbre; i++)    {      test_dx = mv->dx+(current_table->directions[i].dx << step);      test_dy = mv->dy+(current_table->directions[i].dy << step);      if (test_dx >= min_dx && 	  test_dy >= min_dy && 	  test_dx <= max_dx &&	  test_dy <= max_dy) {	/* Find the SAD for the block (8x8) */	motion = (test_dx >> subpel) + (test_dy >> subpel) * (pitch + 32);	residual = (test_dx & ((1<<subpel)-1)) | ((test_dy & ((1<<subpel)-1)) << subpel);	test_error = eval_error(ref[residual]->y+motion+edged_offset, current+offset, shape+offset, pitch) + 	  mv_overhead(pmv, test_dx, test_dy, fcode, quant);#if STAT	motionstat.num_eval+=4;#endif      } else	test_error = INFINITE_ERROR;#if DEBUG      fprintf(debug_log, "error block_vector=%u\n",test_error);#endif      /* Check if the current SAD (for the macroblock) if lesser than the SAD of the previous "best" macroblock */      if(test_error < best_error)      {	last_motion = current_table->directions[i].index_direction;	best_dx = test_dx - mv->dx;	best_dy = test_dy - mv->dy;	best_error = test_error;	mv->error = test_error;      }    }

⌨️ 快捷键说明

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