X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_hqdn3d.c;h=8d71ae316d6b97f7775da386e86e81e0dbeb7ab4;hb=a04ad248a05e7b613abe09b3bb067f555108d794;hp=d6c14bb3d880381d08d92edf7f84846cce0bb3bd;hpb=6fc762b4fd2c28ef7a0689a1df5ce200e5f5948f;p=ffmpeg diff --git a/libavfilter/vf_hqdn3d.c b/libavfilter/vf_hqdn3d.c index d6c14bb3d88..8d71ae316d6 100644 --- a/libavfilter/vf_hqdn3d.c +++ b/libavfilter/vf_hqdn3d.c @@ -160,6 +160,8 @@ static int denoise_depth(HQDN3DContext *s, case 8: ret = denoise_depth(__VA_ARGS__, 8); break; \ case 9: ret = denoise_depth(__VA_ARGS__, 9); break; \ case 10: ret = denoise_depth(__VA_ARGS__, 10); break; \ + case 12: ret = denoise_depth(__VA_ARGS__, 12); break; \ + case 14: ret = denoise_depth(__VA_ARGS__, 14); break; \ case 16: ret = denoise_depth(__VA_ARGS__, 16); break; \ } \ if (ret < 0) { \ @@ -170,13 +172,10 @@ static int denoise_depth(HQDN3DContext *s, } \ } while (0) -static int16_t *precalc_coefs(double dist25, int depth) +static void precalc_coefs(double dist25, int depth, int16_t *ct) { int i; double gamma, simil, C; - int16_t *ct = av_malloc((512<coefs[1]); av_freep(&s->coefs[2]); av_freep(&s->coefs[3]); - av_freep(&s->line); + av_freep(&s->line[0]); + av_freep(&s->line[1]); + av_freep(&s->line[2]); av_freep(&s->frame_prev[0]); av_freep(&s->frame_prev[1]); av_freep(&s->frame_prev[2]); @@ -232,25 +232,16 @@ static av_cold void uninit(AVFilterContext *ctx) static int query_formats(AVFilterContext *ctx) { static const enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_YUV422P, - AV_PIX_FMT_YUV444P, - AV_PIX_FMT_YUV410P, - AV_PIX_FMT_YUV411P, - AV_PIX_FMT_YUV440P, - AV_PIX_FMT_YUVJ420P, - AV_PIX_FMT_YUVJ422P, - AV_PIX_FMT_YUVJ444P, - AV_PIX_FMT_YUVJ440P, - AV_PIX_FMT_YUV420P9, - AV_PIX_FMT_YUV422P9, - AV_PIX_FMT_YUV444P9, - AV_PIX_FMT_YUV420P10, - AV_PIX_FMT_YUV422P10, - AV_PIX_FMT_YUV444P10, - AV_PIX_FMT_YUV420P16, - AV_PIX_FMT_YUV422P16, - AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + 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_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_NONE }; AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); @@ -259,42 +250,79 @@ static int query_formats(AVFilterContext *ctx) return ff_set_common_formats(ctx, fmts_list); } +static void calc_coefs(AVFilterContext *ctx) +{ + HQDN3DContext *s = ctx->priv; + + for (int i = 0; i < 4; i++) + precalc_coefs(s->strength[i], s->depth, s->coefs[i]); +} + static int config_input(AVFilterLink *inlink) { + AVFilterContext *ctx = inlink->dst; HQDN3DContext *s = inlink->dst->priv; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); - int i; + int i, depth; uninit(inlink->dst); s->hsub = desc->log2_chroma_w; s->vsub = desc->log2_chroma_h; - s->depth = desc->comp[0].depth; + s->depth = depth = desc->comp[0].depth; - s->line = av_malloc_array(inlink->w, sizeof(*s->line)); - if (!s->line) - return AVERROR(ENOMEM); + for (i = 0; i < 3; i++) { + s->line[i] = av_malloc_array(inlink->w, sizeof(*s->line[i])); + if (!s->line[i]) + return AVERROR(ENOMEM); + } for (i = 0; i < 4; i++) { - s->coefs[i] = precalc_coefs(s->strength[i], s->depth); + s->coefs[i] = av_malloc((512<coefs[i]) return AVERROR(ENOMEM); } + calc_coefs(ctx); + if (ARCH_X86) ff_hqdn3d_init_x86(s); return 0; } +typedef struct ThreadData { + AVFrame *in, *out; + int direct; +} ThreadData; + +static int do_denoise(AVFilterContext *ctx, void *data, int job_nr, int n_jobs) +{ + HQDN3DContext *s = ctx->priv; + const ThreadData *td = data; + AVFrame *out = td->out; + AVFrame *in = td->in; + int direct = td->direct; + + denoise(s, in->data[job_nr], out->data[job_nr], + s->line[job_nr], &s->frame_prev[job_nr], + AV_CEIL_RSHIFT(in->width, (!!job_nr * s->hsub)), + AV_CEIL_RSHIFT(in->height, (!!job_nr * s->vsub)), + in->linesize[job_nr], out->linesize[job_nr], + s->coefs[job_nr ? CHROMA_SPATIAL : LUMA_SPATIAL], + s->coefs[job_nr ? CHROMA_TMP : LUMA_TMP]); + + return 0; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; - HQDN3DContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out; - int c, direct = av_frame_is_writable(in) && !ctx->is_disabled; + int direct = av_frame_is_writable(in) && !ctx->is_disabled; + ThreadData td; if (direct) { out = in; @@ -308,15 +336,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); } - for (c = 0; c < 3; c++) { - denoise(s, in->data[c], out->data[c], - s->line, &s->frame_prev[c], - AV_CEIL_RSHIFT(in->width, (!!c * s->hsub)), - AV_CEIL_RSHIFT(in->height, (!!c * s->vsub)), - in->linesize[c], out->linesize[c], - s->coefs[c ? CHROMA_SPATIAL : LUMA_SPATIAL], - s->coefs[c ? CHROMA_TMP : LUMA_TMP]); - } + td.in = in; + td.out = out; + td.direct = direct; + /* one thread per plane */ + ctx->internal->execute(ctx, do_denoise, &td, NULL, 3); if (ctx->is_disabled) { av_frame_free(&out); @@ -329,8 +353,22 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) return ff_filter_frame(outlink, out); } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + calc_coefs(ctx); + + return 0; +} + #define OFFSET(x) offsetof(HQDN3DContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM static const AVOption hqdn3d_options[] = { { "luma_spatial", "spatial luma strength", OFFSET(strength[LUMA_SPATIAL]), AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, 0, DBL_MAX, FLAGS }, { "chroma_spatial", "spatial chroma strength", OFFSET(strength[CHROMA_SPATIAL]), AV_OPT_TYPE_DOUBLE, { .dbl = 0.0 }, 0, DBL_MAX, FLAGS }, @@ -360,7 +398,7 @@ static const AVFilterPad avfilter_vf_hqdn3d_outputs[] = { { NULL } }; -AVFilter ff_vf_hqdn3d = { +const AVFilter ff_vf_hqdn3d = { .name = "hqdn3d", .description = NULL_IF_CONFIG_SMALL("Apply a High Quality 3D Denoiser."), .priv_size = sizeof(HQDN3DContext), @@ -370,5 +408,6 @@ AVFilter ff_vf_hqdn3d = { .query_formats = query_formats, .inputs = avfilter_vf_hqdn3d_inputs, .outputs = avfilter_vf_hqdn3d_outputs, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, };