X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_blackframe.c;h=8cbcc005a49bb3dab019b05ef8bfb587fcf52930;hb=5c1585c4c3b5281835d784c5daef0069915ccd57;hp=bdc132285e4126938112c906ebcd9368bd76b491;hpb=b74a1da49db5ebed51aceae6cacc2329288a92c1;p=ffmpeg diff --git a/libavfilter/vf_blackframe.c b/libavfilter/vf_blackframe.c index bdc132285e4..8cbcc005a49 100644 --- a/libavfilter/vf_blackframe.c +++ b/libavfilter/vf_blackframe.c @@ -27,105 +27,107 @@ * Ported from MPlayer libmpcodecs/vf_blackframe.c. */ +#include +#include + +#include "libavutil/internal.h" +#include "libavutil/opt.h" + #include "avfilter.h" #include "formats.h" +#include "internal.h" #include "video.h" -typedef struct { - unsigned int bamount; ///< black amount - unsigned int bthresh; ///< black threshold +typedef struct BlackFrameContext { + const AVClass *class; + int bamount; ///< black amount + int bthresh; ///< black threshold unsigned int frame; ///< frame number unsigned int nblack; ///< number of black pixels counted so far } BlackFrameContext; static int query_formats(AVFilterContext *ctx) { - static const enum PixelFormat pix_fmts[] = { - PIX_FMT_YUV410P, PIX_FMT_YUV420P, PIX_FMT_GRAY8, PIX_FMT_NV12, - PIX_FMT_NV21, PIX_FMT_YUV444P, PIX_FMT_YUV422P, PIX_FMT_YUV411P, - PIX_FMT_NONE + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NV12, + AV_PIX_FMT_NV21, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_NONE }; ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); return 0; } -static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) -{ - BlackFrameContext *blackframe = ctx->priv; - - blackframe->bamount = 98; - blackframe->bthresh = 32; - blackframe->nblack = 0; - blackframe->frame = 0; - - if (args) - sscanf(args, "%u:%u", &blackframe->bamount, &blackframe->bthresh); - - av_log(ctx, AV_LOG_INFO, "bamount:%u bthresh:%u\n", - blackframe->bamount, blackframe->bthresh); - - if (blackframe->bamount > 100 || blackframe->bthresh > 255) { - av_log(ctx, AV_LOG_ERROR, "Too big value for bamount (max is 100) or bthresh (max is 255)\n"); - return AVERROR(EINVAL); - } - - return 0; -} - -static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; - BlackFrameContext *blackframe = ctx->priv; - AVFilterBufferRef *picref = inlink->cur_buf; + BlackFrameContext *s = ctx->priv; int x, i; - uint8_t *p = picref->data[0] + y * picref->linesize[0]; + int pblack = 0; + uint8_t *p = frame->data[0]; - for (i = 0; i < h; i++) { + for (i = 0; i < frame->height; i++) { for (x = 0; x < inlink->w; x++) - blackframe->nblack += p[x] < blackframe->bthresh; - p += picref->linesize[0]; + s->nblack += p[x] < s->bthresh; + p += frame->linesize[0]; } - avfilter_draw_slice(ctx->outputs[0], y, h, slice_dir); + pblack = s->nblack * 100 / (inlink->w * inlink->h); + if (pblack >= s->bamount) + av_log(ctx, AV_LOG_INFO, "frame:%u pblack:%u pts:%"PRId64" t:%f\n", + s->frame, pblack, frame->pts, + frame->pts == AV_NOPTS_VALUE ? -1 : frame->pts * av_q2d(inlink->time_base)); + + s->frame++; + s->nblack = 0; + return ff_filter_frame(inlink->dst->outputs[0], frame); } -static void end_frame(AVFilterLink *inlink) -{ - AVFilterContext *ctx = inlink->dst; - BlackFrameContext *blackframe = ctx->priv; - AVFilterBufferRef *picref = inlink->cur_buf; - int pblack = 0; +#define OFFSET(x) offsetof(BlackFrameContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM +static const AVOption options[] = { + { "amount", "Percentage of the pixels that have to be below the threshold " + "for the frame to be considered black.", OFFSET(bamount), AV_OPT_TYPE_INT, { .i64 = 98 }, 0, 100, FLAGS }, + { "threshold", "threshold below which a pixel value is considered black", + OFFSET(bthresh), AV_OPT_TYPE_INT, { .i64 = 32 }, 0, INT_MAX, FLAGS }, + { NULL }, +}; - pblack = blackframe->nblack * 100 / (inlink->w * inlink->h); - if (pblack >= blackframe->bamount) - av_log(ctx, AV_LOG_INFO, "frame:%u pblack:%u pos:%"PRId64" pts:%"PRId64" t:%f\n", - blackframe->frame, pblack, picref->pos, picref->pts, - picref->pts == AV_NOPTS_VALUE ? -1 : picref->pts * av_q2d(inlink->time_base)); +static const AVClass blackframe_class = { + .class_name = "blackframe", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; - blackframe->frame++; - blackframe->nblack = 0; - avfilter_end_frame(inlink->dst->outputs[0]); -} +static const AVFilterPad avfilter_vf_blackframe_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .get_video_buffer = ff_null_get_video_buffer, + .filter_frame = filter_frame, + }, + { NULL } +}; -AVFilter avfilter_vf_blackframe = { +static const AVFilterPad avfilter_vf_blackframe_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO + }, + { NULL } +}; + +AVFilter ff_vf_blackframe = { .name = "blackframe", .description = NULL_IF_CONFIG_SMALL("Detect frames that are (almost) black."), .priv_size = sizeof(BlackFrameContext), - .init = init, + .priv_class = &blackframe_class, .query_formats = query_formats, - .inputs = (AVFilterPad[]) {{ .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .draw_slice = draw_slice, - .get_video_buffer = ff_null_get_video_buffer, - .start_frame = ff_null_start_frame, - .end_frame = end_frame, }, - { .name = NULL}}, - - .outputs = (AVFilterPad[]) {{ .name = "default", - .type = AVMEDIA_TYPE_VIDEO }, - { .name = NULL}}, + .inputs = avfilter_vf_blackframe_inputs, + + .outputs = avfilter_vf_blackframe_outputs, };