yading@10
|
1 /*
|
yading@10
|
2 * Copyright (c) 2013 Clément Bœsch
|
yading@10
|
3 *
|
yading@10
|
4 * This file is part of FFmpeg.
|
yading@10
|
5 *
|
yading@10
|
6 * FFmpeg is free software; you can redistribute it and/or
|
yading@10
|
7 * modify it under the terms of the GNU Lesser General Public
|
yading@10
|
8 * License as published by the Free Software Foundation; either
|
yading@10
|
9 * version 2.1 of the License, or (at your option) any later version.
|
yading@10
|
10 *
|
yading@10
|
11 * FFmpeg is distributed in the hope that it will be useful,
|
yading@10
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@10
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@10
|
14 * Lesser General Public License for more details.
|
yading@10
|
15 *
|
yading@10
|
16 * You should have received a copy of the GNU Lesser General Public
|
yading@10
|
17 * License along with FFmpeg; if not, write to the Free Software
|
yading@10
|
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@10
|
19 */
|
yading@10
|
20
|
yading@10
|
21 #include "libavutil/lfg.h"
|
yading@10
|
22 #include "libavutil/opt.h"
|
yading@10
|
23 #include "libavutil/random_seed.h"
|
yading@10
|
24 #include "audio.h"
|
yading@10
|
25 #include "video.h"
|
yading@10
|
26
|
yading@10
|
27 enum mode {
|
yading@10
|
28 MODE_NONE,
|
yading@10
|
29 MODE_RO,
|
yading@10
|
30 MODE_RW,
|
yading@10
|
31 MODE_TOGGLE,
|
yading@10
|
32 MODE_RANDOM,
|
yading@10
|
33 NB_MODES
|
yading@10
|
34 };
|
yading@10
|
35
|
yading@10
|
36 typedef struct {
|
yading@10
|
37 const AVClass *class;
|
yading@10
|
38 AVLFG lfg;
|
yading@10
|
39 int64_t random_seed;
|
yading@10
|
40 enum mode mode;
|
yading@10
|
41 } PermsContext;
|
yading@10
|
42
|
yading@10
|
43 #define OFFSET(x) offsetof(PermsContext, x)
|
yading@10
|
44 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_VIDEO_PARAM
|
yading@10
|
45
|
yading@10
|
46 static const AVOption options[] = {
|
yading@10
|
47 { "mode", "select permissions mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = MODE_NONE}, MODE_NONE, NB_MODES-1, FLAGS, "mode" },
|
yading@10
|
48 { "none", "do nothing", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_NONE}, INT_MIN, INT_MAX, FLAGS, "mode" },
|
yading@10
|
49 { "ro", "set all output frames read-only", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_RO}, INT_MIN, INT_MAX, FLAGS, "mode" },
|
yading@10
|
50 { "rw", "set all output frames writable", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_RW}, INT_MIN, INT_MAX, FLAGS, "mode" },
|
yading@10
|
51 { "toggle", "switch permissions", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_TOGGLE}, INT_MIN, INT_MAX, FLAGS, "mode" },
|
yading@10
|
52 { "random", "set permissions randomly", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_RANDOM}, INT_MIN, INT_MAX, FLAGS, "mode" },
|
yading@10
|
53 { "seed", "set the seed for the random mode", OFFSET(random_seed), AV_OPT_TYPE_INT64, {.i64 = -1}, -1, UINT32_MAX, FLAGS },
|
yading@10
|
54 { NULL }
|
yading@10
|
55 };
|
yading@10
|
56
|
yading@10
|
57 static av_cold int init(AVFilterContext *ctx)
|
yading@10
|
58 {
|
yading@10
|
59 PermsContext *perms = ctx->priv;
|
yading@10
|
60
|
yading@10
|
61 if (perms->mode == MODE_RANDOM) {
|
yading@10
|
62 uint32_t seed;
|
yading@10
|
63
|
yading@10
|
64 if (perms->random_seed == -1)
|
yading@10
|
65 perms->random_seed = av_get_random_seed();
|
yading@10
|
66 seed = perms->random_seed;
|
yading@10
|
67 av_log(ctx, AV_LOG_INFO, "random seed: 0x%08x\n", seed);
|
yading@10
|
68 av_lfg_init(&perms->lfg, seed);
|
yading@10
|
69 }
|
yading@10
|
70
|
yading@10
|
71 return 0;
|
yading@10
|
72 }
|
yading@10
|
73
|
yading@10
|
74 enum perm { RO, RW };
|
yading@10
|
75 static const char *perm_str[2] = { "RO", "RW" };
|
yading@10
|
76
|
yading@10
|
77 static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
|
yading@10
|
78 {
|
yading@10
|
79 int ret;
|
yading@10
|
80 AVFilterContext *ctx = inlink->dst;
|
yading@10
|
81 PermsContext *perms = ctx->priv;
|
yading@10
|
82 AVFrame *out = frame;
|
yading@10
|
83 enum perm in_perm = av_frame_is_writable(frame) ? RW : RO;
|
yading@10
|
84 enum perm out_perm;
|
yading@10
|
85
|
yading@10
|
86 switch (perms->mode) {
|
yading@10
|
87 case MODE_TOGGLE: out_perm = in_perm == RO ? RW : RO; break;
|
yading@10
|
88 case MODE_RANDOM: out_perm = av_lfg_get(&perms->lfg) & 1 ? RW : RO; break;
|
yading@10
|
89 case MODE_RO: out_perm = RO; break;
|
yading@10
|
90 case MODE_RW: out_perm = RW; break;
|
yading@10
|
91 default: out_perm = in_perm; break;
|
yading@10
|
92 }
|
yading@10
|
93
|
yading@10
|
94 av_log(ctx, AV_LOG_VERBOSE, "%s -> %s%s\n",
|
yading@10
|
95 perm_str[in_perm], perm_str[out_perm],
|
yading@10
|
96 in_perm == out_perm ? " (no-op)" : "");
|
yading@10
|
97
|
yading@10
|
98 if (in_perm == RO && out_perm == RW) {
|
yading@10
|
99 if ((ret = av_frame_make_writable(frame)) < 0)
|
yading@10
|
100 return ret;
|
yading@10
|
101 } else if (in_perm == RW && out_perm == RO) {
|
yading@10
|
102 out = av_frame_clone(frame);
|
yading@10
|
103 if (!out)
|
yading@10
|
104 return AVERROR(ENOMEM);
|
yading@10
|
105 }
|
yading@10
|
106
|
yading@10
|
107 ret = ff_filter_frame(ctx->outputs[0], out);
|
yading@10
|
108
|
yading@10
|
109 if (in_perm == RW && out_perm == RO)
|
yading@10
|
110 av_frame_free(&frame);
|
yading@10
|
111 return ret;
|
yading@10
|
112 }
|
yading@10
|
113
|
yading@10
|
114 #if CONFIG_APERMS_FILTER
|
yading@10
|
115
|
yading@10
|
116 #define aperms_options options
|
yading@10
|
117 AVFILTER_DEFINE_CLASS(aperms);
|
yading@10
|
118
|
yading@10
|
119 static const AVFilterPad aperms_inputs[] = {
|
yading@10
|
120 {
|
yading@10
|
121 .name = "default",
|
yading@10
|
122 .type = AVMEDIA_TYPE_AUDIO,
|
yading@10
|
123 .filter_frame = filter_frame,
|
yading@10
|
124 },
|
yading@10
|
125 { NULL }
|
yading@10
|
126 };
|
yading@10
|
127
|
yading@10
|
128 static const AVFilterPad aperms_outputs[] = {
|
yading@10
|
129 {
|
yading@10
|
130 .name = "default",
|
yading@10
|
131 .type = AVMEDIA_TYPE_AUDIO,
|
yading@10
|
132 },
|
yading@10
|
133 { NULL }
|
yading@10
|
134 };
|
yading@10
|
135
|
yading@10
|
136 AVFilter avfilter_af_aperms = {
|
yading@10
|
137 .name = "aperms",
|
yading@10
|
138 .description = NULL_IF_CONFIG_SMALL("Set permissions for the output audio frame."),
|
yading@10
|
139 .init = init,
|
yading@10
|
140 .priv_size = sizeof(PermsContext),
|
yading@10
|
141 .inputs = aperms_inputs,
|
yading@10
|
142 .outputs = aperms_outputs,
|
yading@10
|
143 .priv_class = &aperms_class,
|
yading@10
|
144 };
|
yading@10
|
145 #endif /* CONFIG_APERMS_FILTER */
|
yading@10
|
146
|
yading@10
|
147 #if CONFIG_PERMS_FILTER
|
yading@10
|
148
|
yading@10
|
149 #define perms_options options
|
yading@10
|
150 AVFILTER_DEFINE_CLASS(perms);
|
yading@10
|
151
|
yading@10
|
152 static const AVFilterPad perms_inputs[] = {
|
yading@10
|
153 {
|
yading@10
|
154 .name = "default",
|
yading@10
|
155 .type = AVMEDIA_TYPE_VIDEO,
|
yading@10
|
156 .filter_frame = filter_frame,
|
yading@10
|
157 },
|
yading@10
|
158 { NULL }
|
yading@10
|
159 };
|
yading@10
|
160
|
yading@10
|
161 static const AVFilterPad perms_outputs[] = {
|
yading@10
|
162 {
|
yading@10
|
163 .name = "default",
|
yading@10
|
164 .type = AVMEDIA_TYPE_VIDEO,
|
yading@10
|
165 },
|
yading@10
|
166 { NULL }
|
yading@10
|
167 };
|
yading@10
|
168
|
yading@10
|
169 AVFilter avfilter_vf_perms = {
|
yading@10
|
170 .name = "perms",
|
yading@10
|
171 .description = NULL_IF_CONFIG_SMALL("Set permissions for the output video frame."),
|
yading@10
|
172 .init = init,
|
yading@10
|
173 .priv_size = sizeof(PermsContext),
|
yading@10
|
174 .inputs = perms_inputs,
|
yading@10
|
175 .outputs = perms_outputs,
|
yading@10
|
176 .priv_class = &perms_class,
|
yading@10
|
177 };
|
yading@10
|
178 #endif /* CONFIG_PERMS_FILTER */
|