]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_hqdn3d.c
avfilter: Constify all AVFilters
[ffmpeg] / libavfilter / vf_hqdn3d.c
index d6c14bb3d880381d08d92edf7f84846cce0bb3bd..8d71ae316d6b97f7775da386e86e81e0dbeb7ab4 100644 (file)
@@ -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<<LUT_BITS)*sizeof(int16_t));
-    if (!ct)
-        return NULL;
 
     gamma = log(0.25) / log(1.0 - FFMIN(dist25,252.0)/255.0 - 0.00001);
 
@@ -188,7 +187,6 @@ static int16_t *precalc_coefs(double dist25, int depth)
     }
 
     ct[0] = !!dist25;
-    return ct;
 }
 
 #define PARAM1_DEFAULT 4.0
@@ -223,7 +221,9 @@ static av_cold void uninit(AVFilterContext *ctx)
     av_freep(&s->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<<LUT_BITS) * sizeof(int16_t));
         if (!s->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,
 };