1 /*
2  * Copyright (c) 2015 Derek Buitenhuis
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "config_components.h"
22 
23 #include "libavutil/opt.h"
24 #include "avfilter.h"
25 #include "formats.h"
26 #include "internal.h"
27 #include "video.h"
28 
29 #define DEFAULT_LENGTH 300
30 
31 typedef struct ReverseContext {
32     int nb_frames;
33     AVFrame **frames;
34     unsigned int frames_size;
35     unsigned int pts_size;
36     int64_t *pts;
37     int flush_idx;
38     int64_t nb_samples;
39 } ReverseContext;
40 
init(AVFilterContext *ctx)41 static av_cold int init(AVFilterContext *ctx)
42 {
43     ReverseContext *s = ctx->priv;
44 
45     s->pts = av_fast_realloc(NULL, &s->pts_size,
46                              DEFAULT_LENGTH * sizeof(*(s->pts)));
47     if (!s->pts)
48         return AVERROR(ENOMEM);
49 
50     s->frames = av_fast_realloc(NULL, &s->frames_size,
51                                 DEFAULT_LENGTH * sizeof(*(s->frames)));
52     if (!s->frames) {
53         av_freep(&s->pts);
54         return AVERROR(ENOMEM);
55     }
56 
57     return 0;
58 }
59 
uninit(AVFilterContext *ctx)60 static av_cold void uninit(AVFilterContext *ctx)
61 {
62     ReverseContext *s = ctx->priv;
63 
64     while (s->nb_frames > 0) {
65         av_frame_free(&s->frames[s->nb_frames - 1]);
66         s->nb_frames--;
67     }
68 
69     av_freep(&s->pts);
70     av_freep(&s->frames);
71 }
72 
filter_frame(AVFilterLink *inlink, AVFrame *in)73 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
74 {
75     AVFilterContext *ctx = inlink->dst;
76     ReverseContext *s    = ctx->priv;
77     void *ptr;
78 
79     if (s->nb_frames + 1 > s->pts_size / sizeof(*(s->pts))) {
80         ptr = av_fast_realloc(s->pts, &s->pts_size, s->pts_size * 2);
81         if (!ptr)
82             return AVERROR(ENOMEM);
83         s->pts = ptr;
84     }
85 
86     if (s->nb_frames + 1 > s->frames_size / sizeof(*(s->frames))) {
87         ptr = av_fast_realloc(s->frames, &s->frames_size, s->frames_size * 2);
88         if (!ptr)
89             return AVERROR(ENOMEM);
90         s->frames = ptr;
91     }
92 
93     s->frames[s->nb_frames] = in;
94     s->pts[s->nb_frames]    = in->pts;
95     s->nb_frames++;
96 
97     return 0;
98 }
99 
100 #if CONFIG_REVERSE_FILTER
101 
request_frame(AVFilterLink *outlink)102 static int request_frame(AVFilterLink *outlink)
103 {
104     AVFilterContext *ctx = outlink->src;
105     ReverseContext *s = ctx->priv;
106     int ret;
107 
108     ret = ff_request_frame(ctx->inputs[0]);
109 
110     if (ret == AVERROR_EOF && s->nb_frames > 0) {
111         AVFrame *out = s->frames[s->nb_frames - 1];
112         out->pts     = s->pts[s->flush_idx++];
113         ret          = ff_filter_frame(outlink, out);
114         s->frames[s->nb_frames - 1] = NULL;
115         s->nb_frames--;
116     }
117 
118     return ret;
119 }
120 
121 static const AVFilterPad reverse_inputs[] = {
122     {
123         .name         = "default",
124         .type         = AVMEDIA_TYPE_VIDEO,
125         .filter_frame = filter_frame,
126     },
127 };
128 
129 static const AVFilterPad reverse_outputs[] = {
130     {
131         .name          = "default",
132         .type          = AVMEDIA_TYPE_VIDEO,
133         .request_frame = request_frame,
134     },
135 };
136 
137 const AVFilter ff_vf_reverse = {
138     .name        = "reverse",
139     .description = NULL_IF_CONFIG_SMALL("Reverse a clip."),
140     .priv_size   = sizeof(ReverseContext),
141     .init        = init,
142     .uninit      = uninit,
143     FILTER_INPUTS(reverse_inputs),
144     FILTER_OUTPUTS(reverse_outputs),
145 };
146 
147 #endif /* CONFIG_REVERSE_FILTER */
148 
149 #if CONFIG_AREVERSE_FILTER
150 
reverse_samples_planar(AVFrame *out)151 static void reverse_samples_planar(AVFrame *out)
152 {
153     for (int p = 0; p < out->ch_layout.nb_channels; p++) {
154         switch (out->format) {
155         case AV_SAMPLE_FMT_U8P: {
156             uint8_t *dst = (uint8_t *)out->extended_data[p];
157             for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
158                 FFSWAP(uint8_t, dst[i], dst[j]);
159         }
160             break;
161         case AV_SAMPLE_FMT_S16P: {
162             int16_t *dst = (int16_t *)out->extended_data[p];
163             for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
164                 FFSWAP(int16_t, dst[i], dst[j]);
165         }
166             break;
167         case AV_SAMPLE_FMT_S32P: {
168             int32_t *dst = (int32_t *)out->extended_data[p];
169             for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
170                 FFSWAP(int32_t, dst[i], dst[j]);
171         }
172             break;
173         case AV_SAMPLE_FMT_S64P: {
174             int64_t *dst = (int64_t *)out->extended_data[p];
175             for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
176                 FFSWAP(int64_t, dst[i], dst[j]);
177         }
178             break;
179         case AV_SAMPLE_FMT_FLTP: {
180             float *dst = (float *)out->extended_data[p];
181             for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
182                 FFSWAP(float, dst[i], dst[j]);
183         }
184             break;
185         case AV_SAMPLE_FMT_DBLP: {
186             double *dst = (double *)out->extended_data[p];
187             for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
188                 FFSWAP(double, dst[i], dst[j]);
189         }
190             break;
191         }
192     }
193 }
194 
reverse_samples_packed(AVFrame *out)195 static void reverse_samples_packed(AVFrame *out)
196 {
197     const int channels = out->ch_layout.nb_channels;
198 
199     switch (out->format) {
200     case AV_SAMPLE_FMT_U8: {
201         uint8_t *dst = (uint8_t *)out->extended_data[0];
202         for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
203             for (int p = 0; p < channels; p++)
204                 FFSWAP(uint8_t, dst[i * channels + p], dst[j * channels + p]);
205     }
206         break;
207     case AV_SAMPLE_FMT_S16: {
208         int16_t *dst = (int16_t *)out->extended_data[0];
209         for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
210             for (int p = 0; p < channels; p++)
211                 FFSWAP(int16_t, dst[i * channels + p], dst[j * channels + p]);
212     }
213         break;
214     case AV_SAMPLE_FMT_S32: {
215         int32_t *dst = (int32_t *)out->extended_data[0];
216         for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
217             for (int p = 0; p < channels; p++)
218                 FFSWAP(int32_t, dst[i * channels + p], dst[j * channels + p]);
219     }
220         break;
221     case AV_SAMPLE_FMT_S64: {
222         int64_t *dst = (int64_t *)out->extended_data[0];
223         for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
224             for (int p = 0; p < channels; p++)
225                 FFSWAP(int64_t, dst[i * channels + p], dst[j * channels + p]);
226     }
227         break;
228     case AV_SAMPLE_FMT_FLT: {
229         float *dst = (float *)out->extended_data[0];
230         for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
231             for (int p = 0; p < channels; p++)
232                 FFSWAP(float, dst[i * channels + p], dst[j * channels + p]);
233     }
234         break;
235     case AV_SAMPLE_FMT_DBL: {
236         double *dst = (double *)out->extended_data[0];
237         for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
238             for (int p = 0; p < channels; p++)
239                 FFSWAP(double, dst[i * channels + p], dst[j * channels + p]);
240     }
241         break;
242     }
243 }
244 
areverse_request_frame(AVFilterLink *outlink)245 static int areverse_request_frame(AVFilterLink *outlink)
246 {
247     AVFilterContext *ctx = outlink->src;
248     ReverseContext *s = ctx->priv;
249     int ret;
250 
251     ret = ff_request_frame(ctx->inputs[0]);
252 
253     if (ret == AVERROR_EOF && s->nb_frames > 0) {
254         AVFrame *out = s->frames[s->nb_frames - 1];
255         out->pts     = s->pts[s->flush_idx++] - s->nb_samples;
256 	if (s->nb_frames > 1)
257             s->nb_samples += s->pts[s->flush_idx] - s->pts[s->flush_idx - 1] - out->nb_samples;
258 
259         if (av_sample_fmt_is_planar(out->format))
260             reverse_samples_planar(out);
261         else
262             reverse_samples_packed(out);
263         ret = ff_filter_frame(outlink, out);
264         s->frames[s->nb_frames - 1] = NULL;
265         s->nb_frames--;
266     }
267 
268     return ret;
269 }
270 
271 static const AVFilterPad areverse_inputs[] = {
272     {
273         .name           = "default",
274         .type           = AVMEDIA_TYPE_AUDIO,
275         .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
276         .filter_frame   = filter_frame,
277     },
278 };
279 
280 static const AVFilterPad areverse_outputs[] = {
281     {
282         .name          = "default",
283         .type          = AVMEDIA_TYPE_AUDIO,
284         .request_frame = areverse_request_frame,
285     },
286 };
287 
288 const AVFilter ff_af_areverse = {
289     .name          = "areverse",
290     .description   = NULL_IF_CONFIG_SMALL("Reverse an audio clip."),
291     .priv_size     = sizeof(ReverseContext),
292     .init          = init,
293     .uninit        = uninit,
294     FILTER_INPUTS(areverse_inputs),
295     FILTER_OUTPUTS(areverse_outputs),
296 };
297 
298 #endif /* CONFIG_AREVERSE_FILTER */
299