avfilter/vf_idet: add a "half_life" option for statistics
This can be useful for videos in which the interlacing pattern changes. Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
		
							parent
							
								
									50138ea4f7
								
							
						
					
					
						commit
						fe6f5f2908
					
				| @ -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 | ||||
|  | ||||
| @ -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, \ | ||||
|  | ||||
| @ -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", | ||||
|  | ||||
| @ -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]; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user