📄 fame_motion_pmvfast.c
字号:
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 + -