]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_lagfun.c
avcodec: postpone removal of deprecated libopenh264 wrapper options
[ffmpeg] / libavfilter / vf_lagfun.c
index 329c7465e14ea2ee165b66219e722a64571635be..36b19b3f8341a1259d30adc94b4466d3a2227e98 100644 (file)
 
 typedef struct LagfunContext {
     const AVClass *class;
-    const AVPixFmtDescriptor *desc;
     float decay;
     int planes;
 
     int depth;
     int nb_planes;
     int linesize[4];
-    int height[4];
+    int planewidth[4];
+    int planeheight[4];
 
-    AVFrame *old;
+    float *old[4];
 
     int (*lagfun)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
 } LagfunContext;
@@ -74,100 +74,87 @@ static int query_formats(AVFilterContext *ctx)
 }
 
 typedef struct ThreadData {
-    AVFrame *in, *out, *old;
+    AVFrame *in, *out;
 } ThreadData;
 
-static int lagfun_frame8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
-{
-    LagfunContext *s = ctx->priv;
-    const float decay = s->decay;
-    ThreadData *td = arg;
-    AVFrame *in = td->in;
-    AVFrame *out = td->out;
-    AVFrame *old = td->old;
-
-    for (int p = 0; p < s->nb_planes; p++) {
-        const int slice_start = (s->height[p] * jobnr) / nb_jobs;
-        const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs;
-        const uint8_t *src = in->data[p] + slice_start * in->linesize[p];
-        const uint8_t *osrc = old->data[p] + slice_start * old->linesize[p];
-        uint8_t *dst = out->data[p] + slice_start * out->linesize[p];
-
-        if (!((1 << p) & s->planes)) {
-            av_image_copy_plane(dst, out->linesize[p],
-                                src, in->linesize[p],
-                                s->linesize[p], slice_end - slice_start);
-            continue;
-        }
-
-        for (int y = slice_start; y < slice_end; y++) {
-            for (int x = 0; x < s->linesize[p]; x++)
-                dst[x] = FFMAX(src[x], osrc[x] * decay);
-
-            src += in->linesize[p];
-            osrc += old->linesize[p];
-            dst += out->linesize[p];
-        }
-    }
-
-    return 0;
+#define LAGFUN(name, type)                                                \
+static int lagfun_frame##name(AVFilterContext *ctx, void *arg,            \
+                              int jobnr, int nb_jobs)                     \
+{                                                                         \
+    LagfunContext *s = ctx->priv;                                         \
+    const float decay = s->decay;                                         \
+    ThreadData *td = arg;                                                 \
+    AVFrame *in = td->in;                                                 \
+    AVFrame *out = td->out;                                               \
+                                                                          \
+    for (int p = 0; p < s->nb_planes; p++) {                              \
+        const int slice_start = (s->planeheight[p] * jobnr) / nb_jobs;    \
+        const int slice_end = (s->planeheight[p] * (jobnr+1)) / nb_jobs;  \
+        const type *src = (const type *)in->data[p] +                     \
+                          slice_start * in->linesize[p] / sizeof(type);   \
+        float *osrc = s->old[p] + slice_start * s->planewidth[p];         \
+        type *dst = (type *)out->data[p] +                                \
+                    slice_start * out->linesize[p] / sizeof(type);        \
+                                                                          \
+        if (!((1 << p) & s->planes)) {                                    \
+            av_image_copy_plane((uint8_t *)dst, out->linesize[p],         \
+                                (const uint8_t *)src, in->linesize[p],    \
+                                s->linesize[p], slice_end - slice_start); \
+            continue;                                                     \
+        }                                                                 \
+                                                                          \
+        for (int y = slice_start; y < slice_end; y++) {                   \
+            for (int x = 0; x < s->planewidth[p]; x++) {                  \
+                float v = FFMAX(src[x], osrc[x] * decay);                 \
+                                                                          \
+                osrc[x] = v;                                              \
+                if (ctx->is_disabled) {                                   \
+                    dst[x] = src[x];                                      \
+                } else {                                                  \
+                    dst[x] = lrintf(v);                                   \
+                }                                                         \
+            }                                                             \
+                                                                          \
+            src += in->linesize[p] / sizeof(type);                        \
+            osrc += s->planewidth[p];                                     \
+            dst += out->linesize[p] / sizeof(type);                       \
+        }                                                                 \
+    }                                                                     \
+                                                                          \
+    return 0;                                                             \
 }
 
-static int lagfun_frame16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
-{
-    LagfunContext *s = ctx->priv;
-    const float decay = s->decay;
-    ThreadData *td = arg;
-    AVFrame *in = td->in;
-    AVFrame *out = td->out;
-    AVFrame *old = td->old;
-
-    for (int p = 0; p < s->nb_planes; p++) {
-        const int slice_start = (s->height[p] * jobnr) / nb_jobs;
-        const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs;
-        const uint16_t *src = (const uint16_t *)in->data[p] + slice_start * in->linesize[p] / 2;
-        const uint16_t *osrc = (const uint16_t *)old->data[p] + slice_start * old->linesize[p] / 2;
-        uint16_t *dst = (uint16_t *)out->data[p] + slice_start * out->linesize[p] / 2;
-
-        if (!((1 << p) & s->planes)) {
-            av_image_copy_plane((uint8_t *)dst, out->linesize[p],
-                                (uint8_t *)src, in->linesize[p],
-                                s->linesize[p], slice_end - slice_start);
-            continue;
-        }
-
-        for (int y = slice_start; y < slice_end; y++) {
-            for (int x = 0; x < s->linesize[p]; x++)
-                dst[x] = FFMAX(src[x], osrc[x] * decay);
-
-            src += in->linesize[p] / 2;
-            osrc += old->linesize[p] / 2;
-            dst += out->linesize[p] / 2;
-        }
-    }
-
-    return 0;
-}
+LAGFUN(8, uint8_t)
+LAGFUN(16, uint16_t)
 
 static int config_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
     LagfunContext *s = ctx->priv;
     AVFilterLink *inlink = ctx->inputs[0];
+    const AVPixFmtDescriptor *desc;
     int ret;
 
-    s->desc = av_pix_fmt_desc_get(outlink->format);
-    if (!s->desc)
+    desc = av_pix_fmt_desc_get(outlink->format);
+    if (!desc)
         return AVERROR_BUG;
     s->nb_planes = av_pix_fmt_count_planes(outlink->format);
-    s->depth = s->desc->comp[0].depth;
+    s->depth = desc->comp[0].depth;
     s->lagfun = s->depth <= 8 ? lagfun_frame8 : lagfun_frame16;
 
     if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0)
         return ret;
 
-    s->height[1] = s->height[2] = AV_CEIL_RSHIFT(inlink->h, s->desc->log2_chroma_h);
-    s->height[0] = s->height[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->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
+    s->planeheight[0] = s->planeheight[3] = inlink->h;
+
+    for (int p = 0; p < s->nb_planes; p++) {
+        s->old[p] = av_calloc(s->planewidth[p] * s->planeheight[p], sizeof(*s->old[0]));
+        if (!s->old[p])
+            return AVERROR(ENOMEM);
+    }
 
     return 0;
 }
@@ -180,11 +167,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     ThreadData td;
     AVFrame *out;
 
-    if (!s->old) {
-        s->old = av_frame_clone(in);
-        return ff_filter_frame(outlink, in);
-    }
-
     out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
     if (!out) {
         av_frame_free(&in);
@@ -194,12 +176,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 
     td.out = out;
     td.in = in;
-    td.old = s->old;
-    ctx->internal->execute(ctx, s->lagfun, &td, NULL, FFMIN(s->height[1], ff_filter_get_nb_threads(ctx)));
+    ctx->internal->execute(ctx, s->lagfun, &td, NULL, FFMIN(s->planeheight[1], ff_filter_get_nb_threads(ctx)));
 
-    av_frame_free(&s->old);
     av_frame_free(&in);
-    s->old = av_frame_clone(out);
     return ff_filter_frame(outlink, out);
 }
 
@@ -207,11 +186,12 @@ static av_cold void uninit(AVFilterContext *ctx)
 {
     LagfunContext *s = ctx->priv;
 
-    av_frame_free(&s->old);
+    for (int p = 0; p < s->nb_planes; p++)
+        av_freep(&s->old[p]);
 }
 
 #define OFFSET(x) offsetof(LagfunContext, 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 lagfun_options[] = {
     { "decay",  "set decay",                 OFFSET(decay),  AV_OPT_TYPE_FLOAT, {.dbl=.95},  0,  1,  FLAGS },
@@ -248,5 +228,6 @@ AVFilter ff_vf_lagfun = {
     .uninit        = uninit,
     .outputs       = outputs,
     .inputs        = inputs,
-    .flags         = AVFILTER_FLAG_SLICE_THREADS,
+    .flags         = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
+    .process_command = ff_filter_process_command,
 };