You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	avfilter: add bitplanenoise filter
This commit is contained in:
		| @@ -15,6 +15,7 @@ version <next>: | ||||
| - True Audio (TTA) muxer | ||||
| - crystalizer audio filter | ||||
| - acrusher audio filter | ||||
| - bitplanenoise video filter | ||||
|  | ||||
|  | ||||
| version 3.1: | ||||
|   | ||||
| @@ -4410,6 +4410,21 @@ The filter accepts the following option: | ||||
| Set the minimal luminance value. Default is @code{16}. | ||||
| @end table | ||||
|  | ||||
| @section bitplanenoise | ||||
|  | ||||
| Show and measure bit plane noise. | ||||
|  | ||||
| The filter accepts the following options: | ||||
|  | ||||
| @table @option | ||||
| @item bitplane | ||||
| Set which plane to analyze. Default is @code{1}. | ||||
|  | ||||
| @item filter | ||||
| Filter out noisy pixels from @code{bitplane} set above. | ||||
| Default is disabled. | ||||
| @end table | ||||
|  | ||||
| @section blackdetect | ||||
|  | ||||
| Detect video intervals that are (almost) completely black. Can be | ||||
|   | ||||
| @@ -125,6 +125,7 @@ OBJS-$(CONFIG_ALPHAMERGE_FILTER)             += vf_alphamerge.o | ||||
| OBJS-$(CONFIG_ATADENOISE_FILTER)             += vf_atadenoise.o | ||||
| OBJS-$(CONFIG_BBOX_FILTER)                   += bbox.o vf_bbox.o | ||||
| OBJS-$(CONFIG_BENCH_FILTER)                  += f_bench.o | ||||
| OBJS-$(CONFIG_BITPLANENOISE_FILTER)          += vf_bitplanenoise.o | ||||
| OBJS-$(CONFIG_BLACKDETECT_FILTER)            += vf_blackdetect.o | ||||
|  | ||||
| # video filters | ||||
|   | ||||
| @@ -143,6 +143,7 @@ void avfilter_register_all(void) | ||||
|     REGISTER_FILTER(ASS,            ass,            vf); | ||||
|     REGISTER_FILTER(BENCH,          bench,          vf); | ||||
|     REGISTER_FILTER(BBOX,           bbox,           vf); | ||||
|     REGISTER_FILTER(BITPLANENOISE,  bitplanenoise,  vf); | ||||
|     REGISTER_FILTER(BLACKDETECT,    blackdetect,    vf); | ||||
|     REGISTER_FILTER(BLACKFRAME,     blackframe,     vf); | ||||
|     REGISTER_FILTER(BLEND,          blend,          vf); | ||||
|   | ||||
| @@ -30,7 +30,7 @@ | ||||
| #include "libavutil/version.h" | ||||
|  | ||||
| #define LIBAVFILTER_VERSION_MAJOR   6 | ||||
| #define LIBAVFILTER_VERSION_MINOR  51 | ||||
| #define LIBAVFILTER_VERSION_MINOR  52 | ||||
| #define LIBAVFILTER_VERSION_MICRO 100 | ||||
|  | ||||
| #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ | ||||
|   | ||||
							
								
								
									
										227
									
								
								libavfilter/vf_bitplanenoise.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								libavfilter/vf_bitplanenoise.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,227 @@ | ||||
| /* | ||||
|  * Copyright (c) 2016 Paul B Mahol | ||||
|  * | ||||
|  * This file is part of FFmpeg. | ||||
|  * | ||||
|  * FFmpeg is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2.1 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * FFmpeg is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with FFmpeg; if not, write to the Free Software | ||||
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||
|  */ | ||||
|  | ||||
| #include "libavutil/opt.h" | ||||
| #include "libavutil/imgutils.h" | ||||
| #include "avfilter.h" | ||||
| #include "formats.h" | ||||
| #include "internal.h" | ||||
| #include "video.h" | ||||
|  | ||||
| typedef struct BPNContext { | ||||
|     const AVClass *class; | ||||
|  | ||||
|     int bitplane; | ||||
|     int filter; | ||||
|  | ||||
|     int nb_planes; | ||||
|     int planeheight[4]; | ||||
|     int planewidth[4]; | ||||
|     int depth; | ||||
| } BPNContext; | ||||
|  | ||||
| #define OFFSET(x) offsetof(BPNContext, x) | ||||
| #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM | ||||
| static const AVOption bitplanenoise_options[] = { | ||||
|     { "bitplane", "set bit plane to use for measuring noise",  OFFSET(bitplane), AV_OPT_TYPE_INT,  {.i64=1}, 1, 16, FLAGS}, | ||||
|     { "filter",   "show noisy pixels",                         OFFSET(filter),   AV_OPT_TYPE_BOOL, {.i64=0}, 0,  1, FLAGS}, | ||||
|     { NULL } | ||||
| }; | ||||
|  | ||||
| AVFILTER_DEFINE_CLASS(bitplanenoise); | ||||
|  | ||||
| static int query_formats(AVFilterContext *ctx) | ||||
| { | ||||
|     static const enum AVPixelFormat pixfmts[] = { | ||||
|         AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV411P, | ||||
|         AV_PIX_FMT_YUV440P, | ||||
|         AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ411P, | ||||
|         AV_PIX_FMT_YUVJ440P, | ||||
|         AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV420P9, | ||||
|         AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10, | ||||
|         AV_PIX_FMT_YUV440P10, | ||||
|         AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, | ||||
|         AV_PIX_FMT_YUV440P12, | ||||
|         AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, | ||||
|         AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV420P16, | ||||
|         AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, | ||||
|         AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, | ||||
|         AV_PIX_FMT_GRAY8, | ||||
|         AV_PIX_FMT_GRAY16, | ||||
|         AV_PIX_FMT_NONE | ||||
|     }; | ||||
|  | ||||
|     AVFilterFormats *formats = ff_make_format_list(pixfmts); | ||||
|     if (!formats) | ||||
|         return AVERROR(ENOMEM); | ||||
|     return ff_set_common_formats(ctx, formats); | ||||
| } | ||||
|  | ||||
| static int config_input(AVFilterLink *inlink) | ||||
| { | ||||
|     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); | ||||
|     AVFilterContext *ctx = inlink->dst; | ||||
|     BPNContext *s = ctx->priv; | ||||
|  | ||||
|     s->nb_planes = desc->nb_components; | ||||
|  | ||||
|     s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); | ||||
|     s->planeheight[0] = s->planeheight[3] = inlink->h; | ||||
|     s->planewidth[1]  = s->planewidth[2]  = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); | ||||
|     s->planewidth[0]  = s->planewidth[3]  = inlink->w; | ||||
|  | ||||
|     s->depth = desc->comp[0].depth; | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| #define CHECK_BIT(x, a, b, c) { \ | ||||
|     bit = (((val[(x)] & mask) == (val[(x) + (a)] & mask)) + \ | ||||
|            ((val[(x)] & mask) == (val[(x) + (b)] & mask)) + \ | ||||
|            ((val[(x)] & mask) == (val[(x) + (c)] & mask))) > 1; \ | ||||
|     if (dst) \ | ||||
|         dst[(x)] = factor * bit; \ | ||||
|     stats[plane] += bit; } | ||||
|  | ||||
| static int filter_frame(AVFilterLink *inlink, AVFrame *in) | ||||
| { | ||||
|     AVFilterContext *ctx = inlink->dst; | ||||
|     AVFilterLink *outlink = ctx->outputs[0]; | ||||
|     BPNContext *s = ctx->priv; | ||||
|     const int mask = (1 << (s->bitplane - 1)); | ||||
|     const int factor = (1 << s->depth) - 1; | ||||
|     float stats[4] = { 0 }; | ||||
|     char metabuf[128]; | ||||
|     int plane, y, x, bit; | ||||
|     AVFrame *out = s->filter ? NULL : in; | ||||
|  | ||||
|     if (!out) { | ||||
|         out = ff_get_video_buffer(outlink, outlink->w, outlink->h); | ||||
|         if (!out) { | ||||
|             av_frame_free(&in); | ||||
|             return AVERROR(ENOMEM); | ||||
|         } | ||||
|         av_frame_copy_props(out, in); | ||||
|     } | ||||
|  | ||||
|     if (s->depth <= 8) { | ||||
|         for (plane = 0; plane < s->nb_planes; plane++) { | ||||
|             const int linesize = in->linesize[plane]; | ||||
|             const int dlinesize = out->linesize[plane]; | ||||
|             uint8_t *val = in->data[plane]; | ||||
|             uint8_t *dst = s->filter ? out->data[plane]: NULL; | ||||
|  | ||||
|             for (y = 0; y < s->planeheight[plane] - 1; y++) { | ||||
|                 CHECK_BIT(0, 1, 1 + linesize, linesize) | ||||
|  | ||||
|                 for (x = 1; x < s->planewidth[plane] - 1; x++) { | ||||
|                     CHECK_BIT(x, -1, 1, linesize) | ||||
|                 } | ||||
|  | ||||
|                 CHECK_BIT(x, -1, -1 + linesize, linesize) | ||||
|  | ||||
|                 val += linesize; | ||||
|                 if (dst) | ||||
|                     dst += dlinesize; | ||||
|             } | ||||
|  | ||||
|             CHECK_BIT(0, 1, 1 - linesize, -linesize) | ||||
|  | ||||
|             for (x = 1; x < s->planewidth[plane] - 1; x++) { | ||||
|                 CHECK_BIT(x, -1, 1, -linesize) | ||||
|             } | ||||
|  | ||||
|             CHECK_BIT(x, -1, -1 - linesize, -linesize) | ||||
|         } | ||||
|     } else { | ||||
|         for (plane = 0; plane < s->nb_planes; plane++) { | ||||
|             const int linesize = in->linesize[plane] / 2; | ||||
|             const int dlinesize = out->linesize[plane] / 2; | ||||
|             uint16_t *val = (uint16_t *)in->data[plane]; | ||||
|             uint16_t *dst = s->filter ? (uint16_t *)out->data[plane] : NULL; | ||||
|  | ||||
|             val = (uint16_t *)in->data[plane]; | ||||
|             for (y = 0; y < s->planeheight[plane] - 1; y++) { | ||||
|                 CHECK_BIT(0, 1, 1 + linesize, linesize) | ||||
|  | ||||
|                 for (x = 1; x < s->planewidth[plane] - 1; x++) { | ||||
|                     CHECK_BIT(x, -1, 1, linesize) | ||||
|                 } | ||||
|  | ||||
|                 CHECK_BIT(x, -1, -1 + linesize, linesize) | ||||
|  | ||||
|                 val += linesize; | ||||
|                 if (dst) | ||||
|                     dst += dlinesize; | ||||
|             } | ||||
|  | ||||
|             CHECK_BIT(0, 1, 1 - linesize, -linesize) | ||||
|  | ||||
|             for (x = 1; x < s->planewidth[plane] - 1; x++) { | ||||
|                 CHECK_BIT(x, -1, 1, -linesize) | ||||
|             } | ||||
|  | ||||
|             CHECK_BIT(x, -1, -1 -linesize, -linesize) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     for (plane = 0; plane < s->nb_planes; plane++) { | ||||
|         char key[32]; | ||||
|  | ||||
|         stats[plane] /= s->planewidth[plane] * s->planeheight[plane]; | ||||
|         snprintf(key, sizeof(key), "lavfi.bitplanenoise.%d.%d", plane, s->bitplane); | ||||
|         snprintf(metabuf, sizeof(metabuf), "%f", 1. - 2.* fabsf((stats[plane] - 0.5))); | ||||
|         av_dict_set(&out->metadata, key, metabuf, 0); | ||||
|     } | ||||
|  | ||||
|     if (out != in) | ||||
|         av_frame_free(&in); | ||||
|  | ||||
|     return ff_filter_frame(outlink, out); | ||||
| } | ||||
|  | ||||
| static const AVFilterPad inputs[] = { | ||||
|     { | ||||
|         .name           = "default", | ||||
|         .type           = AVMEDIA_TYPE_VIDEO, | ||||
|         .filter_frame   = filter_frame, | ||||
|         .config_props   = config_input, | ||||
|     }, | ||||
|     { NULL } | ||||
| }; | ||||
|  | ||||
| static const AVFilterPad outputs[] = { | ||||
|     { | ||||
|         .name = "default", | ||||
|         .type = AVMEDIA_TYPE_VIDEO, | ||||
|     }, | ||||
|     { NULL } | ||||
| }; | ||||
|  | ||||
| AVFilter ff_vf_bitplanenoise = { | ||||
|     .name           = "bitplanenoise", | ||||
|     .description    = NULL_IF_CONFIG_SMALL("Measure bit plane noise."), | ||||
|     .priv_size      = sizeof(BPNContext), | ||||
|     .query_formats  = query_formats, | ||||
|     .inputs         = inputs, | ||||
|     .outputs        = outputs, | ||||
|     .priv_class     = &bitplanenoise_class, | ||||
|     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user