FFmpeg
Loading...
Searching...
No Matches
f_reverse.c
Go to the documentation of this file.
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/mem.h"
24#include "avfilter.h"
25#include "filters.h"
26
27#define DEFAULT_LENGTH 300
28
40
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->duration = av_fast_realloc(NULL, &s->duration_size,
51 DEFAULT_LENGTH * sizeof(*(s->duration)));
52 if (!s->duration)
53 return AVERROR(ENOMEM);
54
55 s->frames = av_fast_realloc(NULL, &s->frames_size,
56 DEFAULT_LENGTH * sizeof(*(s->frames)));
57 if (!s->frames)
58 return AVERROR(ENOMEM);
59
60 return 0;
61}
62
64{
65 ReverseContext *s = ctx->priv;
66
67 while (s->nb_frames > 0) {
68 av_frame_free(&s->frames[s->nb_frames - 1]);
69 s->nb_frames--;
70 }
71
72 av_freep(&s->pts);
73 av_freep(&s->duration);
74 av_freep(&s->frames);
75}
76
77static int filter_frame(AVFilterLink *inlink, AVFrame *in)
78{
79 AVFilterContext *ctx = inlink->dst;
80 ReverseContext *s = ctx->priv;
81 void *ptr;
82
83 if (s->nb_frames + 1 > s->pts_size / sizeof(*(s->pts))) {
84 ptr = av_fast_realloc(s->pts, &s->pts_size, s->pts_size * 2);
85 if (!ptr)
86 return AVERROR(ENOMEM);
87 s->pts = ptr;
88 }
89
90 if (s->nb_frames + 1 > s->duration_size / sizeof(*(s->duration))) {
91 ptr = av_fast_realloc(s->duration, &s->duration_size, s->duration_size * 2);
92 if (!ptr)
93 return AVERROR(ENOMEM);
94 s->duration = ptr;
95 }
96
97 if (s->nb_frames + 1 > s->frames_size / sizeof(*(s->frames))) {
98 ptr = av_fast_realloc(s->frames, &s->frames_size, s->frames_size * 2);
99 if (!ptr)
100 return AVERROR(ENOMEM);
101 s->frames = ptr;
102 }
103
104 s->frames[s->nb_frames] = in;
105 s->pts[s->nb_frames] = in->pts;
106 s->duration[s->nb_frames] = in->duration;
107 s->nb_frames++;
108
109 return 0;
110}
111
112#if CONFIG_REVERSE_FILTER
113
114static int request_frame(AVFilterLink *outlink)
115{
116 AVFilterContext *ctx = outlink->src;
117 ReverseContext *s = ctx->priv;
118 int ret;
119
120 ret = ff_request_frame(ctx->inputs[0]);
121
122 if (ret == AVERROR_EOF && s->nb_frames > 0) {
123 AVFrame *out = s->frames[s->nb_frames - 1];
124 out->duration= s->duration[s->flush_idx];
125 out->pts = s->pts[s->flush_idx++];
126 ret = ff_filter_frame(outlink, out);
127 s->frames[s->nb_frames - 1] = NULL;
128 s->nb_frames--;
129 }
130
131 return ret;
132}
133
134static const AVFilterPad reverse_inputs[] = {
135 {
136 .name = "default",
137 .type = AVMEDIA_TYPE_VIDEO,
138 .filter_frame = filter_frame,
139 },
140};
141
142static const AVFilterPad reverse_outputs[] = {
143 {
144 .name = "default",
145 .type = AVMEDIA_TYPE_VIDEO,
146 .request_frame = request_frame,
147 },
148};
149
150const FFFilter ff_vf_reverse = {
151 .p.name = "reverse",
152 .p.description = NULL_IF_CONFIG_SMALL("Reverse a clip."),
153 .priv_size = sizeof(ReverseContext),
154 .init = init,
155 .uninit = uninit,
156 FILTER_INPUTS(reverse_inputs),
157 FILTER_OUTPUTS(reverse_outputs),
158 .flags_internal = FF_FILTER_FLAG_DYNAMIC_FRAME_PARAMS,
159};
160
161#endif /* CONFIG_REVERSE_FILTER */
162
163#if CONFIG_AREVERSE_FILTER
164
165static void reverse_samples_planar(AVFrame *out)
166{
167 for (int p = 0; p < out->ch_layout.nb_channels; p++) {
168 switch (out->format) {
169 case AV_SAMPLE_FMT_U8P: {
170 uint8_t *dst = (uint8_t *)out->extended_data[p];
171 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
172 FFSWAP(uint8_t, dst[i], dst[j]);
173 }
174 break;
175 case AV_SAMPLE_FMT_S16P: {
176 int16_t *dst = (int16_t *)out->extended_data[p];
177 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
178 FFSWAP(int16_t, dst[i], dst[j]);
179 }
180 break;
181 case AV_SAMPLE_FMT_S32P: {
182 int32_t *dst = (int32_t *)out->extended_data[p];
183 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
184 FFSWAP(int32_t, dst[i], dst[j]);
185 }
186 break;
187 case AV_SAMPLE_FMT_S64P: {
188 int64_t *dst = (int64_t *)out->extended_data[p];
189 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
190 FFSWAP(int64_t, dst[i], dst[j]);
191 }
192 break;
193 case AV_SAMPLE_FMT_FLTP: {
194 float *dst = (float *)out->extended_data[p];
195 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
196 FFSWAP(float, dst[i], dst[j]);
197 }
198 break;
199 case AV_SAMPLE_FMT_DBLP: {
200 double *dst = (double *)out->extended_data[p];
201 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
202 FFSWAP(double, dst[i], dst[j]);
203 }
204 break;
205 }
206 }
207}
208
209static void reverse_samples_packed(AVFrame *out)
210{
211 const int channels = out->ch_layout.nb_channels;
212
213 switch (out->format) {
214 case AV_SAMPLE_FMT_U8: {
215 uint8_t *dst = (uint8_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(uint8_t, dst[i * channels + p], dst[j * channels + p]);
219 }
220 break;
221 case AV_SAMPLE_FMT_S16: {
222 int16_t *dst = (int16_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(int16_t, dst[i * channels + p], dst[j * channels + p]);
226 }
227 break;
228 case AV_SAMPLE_FMT_S32: {
229 int32_t *dst = (int32_t *)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(int32_t, dst[i * channels + p], dst[j * channels + p]);
233 }
234 break;
235 case AV_SAMPLE_FMT_S64: {
236 int64_t *dst = (int64_t *)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(int64_t, dst[i * channels + p], dst[j * channels + p]);
240 }
241 break;
242 case AV_SAMPLE_FMT_FLT: {
243 float *dst = (float *)out->extended_data[0];
244 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
245 for (int p = 0; p < channels; p++)
246 FFSWAP(float, dst[i * channels + p], dst[j * channels + p]);
247 }
248 break;
249 case AV_SAMPLE_FMT_DBL: {
250 double *dst = (double *)out->extended_data[0];
251 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
252 for (int p = 0; p < channels; p++)
253 FFSWAP(double, dst[i * channels + p], dst[j * channels + p]);
254 }
255 break;
256 }
257}
258
259static int areverse_request_frame(AVFilterLink *outlink)
260{
261 AVFilterContext *ctx = outlink->src;
262 ReverseContext *s = ctx->priv;
263 int ret;
264
265 ret = ff_request_frame(ctx->inputs[0]);
266
267 if (ret == AVERROR_EOF && s->nb_frames > 0) {
268 AVFrame *out = s->frames[s->nb_frames - 1];
269 out->duration = s->duration[s->flush_idx];
270 out->pts = s->pts[s->flush_idx++] - s->nb_samples;
271 if (s->nb_frames > 1)
272 s->nb_samples += s->pts[s->flush_idx] - s->pts[s->flush_idx - 1] - out->nb_samples;
273
274 if (av_sample_fmt_is_planar(out->format))
275 reverse_samples_planar(out);
276 else
277 reverse_samples_packed(out);
278 ret = ff_filter_frame(outlink, out);
279 s->frames[s->nb_frames - 1] = NULL;
280 s->nb_frames--;
281 }
282
283 return ret;
284}
285
286static const AVFilterPad areverse_inputs[] = {
287 {
288 .name = "default",
289 .type = AVMEDIA_TYPE_AUDIO,
291 .filter_frame = filter_frame,
292 },
293};
294
295static const AVFilterPad areverse_outputs[] = {
296 {
297 .name = "default",
298 .type = AVMEDIA_TYPE_AUDIO,
299 .request_frame = areverse_request_frame,
300 },
301};
302
303const FFFilter ff_af_areverse = {
304 .p.name = "areverse",
305 .p.description = NULL_IF_CONFIG_SMALL("Reverse an audio clip."),
306 .priv_size = sizeof(ReverseContext),
307 .init = init,
308 .uninit = uninit,
309 FILTER_INPUTS(areverse_inputs),
310 FILTER_OUTPUTS(areverse_outputs),
311};
312
313#endif /* CONFIG_AREVERSE_FILTER */
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:97
static int request_frame(AVFilterLink *outlink)
Definition af_aecho.c:272
const FFFilter ff_vf_reverse
const FFFilter ff_af_areverse
static FILE * out
static AVFormatContext * ctx
channels
Definition aptx.h:31
int32_t
#define DEFAULT_LENGTH
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1076
int ff_request_frame(AVFilterLink *link)
Request an input frame from the filter at the other end of the link.
Definition avfilter.c:489
Main libavfilter public API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
Definition dolby_e.c:1067
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition f_reverse.c:77
static av_cold void uninit(AVFilterContext *ctx)
Definition f_reverse.c:63
int ret
Definition ffplay.c:391
#define AVERROR_EOF
End of file.
Definition error.h:57
#define AVERROR(e)
Definition error.h:45
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:65
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
Definition mem.c:601
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
Check if the sample format is planar.
Definition samplefmt.c:115
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition samplefmt.h:66
@ AV_SAMPLE_FMT_S16P
signed 16 bits, planar
Definition samplefmt.h:64
@ AV_SAMPLE_FMT_FLT
float
Definition samplefmt.h:60
@ AV_SAMPLE_FMT_S64
signed 64 bits
Definition samplefmt.h:68
@ AV_SAMPLE_FMT_U8P
unsigned 8 bits, planar
Definition samplefmt.h:63
@ AV_SAMPLE_FMT_S32P
signed 32 bits, planar
Definition samplefmt.h:65
@ AV_SAMPLE_FMT_S32
signed 32 bits
Definition samplefmt.h:59
@ AV_SAMPLE_FMT_U8
unsigned 8 bits
Definition samplefmt.h:57
@ AV_SAMPLE_FMT_DBLP
double, planar
Definition samplefmt.h:67
@ AV_SAMPLE_FMT_DBL
double
Definition samplefmt.h:61
@ AV_SAMPLE_FMT_S64P
signed 64 bits, planar
Definition samplefmt.h:69
@ AV_SAMPLE_FMT_S16
signed 16 bits
Definition samplefmt.h:58
static av_cold void uninit(AVBitStreamFilterContext *ctx)
#define FILTER_INPUTS(array)
Definition filters.h:279
#define FILTER_OUTPUTS(array)
Definition filters.h:280
#define AVFILTERPAD_FLAG_NEEDS_WRITABLE
The filter expects writable frames from its input link, duplicating data buffers if needed.
Definition filters.h:59
#define FF_FILTER_FLAG_DYNAMIC_FRAME_PARAMS
Definition filters.h:222
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:97
#define FFSWAP(type, a, b)
Definition macros.h:52
Memory handling functions.
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
An instance of a filter.
Definition avfilter.h:279
A filter pad used for either input or output.
Definition filters.h:40
This structure describes decoded (raw) audio or video data.
Definition frame.h:479
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition frame.h:581
int64_t duration
Duration of the frame, in the same units as pts.
Definition frame.h:827
unsigned int duration_size
Definition f_reverse.c:34
int64_t * pts
Definition f_reverse.c:35
unsigned int frames_size
Definition f_reverse.c:32
unsigned int pts_size
Definition f_reverse.c:33
int64_t nb_samples
Definition f_reverse.c:38
int64_t * duration
Definition f_reverse.c:36
AVFrame ** frames
Definition f_reverse.c:31
#define av_freep(p)