On Tue, Aug 23, 2016 at 01:17:47PM +0000, Davinder Singh wrote: > On Tue, Aug 23, 2016 at 5:38 AM Andy Furniss <adf.li...@gmail.com> wrote: > > > [...] > > > > Nice I can see the edges are better than the last version. > > > > The doc/filters.texi hunk doesn't apply to git master. > > > > I was going to post some comparisons with mcfps tonight, but I'll need > > to redo them to see what's changed. > > > fixed docs conflict. > > thanks for testing!
[...] > +uint64_t ff_me_search_tss(AVMotionEstContext *me_ctx, int x_mb, int y_mb, > int *mv) > +{ > + int x, y; > + int x_min = FFMAX(me_ctx->x_min, x_mb - me_ctx->search_param); > + int y_min = FFMAX(me_ctx->y_min, y_mb - me_ctx->search_param); > + int x_max = FFMIN(x_mb + me_ctx->search_param, me_ctx->x_max); > + int y_max = FFMIN(y_mb + me_ctx->search_param, me_ctx->y_max); > + uint64_t cost, cost_min; > + int step = ROUNDED_DIV(me_ctx->search_param, 2); > + int i; > + > + int square[8][2] = {{0,-1}, {0,1}, {-1,0}, {1,0}, {-1,-1}, {-1,1}, > {1,-1}, {1,1}}; const > + > + mv[0] = x_mb; > + mv[1] = y_mb; > + > + if (!(cost_min = me_ctx->get_cost(me_ctx, x_mb, y_mb, x_mb, y_mb))) > + return cost_min; > + > + do { > + x = mv[0]; > + y = mv[1]; > + > + for (i = 0; i < 8; i++) > + COST_P_MV(x + square[i][0] * step, y + square[i][1] * step); > + > + step = step / 2; >>1 might be faster > + > + } while (step > 0); > + > + return cost_min; > +} > + > +uint64_t ff_me_search_tdls(AVMotionEstContext *me_ctx, int x_mb, int y_mb, > int *mv) > +{ > + int x, y; > + int x_min = FFMAX(me_ctx->x_min, x_mb - me_ctx->search_param); > + int y_min = FFMAX(me_ctx->y_min, y_mb - me_ctx->search_param); > + int x_max = FFMIN(x_mb + me_ctx->search_param, me_ctx->x_max); > + int y_max = FFMIN(y_mb + me_ctx->search_param, me_ctx->y_max); > + uint64_t cost, cost_min; > + int step = ROUNDED_DIV(me_ctx->search_param, 2); > + int i; > + > + int dia2[4][2] = {{-1, 0}, { 0,-1}, > + { 1, 0}, { 0, 1}}; const > + > + mv[0] = x_mb; > + mv[1] = y_mb; > + > + if (!(cost_min = me_ctx->get_cost(me_ctx, x_mb, y_mb, x_mb, y_mb))) > + return cost_min; > + > + do { > + x = mv[0]; > + y = mv[1]; > + > + for (i = 0; i < 4; i++) > + COST_P_MV(x + dia2[i][0] * step, y + dia2[i][1] * step); > + > + if (x == mv[0] && y == mv[1]) > + step = step / 2; > + > + } while (step > 0); > + > + return cost_min; > +} > + > +uint64_t ff_me_search_ntss(AVMotionEstContext *me_ctx, int x_mb, int y_mb, > int *mv) > +{ > + int x, y; > + int x_min = FFMAX(me_ctx->x_min, x_mb - me_ctx->search_param); > + int y_min = FFMAX(me_ctx->y_min, y_mb - me_ctx->search_param); > + int x_max = FFMIN(x_mb + me_ctx->search_param, me_ctx->x_max); > + int y_max = FFMIN(y_mb + me_ctx->search_param, me_ctx->y_max); > + uint64_t cost, cost_min; > + int step = ROUNDED_DIV(me_ctx->search_param, 2); > + int first_step = 1; > + int i; > + > + int square[8][2] = {{0,-1}, {0,1}, {-1,0}, {1,0}, {-1,-1}, {-1,1}, > {1,-1}, {1,1}}; const [...] > +uint64_t ff_me_search_ds(AVMotionEstContext *me_ctx, int x_mb, int y_mb, int > *mv) > +{ > + int x, y; > + int x_min = FFMAX(me_ctx->x_min, x_mb - me_ctx->search_param); > + int y_min = FFMAX(me_ctx->y_min, y_mb - me_ctx->search_param); > + int x_max = FFMIN(x_mb + me_ctx->search_param, me_ctx->x_max); > + int y_max = FFMIN(y_mb + me_ctx->search_param, me_ctx->y_max); > + uint64_t cost, cost_min; > + int i; > + int dir_x, dir_y; > + > + int dia[8][2] = {{-2, 0}, {-1,-1}, { 0,-2}, { 1,-1}, > + { 2, 0}, { 1, 1}, { 0, 2}, {-1, 1}}; > + int dia2[4][2] = {{-1, 0}, { 0,-1}, > + { 1, 0}, { 0, 1}}; > + > + if (!(cost_min = me_ctx->get_cost(me_ctx, x_mb, y_mb, x_mb, y_mb))) > + return cost_min; > + > + x = x_mb; y = y_mb; > + dir_x = dir_y = 0; > + > + do { > + x = mv[0]; > + y = mv[1]; > + > + #if 1 > + for (i = 0; i < 8; i++) > + COST_P_MV(x + dia[i][0], y + dia[i][1]); > + #else > + /* this version skips previously examined 3 or 5 locations based on > prev origin */ > + if (dir_x <= 0) > + COST_P_MV(x - 2, y); > + if (dir_x <= 0 && dir_y <= 0) > + COST_P_MV(x - 1, y - 1); > + if (dir_y <= 0) > + COST_P_MV(x, y - 2); > + if (dir_x >= 0 && dir_y <= 0) > + COST_P_MV(x + 1, y - 1); > + if (dir_x >= 0) > + COST_P_MV(x + 2, y); > + if (dir_x >= 0 && dir_y >= 0) > + COST_P_MV(x + 1, y + 1); > + if (dir_y >= 0) > + COST_P_MV(x, y + 2); > + if (dir_x <= 0 && dir_y >= 0) > + COST_P_MV(x - 1, y + 1); > + > + dir_x = mv[0] - x; > + dir_y = mv[1] - y; > + #endif > + > + } while (x != mv[0] || y != mv[1]); > + > + for (i = 0; i < 4; i++) > + COST_P_MV(x + dia2[i][0], y + dia2[i][1]); > + > + return cost_min; > +} > + > +uint64_t ff_me_search_hexbs(AVMotionEstContext *me_ctx, int x_mb, int y_mb, > int *mv) > +{ > + int x, y; > + int x_min = FFMAX(me_ctx->x_min, x_mb - me_ctx->search_param); > + int y_min = FFMAX(me_ctx->y_min, y_mb - me_ctx->search_param); > + int x_max = FFMIN(x_mb + me_ctx->search_param, me_ctx->x_max); > + int y_max = FFMIN(y_mb + me_ctx->search_param, me_ctx->y_max); > + uint64_t cost, cost_min; > + int i; > + > + int hex2[6][2] = {{-2, 0}, {-1,-2}, {-1, 2}, > + { 1,-2}, { 1, 2}, { 2, 0}}; > + > + int dia2[4][2] = {{-1, 0}, { 0,-1}, > + { 1, 0}, { 0, 1}}; > + > + if (!(cost_min = me_ctx->get_cost(me_ctx, x_mb, y_mb, x_mb, y_mb))) > + return cost_min; > + > + do { > + x = mv[0]; > + y = mv[1]; > + > + for (i = 0; i < 6; i++) > + COST_P_MV(x + hex2[i][0], y + hex2[i][1]); > + > + } while (x != mv[0] || y != mv[1]); > + > + for (i = 0; i < 4; i++) > + COST_P_MV(x + dia2[i][0], y + dia2[i][1]); > + > + return cost_min; > +} why do these not try predictors like epzs / umh ? i guess some paper doesnt say exlpicitly it should be done but really it should be done for all predictive zonal searches IMO [...] > +#define OFFSET(x) offsetof(MEContext, x) > +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM > +#define CONST(name, help, val, unit) { name, help, 0, AV_OPT_TYPE_CONST, > {.i64=val}, 0, 0, FLAGS, unit } > + > +static const AVOption mestimate_options[] = { > + { "method", "motion estimation method", OFFSET(method), AV_OPT_TYPE_INT, > {.i64 = AV_ME_METHOD_ESA}, AV_ME_METHOD_ESA, AV_ME_METHOD_UMH, FLAGS, > "method" }, > + CONST("esa", "exhaustive search", > AV_ME_METHOD_ESA, "method"), > + CONST("tss", "three step search", > AV_ME_METHOD_TSS, "method"), > + CONST("tdls", "two dimensional logarithmic search", > AV_ME_METHOD_TDLS, "method"), > + CONST("ntss", "new three step search", > AV_ME_METHOD_NTSS, "method"), > + CONST("fss", "four step search", > AV_ME_METHOD_FSS, "method"), > + CONST("ds", "diamond search", > AV_ME_METHOD_DS, "method"), > + CONST("hexbs", "hexagon-based search", > AV_ME_METHOD_HEXBS, "method"), > + CONST("epzs", "enhanced predictive zonal search", > AV_ME_METHOD_EPZS, "method"), > + CONST("umh", "uneven multi-hexagon search", > AV_ME_METHOD_UMH, "method"), AVOption is not compatible with general enums, as C does not gurantee them to be stored in an int, it just happens to work on most platforms [...] > +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) > +{ > + AVFilterContext *ctx = inlink->dst; > + MEContext *s = ctx->priv; > + AVMotionEstContext *me_ctx = &s->me_ctx; > + AVFrameSideData *sd; > + AVFrame *out; > + int mb_x, mb_y, dir; > + int32_t mv_count = 0; > + int ret; > + > + if (frame->pts == AV_NOPTS_VALUE) { > + ret = ff_filter_frame(ctx->outputs[0], frame); > + return ret; > + } > + > + av_frame_free(&s->prev); > + s->prev = s->cur; > + s->cur = s->next; > + s->next = frame; > + > + s->mv_table[2] = memcpy(s->mv_table[2], s->mv_table[1], > sizeof(*s->mv_table[1]) * s->b_count); > + s->mv_table[1] = memcpy(s->mv_table[1], s->mv_table[0], > sizeof(*s->mv_table[0]) * s->b_count); > + > + if (!s->cur) { > + s->cur = av_frame_clone(frame); > + if (!s->cur) > + return AVERROR(ENOMEM); > + } > + > + if (!s->prev) > + return 0; > + > + out = av_frame_clone(s->cur); > + if (!out) > + return AVERROR(ENOMEM); > + > + sd = av_frame_new_side_data(out, AV_FRAME_DATA_MOTION_VECTORS, 2 * > s->b_count * sizeof(AVMotionVector)); > + if (!sd) > + return AVERROR(ENOMEM); leaks "out" [...] > +static uint64_t get_sbad(AVMotionEstContext *me_ctx, int x, int y, int x_mv, > int y_mv) > +{ > + uint8_t *data_cur = me_ctx->data_cur; > + uint8_t *data_next = me_ctx->data_ref; > + int linesize = me_ctx->linesize; > + int mv_x1 = x_mv - x; > + int mv_y1 = y_mv - y; > + int mv_x, mv_y, i, j; > + uint64_t sbad = 0; > + > + x = av_clip(x, me_ctx->x_min, me_ctx->x_max); > + y = av_clip(y, me_ctx->y_min, me_ctx->y_max); > + mv_x = av_clip(x_mv - x, -FFMIN(x - me_ctx->x_min, me_ctx->x_max - x), > FFMIN(x - me_ctx->x_min, me_ctx->x_max - x)); > + mv_y = av_clip(y_mv - y, -FFMIN(y - me_ctx->y_min, me_ctx->y_max - y), > FFMIN(y - me_ctx->y_min, me_ctx->y_max - y)); > + > + data_cur += (y + mv_y) * linesize; > + data_next += (y - mv_y) * linesize; > + > + for (j = 0; j < me_ctx->mb_size; j++) > + for (i = 0; i < me_ctx->mb_size; i++) > + sbad += FFABS(data_cur[x + mv_x + i + j * linesize] - > data_next[x - mv_x + i + j * linesize]); > + > + return sbad + (FFABS(mv_x1 - me_ctx->pred_x) + FFABS(mv_y1 - > me_ctx->pred_y)) * COST_PRED_SCALE; with this style of smoothness cost you likely want to make an exception for the 0,0 vector (giving it the same "penalty" as the median or even very slightly less) This would normally be implemented by not adding the penalty on the 0,0 perdictor check but as its implemented in the compare function itself it would need a check i think it would slighty improve quality. Of course if it does not then ignore this suggestion also i will apply this patchset once the issues raised here are fixed if noone objects, its much easier and more efficient to work in main git than on top of a growing patch Thanks [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Republics decline into democracies and democracies degenerate into despotisms. -- Aristotle
signature.asc
Description: Digital signature
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel