Browse code

lavfi: add bench and abench filters

Clément Bœsch authored on 2016/02/29 20:19:55
Showing 6 changed files
... ...
@@ -8,6 +8,7 @@ version <next>:
8 8
 - Bob Weaver deinterlacing filter
9 9
 - firequalizer filter
10 10
 - datascope filter
11
+- bench and abench filters
11 12
 
12 13
 
13 14
 version 3.0:
... ...
@@ -10874,6 +10874,7 @@ Scale a subtitle stream to match the main video in size before overlaying
10874 10874
 @end example
10875 10875
 @end itemize
10876 10876
 
10877
+@anchor{selectivecolor}
10877 10878
 @section selectivecolor
10878 10879
 
10879 10880
 Adjust cyan, magenta, yellow and black (CMYK) to certain ranges of colors (such
... ...
@@ -14289,6 +14290,40 @@ ffplay -f lavfi 'amovie=input.mp3, asplit [a][out1];
14289 14289
 @end example
14290 14290
 @end itemize
14291 14291
 
14292
+@section bench, abench
14293
+
14294
+Benchmark part of a filtergraph.
14295
+
14296
+The filter accepts the following options:
14297
+
14298
+@table @option
14299
+@item action
14300
+Start or stop a timer.
14301
+
14302
+Available values are:
14303
+@table @samp
14304
+@item start
14305
+Get the current time, set it as frame metadata (using the key
14306
+@code{lavfi.bench.start_time}), and forward the frame to the next filter.
14307
+
14308
+@item stop
14309
+Get the current time and fetch the @code{lavfi.bench.start_time} metadata from
14310
+the input frame metadata to get the time difference. Time difference, average,
14311
+maximum and minimum time (respectively @code{t}, @code{avg}, @code{max} and
14312
+@code{min}) are then printed. The timestamps are expressed in seconds.
14313
+@end table
14314
+@end table
14315
+
14316
+@subsection Examples
14317
+
14318
+@itemize
14319
+@item
14320
+Benchmark @ref{selectivecolor} filter:
14321
+@example
14322
+bench=start,selectivecolor=reds=-.2 .12 -.49,bench=stop
14323
+@end example
14324
+@end itemize
14325
+
14292 14326
 @section concat
14293 14327
 
14294 14328
 Concatenate audio and video streams, joining them together one after the
... ...
@@ -24,6 +24,7 @@ OBJS = allfilters.o                                                     \
24 24
        transform.o                                                      \
25 25
        video.o                                                          \
26 26
 
27
+OBJS-$(CONFIG_ABENCH_FILTER)                 += f_bench.o
27 28
 OBJS-$(CONFIG_ACOMPRESSOR_FILTER)            += af_sidechaincompress.o
28 29
 OBJS-$(CONFIG_ACROSSFADE_FILTER)             += af_afade.o
29 30
 OBJS-$(CONFIG_ADELAY_FILTER)                 += af_adelay.o
... ...
@@ -116,6 +117,7 @@ OBJS-$(CONFIG_ALPHAEXTRACT_FILTER)           += vf_extractplanes.o
116 116
 OBJS-$(CONFIG_ALPHAMERGE_FILTER)             += vf_alphamerge.o
117 117
 OBJS-$(CONFIG_ATADENOISE_FILTER)             += vf_atadenoise.o
118 118
 OBJS-$(CONFIG_BBOX_FILTER)                   += bbox.o vf_bbox.o
119
+OBJS-$(CONFIG_BENCH_FILTER)                  += f_bench.o
119 120
 OBJS-$(CONFIG_BLACKDETECT_FILTER)            += vf_blackdetect.o
120 121
 OBJS-$(CONFIG_BLACKFRAME_FILTER)             += vf_blackframe.o
121 122
 OBJS-$(CONFIG_BLEND_FILTER)                  += vf_blend.o dualinput.o framesync.o
... ...
@@ -45,6 +45,7 @@ void avfilter_register_all(void)
45 45
         return;
46 46
     initialized = 1;
47 47
 
48
+    REGISTER_FILTER(ABENCH,         abench,         af);
48 49
     REGISTER_FILTER(ACOMPRESSOR,    acompressor,    af);
49 50
     REGISTER_FILTER(ACROSSFADE,     acrossfade,     af);
50 51
     REGISTER_FILTER(ADELAY,         adelay,         af);
... ...
@@ -136,6 +137,7 @@ void avfilter_register_all(void)
136 136
     REGISTER_FILTER(ALPHAMERGE,     alphamerge,     vf);
137 137
     REGISTER_FILTER(ATADENOISE,     atadenoise,     vf);
138 138
     REGISTER_FILTER(ASS,            ass,            vf);
139
+    REGISTER_FILTER(BENCH,          bench,          vf);
139 140
     REGISTER_FILTER(BBOX,           bbox,           vf);
140 141
     REGISTER_FILTER(BLACKDETECT,    blackdetect,    vf);
141 142
     REGISTER_FILTER(BLACKFRAME,     blackframe,     vf);
142 143
new file mode 100644
... ...
@@ -0,0 +1,151 @@
0
+/*
1
+ * This file is part of FFmpeg.
2
+ *
3
+ * FFmpeg is free software; you can redistribute it and/or
4
+ * modify it under the terms of the GNU Lesser General Public
5
+ * License as published by the Free Software Foundation; either
6
+ * version 2.1 of the License, or (at your option) any later version.
7
+ *
8
+ * FFmpeg is distributed in the hope that it will be useful,
9
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
+ * Lesser General Public License for more details.
12
+ *
13
+ * You should have received a copy of the GNU Lesser General Public
14
+ * License along with FFmpeg; if not, write to the Free Software
15
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+ */
17
+
18
+#include "libavutil/opt.h"
19
+#include "libavutil/time.h"
20
+#include "avfilter.h"
21
+#include "formats.h"
22
+#include "internal.h"
23
+
24
+enum BenchAction {
25
+    ACTION_START,
26
+    ACTION_STOP,
27
+    NB_ACTION
28
+};
29
+
30
+typedef struct {
31
+    const AVClass *class;
32
+    int action;
33
+    int64_t max, min;
34
+    int64_t sum;
35
+    int n;
36
+} BenchContext;
37
+
38
+#define OFFSET(x) offsetof(BenchContext, x)
39
+#define DEFINE_OPTIONS(filt_name, FLAGS)                                                                                \
40
+static const AVOption filt_name##_options[] = {                                                                         \
41
+    { "action", "set action", OFFSET(action), AV_OPT_TYPE_INT, {.i64=ACTION_START}, 0, NB_ACTION-1, FLAGS, "action" },  \
42
+        { "start", "start timer",  0, AV_OPT_TYPE_CONST, {.i64=ACTION_START}, INT_MIN, INT_MAX, FLAGS, "action" },      \
43
+        { "stop",  "stop timer",   0, AV_OPT_TYPE_CONST, {.i64=ACTION_STOP},  INT_MIN, INT_MAX, FLAGS, "action" },      \
44
+    { NULL }                                                                                                            \
45
+}
46
+
47
+#define START_TIME_KEY "lavfi.bench.start_time"
48
+#define T2F(v) ((v) / 1000000.)
49
+
50
+static av_cold int init(AVFilterContext *ctx)
51
+{
52
+    BenchContext *s = ctx->priv;
53
+    s->min = INT64_MAX;
54
+    s->max = INT64_MIN;
55
+    return 0;
56
+}
57
+
58
+static int filter_frame(AVFilterLink *inlink, AVFrame *in)
59
+{
60
+    AVFilterContext *ctx = inlink->dst;
61
+    BenchContext *s = ctx->priv;
62
+    AVFilterLink *outlink = ctx->outputs[0];
63
+    const int64_t t = av_gettime();
64
+
65
+    if (t < 0)
66
+        return ff_filter_frame(outlink, in);
67
+
68
+    if (s->action == ACTION_START) {
69
+        av_dict_set_int(&in->metadata, START_TIME_KEY, t, 0);
70
+    } else if (s->action = ACTION_STOP) {
71
+        AVDictionaryEntry *e = av_dict_get(in->metadata, START_TIME_KEY, NULL, 0);
72
+        if (e) {
73
+            const int64_t start = strtoll(e->value, NULL, 0);
74
+            const int64_t diff = t - start;
75
+            s->sum += diff;
76
+            s->n++;
77
+            s->min = FFMIN(s->min, diff);
78
+            s->max = FFMAX(s->max, diff);
79
+            av_log(s, AV_LOG_INFO, "t:%f avg:%f max:%f min:%f\n",
80
+                   T2F(diff), T2F(s->sum / s->n), T2F(s->max), T2F(s->min));
81
+        }
82
+        av_dict_set(&in->metadata, START_TIME_KEY, NULL, 0);
83
+    }
84
+
85
+    return ff_filter_frame(outlink, in);
86
+}
87
+
88
+#if CONFIG_BENCH_FILTER
89
+DEFINE_OPTIONS(bench, AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM);
90
+AVFILTER_DEFINE_CLASS(bench);
91
+
92
+static const AVFilterPad bench_inputs[] = {
93
+    {
94
+        .name         = "default",
95
+        .type         = AVMEDIA_TYPE_VIDEO,
96
+        .filter_frame = filter_frame,
97
+    },
98
+    { NULL }
99
+};
100
+
101
+static const AVFilterPad bench_outputs[] = {
102
+    {
103
+        .name = "default",
104
+        .type = AVMEDIA_TYPE_VIDEO,
105
+    },
106
+    { NULL }
107
+};
108
+
109
+AVFilter ff_vf_bench = {
110
+    .name          = "bench",
111
+    .description   = NULL_IF_CONFIG_SMALL("Benchmark part of a filtergraph."),
112
+    .priv_size     = sizeof(BenchContext),
113
+    .init          = init,
114
+    .inputs        = bench_inputs,
115
+    .outputs       = bench_outputs,
116
+    .priv_class    = &bench_class,
117
+};
118
+#endif /* CONFIG_BENCH_FILTER */
119
+
120
+#if CONFIG_ABENCH_FILTER
121
+DEFINE_OPTIONS(abench, AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM);
122
+AVFILTER_DEFINE_CLASS(abench);
123
+
124
+static const AVFilterPad abench_inputs[] = {
125
+    {
126
+        .name         = "default",
127
+        .type         = AVMEDIA_TYPE_AUDIO,
128
+        .filter_frame = filter_frame,
129
+    },
130
+    { NULL }
131
+};
132
+
133
+static const AVFilterPad abench_outputs[] = {
134
+    {
135
+        .name = "default",
136
+        .type = AVMEDIA_TYPE_AUDIO,
137
+    },
138
+    { NULL }
139
+};
140
+
141
+AVFilter ff_af_abench = {
142
+    .name          = "abench",
143
+    .description   = NULL_IF_CONFIG_SMALL("Benchmark part of a filtergraph."),
144
+    .priv_size     = sizeof(BenchContext),
145
+    .init          = init,
146
+    .inputs        = abench_inputs,
147
+    .outputs       = abench_outputs,
148
+    .priv_class    = &abench_class,
149
+};
150
+#endif /* CONFIG_ABENCH_FILTER */
... ...
@@ -30,7 +30,7 @@
30 30
 #include "libavutil/version.h"
31 31
 
32 32
 #define LIBAVFILTER_VERSION_MAJOR   6
33
-#define LIBAVFILTER_VERSION_MINOR  37
33
+#define LIBAVFILTER_VERSION_MINOR  38
34 34
 #define LIBAVFILTER_VERSION_MICRO 100
35 35
 
36 36
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \