Browse code

lavfi: add perms and aperms filters.

Clément Bœsch authored on 2013/03/13 13:59:20
Showing 6 changed files
... ...
@@ -7,6 +7,7 @@ version <next>:
7 7
 - ffmpeg now fails when input options are used for output file
8 8
   or vice versa
9 9
 - support for Monkey's Audio versions from 3.93
10
+- perms and aperms filters
10 11
 
11 12
 
12 13
 version 1.2:
... ...
@@ -662,6 +662,7 @@ afade=t=out:ss=875:d=25
662 662
 @end example
663 663
 @end itemize
664 664
 
665
+@anchor{aformat}
665 666
 @section aformat
666 667
 
667 668
 Set output format constraints for the input audio. The framework will
... ...
@@ -3028,6 +3029,7 @@ framework.
3028 3028
 
3029 3029
 The filter does not take parameters.
3030 3030
 
3031
+@anchor{format}
3031 3032
 @section format
3032 3033
 
3033 3034
 Convert the input video to one of the specified pixel formats.
... ...
@@ -6085,6 +6087,43 @@ tools.
6085 6085
 
6086 6086
 Below is a description of the currently available multimedia filters.
6087 6087
 
6088
+@section aperms, perms
6089
+
6090
+Set read/write permissions for the output frames.
6091
+
6092
+These filters are mainly aimed at developers to test direct path in the
6093
+following filter in the filtergraph.
6094
+
6095
+The filters accept parameters as a list of @var{key}=@var{value} pairs,
6096
+separated by ":". If the key of the first options is omitted, the argument is
6097
+assumed to be the @var{mode}.
6098
+
6099
+A description of the accepted parameters follows.
6100
+
6101
+@table @option
6102
+@item mode
6103
+Select the permissions mode.
6104
+
6105
+It accepts the following values:
6106
+@table @samp
6107
+@item none
6108
+Do nothing. This is the default.
6109
+@item ro
6110
+Set all the output frames read-only.
6111
+@item rw
6112
+Set all the output frames directly writable.
6113
+@item toggle
6114
+Make the frame read-only if writable, and writable if read-only.
6115
+@item random
6116
+Set each output frame read-only or writable randomly.
6117
+@end table
6118
+@end table
6119
+
6120
+Note: in case of auto-inserted filter between the permission filter and the
6121
+following one, the permission might not be received as expected in that
6122
+following filter. Inserting a @ref{format} or @ref{aformat} filter before the
6123
+perms/aperms filter can avoid this problem.
6124
+
6088 6125
 @section aselect, select
6089 6126
 Select frames to pass in output.
6090 6127
 
... ...
@@ -56,6 +56,7 @@ OBJS-$(CONFIG_AMERGE_FILTER)                 += af_amerge.o
56 56
 OBJS-$(CONFIG_AMIX_FILTER)                   += af_amix.o
57 57
 OBJS-$(CONFIG_ANULL_FILTER)                  += af_anull.o
58 58
 OBJS-$(CONFIG_APAD_FILTER)                   += af_apad.o
59
+OBJS-$(CONFIG_APERMS_FILTER)                 += f_perms.o
59 60
 OBJS-$(CONFIG_ARESAMPLE_FILTER)              += af_aresample.o
60 61
 OBJS-$(CONFIG_ASELECT_FILTER)                += f_select.o
61 62
 OBJS-$(CONFIG_ASENDCMD_FILTER)               += f_sendcmd.o
... ...
@@ -139,6 +140,7 @@ OBJS-$(CONFIG_NULL_FILTER)                   += vf_null.o
139 139
 OBJS-$(CONFIG_OCV_FILTER)                    += vf_libopencv.o
140 140
 OBJS-$(CONFIG_OVERLAY_FILTER)                += vf_overlay.o
141 141
 OBJS-$(CONFIG_PAD_FILTER)                    += vf_pad.o
142
+OBJS-$(CONFIG_PERMS_FILTER)                  += f_perms.o
142 143
 OBJS-$(CONFIG_PIXDESCTEST_FILTER)            += vf_pixdesctest.o
143 144
 OBJS-$(CONFIG_PP_FILTER)                     += vf_pp.o
144 145
 OBJS-$(CONFIG_REMOVELOGO_FILTER)             += bbox.o lswsutils.o lavfutils.o vf_removelogo.o
... ...
@@ -52,6 +52,7 @@ void avfilter_register_all(void)
52 52
     REGISTER_FILTER(AMIX,           amix,           af);
53 53
     REGISTER_FILTER(ANULL,          anull,          af);
54 54
     REGISTER_FILTER(APAD,           apad,           af);
55
+    REGISTER_FILTER(APERMS,         aperms,         af);
55 56
     REGISTER_FILTER(ARESAMPLE,      aresample,      af);
56 57
     REGISTER_FILTER(ASELECT,        aselect,        af);
57 58
     REGISTER_FILTER(ASENDCMD,       asendcmd,       af);
... ...
@@ -135,6 +136,7 @@ void avfilter_register_all(void)
135 135
     REGISTER_FILTER(OCV,            ocv,            vf);
136 136
     REGISTER_FILTER(OVERLAY,        overlay,        vf);
137 137
     REGISTER_FILTER(PAD,            pad,            vf);
138
+    REGISTER_FILTER(PERMS,          perms,          vf);
138 139
     REGISTER_FILTER(PIXDESCTEST,    pixdesctest,    vf);
139 140
     REGISTER_FILTER(PP,             pp,             vf);
140 141
     REGISTER_FILTER(REMOVELOGO,     removelogo,     vf);
141 142
new file mode 100644
... ...
@@ -0,0 +1,187 @@
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/lfg.h"
19
+#include "libavutil/opt.h"
20
+#include "libavutil/random_seed.h"
21
+#include "audio.h"
22
+#include "video.h"
23
+
24
+enum mode {
25
+    MODE_NONE,
26
+    MODE_RO,
27
+    MODE_RW,
28
+    MODE_TOGGLE,
29
+    MODE_RANDOM,
30
+    NB_MODES
31
+};
32
+
33
+typedef struct {
34
+    const AVClass *class;
35
+    AVLFG lfg;
36
+    enum mode mode;
37
+} PermsContext;
38
+
39
+#define OFFSET(x) offsetof(PermsContext, x)
40
+#define FLAGS AV_OPT_FLAG_FILTERING_PARAM
41
+
42
+static const AVOption options[] = {
43
+    { "mode", "select permissions mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = MODE_NONE}, MODE_NONE, NB_MODES-1, FLAGS, "mode" },
44
+        { "none",   "do nothing",                       0, AV_OPT_TYPE_CONST, {.i64 = MODE_NONE},       INT_MIN, INT_MAX, FLAGS, "mode" },
45
+        { "ro",     "set all output frames read-only",  0, AV_OPT_TYPE_CONST, {.i64 = MODE_RO},         INT_MIN, INT_MAX, FLAGS, "mode" },
46
+        { "rw",     "set all output frames writable",   0, AV_OPT_TYPE_CONST, {.i64 = MODE_RW},         INT_MIN, INT_MAX, FLAGS, "mode" },
47
+        { "toggle", "switch permissions",               0, AV_OPT_TYPE_CONST, {.i64 = MODE_TOGGLE},     INT_MIN, INT_MAX, FLAGS, "mode" },
48
+        { "random", "set permissions randomly",         0, AV_OPT_TYPE_CONST, {.i64 = MODE_RANDOM},     INT_MIN, INT_MAX, FLAGS, "mode" },
49
+    { NULL }
50
+};
51
+
52
+static av_cold int init(AVFilterContext *ctx, const char *args, const AVClass *class)
53
+{
54
+    int ret;
55
+    PermsContext *perms = ctx->priv;
56
+    static const char *shorthand[] = { "mode", NULL };
57
+
58
+    perms->class = class;
59
+    av_opt_set_defaults(perms);
60
+
61
+    if ((ret = av_opt_set_from_string(perms, args, shorthand, "=", ":")) < 0)
62
+        return ret;
63
+
64
+    // TODO: add a seed option
65
+    if (perms->mode == MODE_RANDOM)
66
+        av_lfg_init(&perms->lfg, av_get_random_seed());
67
+
68
+    av_opt_free(perms);
69
+    return 0;
70
+}
71
+
72
+enum perm                        {  RO,   RW  };
73
+static const char *perm_str[2] = { "RO", "RW" };
74
+
75
+static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
76
+{
77
+    int ret;
78
+    AVFilterContext *ctx = inlink->dst;
79
+    PermsContext *perms = ctx->priv;
80
+    AVFrame *out = frame;
81
+    enum perm in_perm = av_frame_is_writable(frame) ? RW : RO;
82
+    enum perm out_perm;
83
+
84
+    switch (perms->mode) {
85
+    case MODE_TOGGLE:   out_perm = in_perm == RO ? RW : RO;                 break;
86
+    case MODE_RANDOM:   out_perm = av_lfg_get(&perms->lfg) & 1 ? RW : RO;   break;
87
+    case MODE_RO:       out_perm = RO;                                      break;
88
+    case MODE_RW:       out_perm = RW;                                      break;
89
+    default:            out_perm = in_perm;                                 break;
90
+    }
91
+
92
+    av_log(ctx, AV_LOG_VERBOSE, "%s -> %s%s\n",
93
+           perm_str[in_perm], perm_str[out_perm],
94
+           in_perm == out_perm ? " (no-op)" : "");
95
+
96
+    if (in_perm == RO && out_perm == RW) {
97
+        if ((ret = av_frame_make_writable(frame)) < 0)
98
+            return ret;
99
+    } else if (in_perm == RW && out_perm == RO) {
100
+        out = av_frame_clone(frame);
101
+        if (!out)
102
+            return AVERROR(ENOMEM);
103
+    }
104
+
105
+    ret = ff_filter_frame(ctx->outputs[0], out);
106
+
107
+    if (in_perm == RW && out_perm == RO)
108
+        av_frame_free(&frame);
109
+    return ret;
110
+}
111
+
112
+#if CONFIG_APERMS_FILTER
113
+
114
+#define aperms_options options
115
+AVFILTER_DEFINE_CLASS(aperms);
116
+
117
+static av_cold int aperms_init(AVFilterContext *ctx, const char *args)
118
+{
119
+    return init(ctx, args, &aperms_class);
120
+}
121
+
122
+static const AVFilterPad aperms_inputs[] = {
123
+    {
124
+        .name         = "default",
125
+        .type         = AVMEDIA_TYPE_AUDIO,
126
+        .filter_frame = filter_frame,
127
+    },
128
+    { NULL }
129
+};
130
+
131
+static const AVFilterPad aperms_outputs[] = {
132
+    {
133
+        .name = "default",
134
+        .type = AVMEDIA_TYPE_AUDIO,
135
+    },
136
+    { NULL }
137
+};
138
+
139
+AVFilter avfilter_af_aperms = {
140
+    .name        = "aperms",
141
+    .description = NULL_IF_CONFIG_SMALL("Set permissions for the output audio frame."),
142
+    .init        = aperms_init,
143
+    .priv_size   = sizeof(PermsContext),
144
+    .inputs      = aperms_inputs,
145
+    .outputs     = aperms_outputs,
146
+    .priv_class  = &aperms_class,
147
+};
148
+#endif /* CONFIG_APERMS_FILTER */
149
+
150
+#if CONFIG_PERMS_FILTER
151
+
152
+#define perms_options options
153
+AVFILTER_DEFINE_CLASS(perms);
154
+
155
+static av_cold int perms_init(AVFilterContext *ctx, const char *args)
156
+{
157
+    return init(ctx, args, &perms_class);
158
+}
159
+
160
+static const AVFilterPad perms_inputs[] = {
161
+    {
162
+        .name         = "default",
163
+        .type         = AVMEDIA_TYPE_VIDEO,
164
+        .filter_frame = filter_frame,
165
+    },
166
+    { NULL }
167
+};
168
+
169
+static const AVFilterPad perms_outputs[] = {
170
+    {
171
+        .name = "default",
172
+        .type = AVMEDIA_TYPE_VIDEO,
173
+    },
174
+    { NULL }
175
+};
176
+
177
+AVFilter avfilter_vf_perms = {
178
+    .name        = "perms",
179
+    .description = NULL_IF_CONFIG_SMALL("Set permissions for the output video frame."),
180
+    .init        = perms_init,
181
+    .priv_size   = sizeof(PermsContext),
182
+    .inputs      = perms_inputs,
183
+    .outputs     = perms_outputs,
184
+    .priv_class  = &perms_class,
185
+};
186
+#endif /* CONFIG_PERMS_FILTER */
... ...
@@ -29,8 +29,8 @@
29 29
 #include "libavutil/avutil.h"
30 30
 
31 31
 #define LIBAVFILTER_VERSION_MAJOR  3
32
-#define LIBAVFILTER_VERSION_MINOR  45
33
-#define LIBAVFILTER_VERSION_MICRO 104
32
+#define LIBAVFILTER_VERSION_MINOR  46
33
+#define LIBAVFILTER_VERSION_MICRO 100
34 34
 
35 35
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
36 36
                                                LIBAVFILTER_VERSION_MINOR, \