Browse code

avfilter: add areverse filter

Signed-off-by: Paul B Mahol <onemda@gmail.com>

Paul B Mahol authored on 2015/07/21 19:43:04
Showing 6 changed files
... ...
@@ -18,7 +18,7 @@ version <next>:
18 18
 - libkvazaar HEVC encoder
19 19
 - erosion, dilation, deflate and inflate video filters
20 20
 - Dynamic Audio Normalizer as dynaudnorm filter
21
-- Reverse filter
21
+- Reverse video and areverse audio filter
22 22
 - Random filter
23 23
 - deband filter
24 24
 - AAC fixed-point decoding
... ...
@@ -8489,7 +8489,7 @@ pixels will slow things down on a large logo.
8489 8489
 This filter uses the repeat_field flag from the Video ES headers and hard repeats
8490 8490
 fields based on its value.
8491 8491
 
8492
-@section reverse
8492
+@section reverse, areverse
8493 8493
 
8494 8494
 Reverse a clip.
8495 8495
 
... ...
@@ -43,6 +43,7 @@ OBJS-$(CONFIG_APAD_FILTER)                   += af_apad.o
43 43
 OBJS-$(CONFIG_APERMS_FILTER)                 += f_perms.o
44 44
 OBJS-$(CONFIG_APHASER_FILTER)                += af_aphaser.o generate_wave_table.o
45 45
 OBJS-$(CONFIG_ARESAMPLE_FILTER)              += af_aresample.o
46
+OBJS-$(CONFIG_AREVERSE_FILTER)               += vf_reverse.o
46 47
 OBJS-$(CONFIG_ASELECT_FILTER)                += f_select.o
47 48
 OBJS-$(CONFIG_ASENDCMD_FILTER)               += f_sendcmd.o
48 49
 OBJS-$(CONFIG_ASETNSAMPLES_FILTER)           += af_asetnsamples.o
... ...
@@ -59,6 +59,7 @@ void avfilter_register_all(void)
59 59
     REGISTER_FILTER(APERMS,         aperms,         af);
60 60
     REGISTER_FILTER(APHASER,        aphaser,        af);
61 61
     REGISTER_FILTER(ARESAMPLE,      aresample,      af);
62
+    REGISTER_FILTER(AREVERSE,       areverse,       af);
62 63
     REGISTER_FILTER(ASELECT,        aselect,        af);
63 64
     REGISTER_FILTER(ASENDCMD,       asendcmd,       af);
64 65
     REGISTER_FILTER(ASETNSAMPLES,   asetnsamples,   af);
... ...
@@ -30,7 +30,7 @@
30 30
 #include "libavutil/version.h"
31 31
 
32 32
 #define LIBAVFILTER_VERSION_MAJOR  5
33
-#define LIBAVFILTER_VERSION_MINOR  27
33
+#define LIBAVFILTER_VERSION_MINOR  28
34 34
 #define LIBAVFILTER_VERSION_MICRO 100
35 35
 
36 36
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
... ...
@@ -95,6 +95,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
95 95
     return 0;
96 96
 }
97 97
 
98
+#if CONFIG_REVERSE_FILTER
99
+
98 100
 static int request_frame(AVFilterLink *outlink)
99 101
 {
100 102
     AVFilterContext *ctx = outlink->src;
... ...
@@ -141,3 +143,117 @@ AVFilter ff_vf_reverse = {
141 141
     .inputs      = reverse_inputs,
142 142
     .outputs     = reverse_outputs,
143 143
 };
144
+
145
+#endif /* CONFIG_REVERSE_FILTER */
146
+
147
+#if CONFIG_AREVERSE_FILTER
148
+
149
+static int query_formats(AVFilterContext *ctx)
150
+{
151
+    AVFilterFormats *formats;
152
+    AVFilterChannelLayouts *layouts;
153
+    int ret;
154
+
155
+    layouts = ff_all_channel_layouts();
156
+    if (!layouts)
157
+        return AVERROR(ENOMEM);
158
+    ret = ff_set_common_channel_layouts(ctx, layouts);
159
+    if (ret < 0)
160
+        return ret;
161
+
162
+    ret = ff_set_common_formats(ctx, ff_planar_sample_fmts());
163
+    if (ret < 0)
164
+        return ret;
165
+
166
+    formats = ff_all_samplerates();
167
+    if (!formats)
168
+        return AVERROR(ENOMEM);
169
+    return ff_set_common_samplerates(ctx, formats);
170
+}
171
+
172
+static int areverse_request_frame(AVFilterLink *outlink)
173
+{
174
+    AVFilterContext *ctx = outlink->src;
175
+    ReverseContext *s = ctx->priv;
176
+    int ret, p, i, j;
177
+
178
+    ret = ff_request_frame(ctx->inputs[0]);
179
+
180
+    if (ret == AVERROR_EOF && s->nb_frames > 0) {
181
+        AVFrame *out = s->frames[s->nb_frames - 1];
182
+        out->pts     = s->pts[s->flush_idx++];
183
+
184
+        for (p = 0; p < outlink->channels; p++) {
185
+            switch (outlink->format) {
186
+            case AV_SAMPLE_FMT_U8P: {
187
+                uint8_t *dst = (uint8_t *)out->extended_data[p];
188
+                for (i = 0, j = out->nb_samples - 1; i < j; i++, j--)
189
+                    FFSWAP(uint8_t, dst[i], dst[j]);
190
+            }
191
+                break;
192
+            case AV_SAMPLE_FMT_S16P: {
193
+                int16_t *dst = (int16_t *)out->extended_data[p];
194
+                for (i = 0, j = out->nb_samples - 1; i < j; i++, j--)
195
+                    FFSWAP(int16_t, dst[i], dst[j]);
196
+            }
197
+                break;
198
+            case AV_SAMPLE_FMT_S32P: {
199
+                int32_t *dst = (int32_t *)out->extended_data[p];
200
+                for (i = 0, j = out->nb_samples - 1; i < j; i++, j--)
201
+                    FFSWAP(int32_t, dst[i], dst[j]);
202
+            }
203
+                break;
204
+            case AV_SAMPLE_FMT_FLTP: {
205
+                float *dst = (float *)out->extended_data[p];
206
+                for (i = 0, j = out->nb_samples - 1; i < j; i++, j--)
207
+                    FFSWAP(float, dst[i], dst[j]);
208
+            }
209
+                break;
210
+            case AV_SAMPLE_FMT_DBLP: {
211
+                double *dst = (double *)out->extended_data[p];
212
+                for (i = 0, j = out->nb_samples - 1; i < j; i++, j--)
213
+                    FFSWAP(double, dst[i], dst[j]);
214
+            }
215
+                break;
216
+            }
217
+        }
218
+
219
+        ret = ff_filter_frame(outlink, out);
220
+        s->nb_frames--;
221
+    }
222
+
223
+    return ret;
224
+}
225
+
226
+static const AVFilterPad areverse_inputs[] = {
227
+    {
228
+        .name           = "default",
229
+        .type           = AVMEDIA_TYPE_AUDIO,
230
+        .filter_frame   = filter_frame,
231
+        .needs_writable = 1,
232
+    },
233
+    { NULL }
234
+};
235
+
236
+static const AVFilterPad areverse_outputs[] = {
237
+    {
238
+        .name          = "default",
239
+        .type          = AVMEDIA_TYPE_AUDIO,
240
+        .request_frame = areverse_request_frame,
241
+        .config_props  = config_output,
242
+    },
243
+    { NULL }
244
+};
245
+
246
+AVFilter ff_af_areverse = {
247
+    .name          = "areverse",
248
+    .description   = NULL_IF_CONFIG_SMALL("Reverse an audio clip."),
249
+    .query_formats = query_formats,
250
+    .priv_size     = sizeof(ReverseContext),
251
+    .init          = init,
252
+    .uninit        = uninit,
253
+    .inputs        = areverse_inputs,
254
+    .outputs       = areverse_outputs,
255
+};
256
+
257
+#endif /* CONFIG_AREVERSE_FILTER */