X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_delogo.c;h=dc58078d04aefa0880236787f5565e33da8472c0;hb=6ebd06a9b2508747a135ee4c880d8f612e08932b;hp=81f33b727ef15ccf6dcbf8958bccd2eb1bc1a8ad;hpb=d4f89906e3b310609b636cf6071313ec557ec873;p=ffmpeg diff --git a/libavfilter/vf_delogo.c b/libavfilter/vf_delogo.c index 81f33b727ef..dc58078d04a 100644 --- a/libavfilter/vf_delogo.c +++ b/libavfilter/vf_delogo.c @@ -25,6 +25,7 @@ * Ported from MPlayer libmpcodecs/vf_delogo.c. */ +#include "libavutil/common.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" @@ -79,12 +80,12 @@ static void apply_delogo(uint8_t *dst, int dst_linesize, topright = src+logo_y1 * src_linesize+logo_x2-1; botleft = src+(logo_y2-1) * src_linesize+logo_x1; - dst += (logo_y1+1)*dst_linesize; - src += (logo_y1+1)*src_linesize; - if (!direct) av_image_copy_plane(dst, dst_linesize, src, src_linesize, w, h); + dst += (logo_y1 + 1) * dst_linesize; + src += (logo_y1 + 1) * src_linesize; + for (y = logo_y1+1; y < logo_y2-1; y++) { for (x = logo_x1+1, xdst = dst+logo_x1+1, @@ -129,22 +130,23 @@ static void apply_delogo(uint8_t *dst, int dst_linesize, } } -typedef struct { +typedef struct DelogoContext { const AVClass *class; int x, y, w, h, band, show; } DelogoContext; #define OFFSET(x) offsetof(DelogoContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM static const AVOption delogo_options[]= { - {"x", "set logo x position", OFFSET(x), FF_OPT_TYPE_INT, {-1}, -1, INT_MAX }, - {"y", "set logo y position", OFFSET(y), FF_OPT_TYPE_INT, {-1}, -1, INT_MAX }, - {"w", "set logo width", OFFSET(w), FF_OPT_TYPE_INT, {-1}, -1, INT_MAX }, - {"h", "set logo height", OFFSET(h), FF_OPT_TYPE_INT, {-1}, -1, INT_MAX }, - {"band", "set delogo area band size", OFFSET(band), FF_OPT_TYPE_INT, { 4}, -1, INT_MAX }, - {"t", "set delogo area band size", OFFSET(band), FF_OPT_TYPE_INT, { 4}, -1, INT_MAX }, - {"show", "show delogo area", OFFSET(show), FF_OPT_TYPE_INT, { 0}, 0, 1 }, - {NULL}, + { "x", "set logo x position", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, + { "y", "set logo y position", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, + { "w", "set logo width", OFFSET(w), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, + { "h", "set logo height", OFFSET(h), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, + { "band", "set delogo area band size", OFFSET(band), AV_OPT_TYPE_INT, { .i64 = 4 }, -1, INT_MAX, FLAGS }, + { "t", "set delogo area band size", OFFSET(band), AV_OPT_TYPE_INT, { .i64 = 4 }, -1, INT_MAX, FLAGS }, + { "show", "show delogo area", OFFSET(show), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS }, + { NULL }, }; static const char *delogo_get_name(void *ctx) @@ -160,39 +162,24 @@ static const AVClass delogo_class = { static int query_formats(AVFilterContext *ctx) { - enum PixelFormat pix_fmts[] = { - PIX_FMT_YUV444P, PIX_FMT_YUV422P, PIX_FMT_YUV420P, - PIX_FMT_YUV411P, PIX_FMT_YUV410P, PIX_FMT_YUV440P, - PIX_FMT_YUVA420P, PIX_FMT_GRAY8, - PIX_FMT_NONE + enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_GRAY8, + 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) +static av_cold int init(AVFilterContext *ctx) { - DelogoContext *delogo = ctx->priv; - int ret = 0; - - delogo->class = &delogo_class; - av_opt_set_defaults(delogo); - - if (args) - ret = sscanf(args, "%d:%d:%d:%d:%d", - &delogo->x, &delogo->y, &delogo->w, &delogo->h, &delogo->band); - if (ret == 5) { - if (delogo->band < 0) - delogo->show = 1; - } else if ((ret = (av_set_options_string(delogo, args, "=", ":"))) < 0) { - av_log(ctx, AV_LOG_ERROR, "Error parsing options string: '%s'\n", args); - return ret; - } + DelogoContext *s = ctx->priv; #define CHECK_UNSET_OPT(opt) \ - if (delogo->opt == -1) { \ - av_log(delogo, AV_LOG_ERROR, "Option %s was not set.\n", #opt); \ + if (s->opt == -1) { \ + av_log(s, AV_LOG_ERROR, "Option %s was not set.\n", #opt); \ return AVERROR(EINVAL); \ } CHECK_UNSET_OPT(x); @@ -200,104 +187,91 @@ static av_cold int init(AVFilterContext *ctx, const char *args) CHECK_UNSET_OPT(w); CHECK_UNSET_OPT(h); - if (delogo->show) - delogo->band = 4; + if (s->show) + s->band = 4; av_log(ctx, AV_LOG_DEBUG, "x:%d y:%d, w:%d h:%d band:%d show:%d\n", - delogo->x, delogo->y, delogo->w, delogo->h, delogo->band, delogo->show); + s->x, s->y, s->w, s->h, s->band, s->show); - delogo->w += delogo->band*2; - delogo->h += delogo->band*2; - delogo->x -= delogo->band; - delogo->y -= delogo->band; + s->w += s->band*2; + s->h += s->band*2; + s->x -= s->band; + s->y -= s->band; return 0; } -static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) +static int filter_frame(AVFilterLink *inlink, AVFrame *in) { + DelogoContext *s = inlink->dst->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; - AVFilterBufferRef *outpicref = NULL; - int ret = 0; - - if (inpicref->perms & AV_PERM_PRESERVE) { - outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE, - outlink->w, outlink->h); - if (!outpicref) - return AVERROR(ENOMEM); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + AVFrame *out; + int hsub0 = desc->log2_chroma_w; + int vsub0 = desc->log2_chroma_h; + int direct = 0; + int plane; - avfilter_copy_buffer_ref_props(outpicref, inpicref); - outpicref->video->w = outlink->w; - outpicref->video->h = outlink->h; + if (av_frame_is_writable(in)) { + direct = 1; + out = in; } else { - outpicref = avfilter_ref_buffer(inpicref, ~0); - if (!outpicref) + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + av_frame_free(&in); return AVERROR(ENOMEM); - } + } - ret = ff_start_frame(outlink, avfilter_ref_buffer(outpicref, ~0)); - if (ret < 0) { - avfilter_unref_bufferp(&outpicref); - return ret; + av_frame_copy_props(out, in); + out->width = outlink->w; + out->height = outlink->h; } - outlink->out_buf = outpicref; - return 0; -} - -static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) -{ - return 0; -} - -static int end_frame(AVFilterLink *inlink) -{ - DelogoContext *delogo = inlink->dst->priv; - AVFilterLink *outlink = inlink->dst->outputs[0]; - AVFilterBufferRef *inpicref = inlink ->cur_buf; - AVFilterBufferRef *outpicref = outlink->out_buf; - int direct = inpicref->buf == outpicref->buf; - int hsub0 = av_pix_fmt_descriptors[inlink->format].log2_chroma_w; - int vsub0 = av_pix_fmt_descriptors[inlink->format].log2_chroma_h; - int plane; - int ret; - - for (plane = 0; plane < 4 && inpicref->data[plane]; plane++) { + for (plane = 0; plane < 4 && in->data[plane]; plane++) { int hsub = plane == 1 || plane == 2 ? hsub0 : 0; int vsub = plane == 1 || plane == 2 ? vsub0 : 0; - apply_delogo(outpicref->data[plane], outpicref->linesize[plane], - inpicref ->data[plane], inpicref ->linesize[plane], + apply_delogo(out->data[plane], out->linesize[plane], + in ->data[plane], in ->linesize[plane], inlink->w>>hsub, inlink->h>>vsub, - delogo->x>>hsub, delogo->y>>vsub, - delogo->w>>hsub, delogo->h>>vsub, - delogo->band>>FFMIN(hsub, vsub), - delogo->show, direct); + s->x>>hsub, s->y>>vsub, + s->w>>hsub, s->h>>vsub, + s->band>>FFMIN(hsub, vsub), + s->show, direct); } - if ((ret = ff_draw_slice(outlink, 0, inlink->h, 1)) < 0 || - (ret = ff_end_frame(outlink)) < 0) - return ret; - return 0; + if (!direct) + av_frame_free(&in); + + return ff_filter_frame(outlink, out); } -AVFilter avfilter_vf_delogo = { +static const AVFilterPad avfilter_vf_delogo_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .get_video_buffer = ff_null_get_video_buffer, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad avfilter_vf_delogo_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter ff_vf_delogo = { .name = "delogo", .description = NULL_IF_CONFIG_SMALL("Remove logo from input video."), .priv_size = sizeof(DelogoContext), + .priv_class = &delogo_class, .init = init, .query_formats = query_formats, - .inputs = (const AVFilterPad[]) {{ .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .get_video_buffer = ff_null_get_video_buffer, - .start_frame = start_frame, - .draw_slice = null_draw_slice, - .end_frame = end_frame, - .min_perms = AV_PERM_WRITE | AV_PERM_READ, - .rej_perms = AV_PERM_PRESERVE }, - { .name = NULL}}, - .outputs = (const AVFilterPad[]) {{ .name = "default", - .type = AVMEDIA_TYPE_VIDEO, }, - { .name = NULL}}, + .inputs = avfilter_vf_delogo_inputs, + .outputs = avfilter_vf_delogo_outputs, };