I got rid of the macros, and changed the precision to 2**20 (the inconsistency in the final statistics was due to overflow because PRECISION was too high). Now it should be small enough that it would take 78hrs of 60fps to overflow. It also now separately keeps track of the absolute total and log that at the end.
From 531b758519387fd31eb9ddac7561737340accba0 Mon Sep 17 00:00:00 2001 From: Kevin Mitchell <kevmi...@gmail.com> Date: Sun, 2 Nov 2014 21:30:51 -0800 Subject: [PATCH 1/2] avfilter/vf_idet: add a "half_life" option for statistics
This can be useful for videos in which the interlacing pattern changes. --- doc/filters.texi | 5 ++++ libavfilter/version.h | 2 +- libavfilter/vf_idet.c | 82 +++++++++++++++++++++++++++++++++++---------------- libavfilter/vf_idet.h | 8 +++-- 4 files changed, 69 insertions(+), 28 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 33f842b..ae08f32 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -5625,6 +5625,11 @@ The filter accepts the following options: Set interlacing threshold. @item prog_thres Set progressive threshold. +@item half_life +Number of frames after which a given frame's contribution to the +statistics is halved (i.e., it contributes only 0.5 to it's +classification). The default of 0 means that all frames seen are given +full weight of 1.0 forever. @end table @section il diff --git a/libavfilter/version.h b/libavfilter/version.h index 440c587..dab9b45 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #define LIBAVFILTER_VERSION_MAJOR 5 #define LIBAVFILTER_VERSION_MINOR 2 -#define LIBAVFILTER_VERSION_MICRO 101 +#define LIBAVFILTER_VERSION_MICRO 102 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ diff --git a/libavfilter/vf_idet.c b/libavfilter/vf_idet.c index 6f99f39..01d7eca 100644 --- a/libavfilter/vf_idet.c +++ b/libavfilter/vf_idet.c @@ -32,6 +32,7 @@ static const AVOption idet_options[] = { { "intl_thres", "set interlacing threshold", OFFSET(interlace_threshold), AV_OPT_TYPE_FLOAT, {.dbl = 1.04}, -1, FLT_MAX, FLAGS }, { "prog_thres", "set progressive threshold", OFFSET(progressive_threshold), AV_OPT_TYPE_FLOAT, {.dbl = 1.5}, -1, FLT_MAX, FLAGS }, + { "half_life", "half life of cumulative statistics", OFFSET(half_life), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, -1, INT_MAX, FLAGS }, { NULL } }; @@ -48,6 +49,24 @@ static const char *type2str(Type type) return NULL; } +#define PRECISION 1048576 + +static uint64_t uintpow(uint64_t b,unsigned int e) +{ + uint64_t r=1; + while(e--) r*=b; + return r; +} + +static int av_dict_set_fxp(AVDictionary **pm, const char *key, uint64_t value, unsigned int digits, + int flags) +{ + char valuestr[44]; + snprintf(valuestr, sizeof(valuestr), "%"PRId64".%0*"PRId64, + value / PRECISION, digits, ( value % PRECISION ) / ( PRECISION / uintpow(10,digits) )); + return av_dict_set(pm, key, valuestr, flags); +} + int ff_idet_filter_line_c(const uint8_t *a, const uint8_t *b, const uint8_t *c, int w) { int x; @@ -146,23 +165,32 @@ static void filter(AVFilterContext *ctx) idet->cur->interlaced_frame = 0; } - idet->prestat [ type] ++; - idet->poststat[idet->last_type] ++; + + + for(i=0; i<4; i++){ + idet->prestat [i] = (idet->decay_coefficient * idet->prestat [i]) / PRECISION; + idet->poststat[i] = (idet->decay_coefficient * idet->poststat[i]) / PRECISION; + } + + idet->total_prestat [ type] ++; + idet->prestat [ type] += PRECISION; + + idet->total_poststat[idet->last_type] ++; + idet->poststat [idet->last_type] += PRECISION; av_log(ctx, AV_LOG_DEBUG, "Single frame:%12s, Multi frame:%12s\n", type2str(type), type2str(idet->last_type)); - av_dict_set (metadata, "lavfi.idet.single.current_frame", type2str(type), 0); - av_dict_set_int(metadata, "lavfi.idet.single.tff", idet->prestat[TFF], 0); - av_dict_set_int(metadata, "lavfi.idet.single.bff", idet->prestat[BFF], 0); - av_dict_set_int(metadata, "lavfi.idet.single.progressive", idet->prestat[PROGRESSIVE], 0); - av_dict_set_int(metadata, "lavfi.idet.single.undetermined", idet->prestat[UNDETERMINED], 0); + av_dict_set (metadata, "lavfi.idet.single.current_frame", type2str(type), 0); + av_dict_set_fxp(metadata, "lavfi.idet.single.tff", idet->prestat[TFF], 2 , 0); + av_dict_set_fxp(metadata, "lavfi.idet.single.bff", idet->prestat[BFF], 2, 0); + av_dict_set_fxp(metadata, "lavfi.idet.single.progressive", idet->prestat[PROGRESSIVE], 2, 0); + av_dict_set_fxp(metadata, "lavfi.idet.single.undetermined", idet->prestat[UNDETERMINED], 2, 0); av_dict_set (metadata, "lavfi.idet.multiple.current_frame", type2str(idet->last_type), 0); - av_dict_set_int(metadata, "lavfi.idet.multiple.tff", idet->poststat[TFF], 0); - av_dict_set_int(metadata, "lavfi.idet.multiple.bff", idet->poststat[BFF], 0); - av_dict_set_int(metadata, "lavfi.idet.multiple.progressive", idet->poststat[PROGRESSIVE], 0); - av_dict_set_int(metadata, "lavfi.idet.multiple.undetermined", idet->poststat[UNDETERMINED], 0); - + av_dict_set_fxp(metadata, "lavfi.idet.multiple.tff", idet->poststat[TFF], 2, 0); + av_dict_set_fxp(metadata, "lavfi.idet.multiple.bff", idet->poststat[BFF], 2, 0); + av_dict_set_fxp(metadata, "lavfi.idet.multiple.progressive", idet->poststat[PROGRESSIVE], 2, 0); + av_dict_set_fxp(metadata, "lavfi.idet.multiple.undetermined", idet->poststat[UNDETERMINED], 2, 0); } static int filter_frame(AVFilterLink *link, AVFrame *picref) @@ -228,18 +256,18 @@ static av_cold void uninit(AVFilterContext *ctx) { IDETContext *idet = ctx->priv; - av_log(ctx, AV_LOG_INFO, "Single frame detection: TFF:%d BFF:%d Progressive:%d Undetermined:%d\n", - idet->prestat[TFF], - idet->prestat[BFF], - idet->prestat[PROGRESSIVE], - idet->prestat[UNDETERMINED] - ); - av_log(ctx, AV_LOG_INFO, "Multi frame detection: TFF:%d BFF:%d Progressive:%d Undetermined:%d\n", - idet->poststat[TFF], - idet->poststat[BFF], - idet->poststat[PROGRESSIVE], - idet->poststat[UNDETERMINED] - ); + av_log(ctx, AV_LOG_INFO, "Single frame detection: TFF:%6"PRId64" BFF:%6"PRId64" Progressive:%6"PRId64" Undetermined:%6"PRId64"\n", + idet->total_prestat[TFF], + idet->total_prestat[BFF], + idet->total_prestat[PROGRESSIVE], + idet->total_prestat[UNDETERMINED] + ); + av_log(ctx, AV_LOG_INFO, "Multi frame detection: TFF:%6"PRId64" BFF:%6"PRId64" Progressive:%6"PRId64" Undetermined:%6"PRId64"\n", + idet->total_poststat[TFF], + idet->total_poststat[BFF], + idet->total_poststat[PROGRESSIVE], + idet->total_poststat[UNDETERMINED] + ); av_frame_free(&idet->prev); av_frame_free(&idet->cur ); @@ -290,6 +318,11 @@ static av_cold int init(AVFilterContext *ctx) idet->last_type = UNDETERMINED; memset(idet->history, UNDETERMINED, HIST_SIZE); + if( idet->half_life > 0 ) + idet->decay_coefficient = (uint64_t) round( PRECISION * pow(2.0,-1.0 / idet->half_life) ); + else + idet->decay_coefficient = PRECISION; + idet->filter_line = ff_idet_filter_line_c; if (ARCH_X86) @@ -298,7 +331,6 @@ static av_cold int init(AVFilterContext *ctx) return 0; } - static const AVFilterPad idet_inputs[] = { { .name = "default", diff --git a/libavfilter/vf_idet.h b/libavfilter/vf_idet.h index 57332df..05aa1e0 100644 --- a/libavfilter/vf_idet.h +++ b/libavfilter/vf_idet.h @@ -37,10 +37,14 @@ typedef struct { const AVClass *class; float interlace_threshold; float progressive_threshold; + float half_life; + uint64_t decay_coefficient; Type last_type; - int prestat[4]; - int poststat[4]; + uint64_t prestat[4]; + uint64_t poststat[4]; + uint64_t total_prestat[4]; + uint64_t total_poststat[4]; uint8_t history[HIST_SIZE]; -- 2.1.1
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel