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};
159
160#endif /* CONFIG_REVERSE_FILTER */
161
162#if CONFIG_AREVERSE_FILTER
163
164static void reverse_samples_planar(AVFrame *out)
165{
166 for (int p = 0; p < out->ch_layout.nb_channels; p++) {
167 switch (out->format) {
168 case AV_SAMPLE_FMT_U8P: {
169 uint8_t *dst = (uint8_t *)out->extended_data[p];
170 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
171 FFSWAP(uint8_t, dst[i], dst[j]);
172 }
173 break;
174 case AV_SAMPLE_FMT_S16P: {
175 int16_t *dst = (int16_t *)out->extended_data[p];
176 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
177 FFSWAP(int16_t, dst[i], dst[j]);
178 }
179 break;
180 case AV_SAMPLE_FMT_S32P: {
181 int32_t *dst = (int32_t *)out->extended_data[p];
182 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
183 FFSWAP(int32_t, dst[i], dst[j]);
184 }
185 break;
186 case AV_SAMPLE_FMT_S64P: {
187 int64_t *dst = (int64_t *)out->extended_data[p];
188 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
189 FFSWAP(int64_t, dst[i], dst[j]);
190 }
191 break;
192 case AV_SAMPLE_FMT_FLTP: {
193 float *dst = (float *)out->extended_data[p];
194 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
195 FFSWAP(float, dst[i], dst[j]);
196 }
197 break;
198 case AV_SAMPLE_FMT_DBLP: {
199 double *dst = (double *)out->extended_data[p];
200 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
201 FFSWAP(double, dst[i], dst[j]);
202 }
203 break;
204 }
205 }
206}
207
208static void reverse_samples_packed(AVFrame *out)
209{
210 const int channels = out->ch_layout.nb_channels;
211
212 switch (out->format) {
213 case AV_SAMPLE_FMT_U8: {
214 uint8_t *dst = (uint8_t *)out->extended_data[0];
215 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
216 for (int p = 0; p < channels; p++)
217 FFSWAP(uint8_t, dst[i * channels + p], dst[j * channels + p]);
218 }
219 break;
220 case AV_SAMPLE_FMT_S16: {
221 int16_t *dst = (int16_t *)out->extended_data[0];
222 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
223 for (int p = 0; p < channels; p++)
224 FFSWAP(int16_t, dst[i * channels + p], dst[j * channels + p]);
225 }
226 break;
227 case AV_SAMPLE_FMT_S32: {
228 int32_t *dst = (int32_t *)out->extended_data[0];
229 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
230 for (int p = 0; p < channels; p++)
231 FFSWAP(int32_t, dst[i * channels + p], dst[j * channels + p]);
232 }
233 break;
234 case AV_SAMPLE_FMT_S64: {
235 int64_t *dst = (int64_t *)out->extended_data[0];
236 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
237 for (int p = 0; p < channels; p++)
238 FFSWAP(int64_t, dst[i * channels + p], dst[j * channels + p]);
239 }
240 break;
241 case AV_SAMPLE_FMT_FLT: {
242 float *dst = (float *)out->extended_data[0];
243 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
244 for (int p = 0; p < channels; p++)
245 FFSWAP(float, dst[i * channels + p], dst[j * channels + p]);
246 }
247 break;
248 case AV_SAMPLE_FMT_DBL: {
249 double *dst = (double *)out->extended_data[0];
250 for (int i = 0, j = out->nb_samples - 1; i < j; i++, j--)
251 for (int p = 0; p < channels; p++)
252 FFSWAP(double, dst[i * channels + p], dst[j * channels + p]);
253 }
254 break;
255 }
256}
257
258static int areverse_request_frame(AVFilterLink *outlink)
259{
260 AVFilterContext *ctx = outlink->src;
261 ReverseContext *s = ctx->priv;
262 int ret;
263
264 ret = ff_request_frame(ctx->inputs[0]);
265
266 if (ret == AVERROR_EOF && s->nb_frames > 0) {
267 AVFrame *out = s->frames[s->nb_frames - 1];
268 out->duration = s->duration[s->flush_idx];
269 out->pts = s->pts[s->flush_idx++] - s->nb_samples;
270 if (s->nb_frames > 1)
271 s->nb_samples += s->pts[s->flush_idx] - s->pts[s->flush_idx - 1] - out->nb_samples;
272
273 if (av_sample_fmt_is_planar(out->format))
274 reverse_samples_planar(out);
275 else
276 reverse_samples_packed(out);
277 ret = ff_filter_frame(outlink, out);
278 s->frames[s->nb_frames - 1] = NULL;
279 s->nb_frames--;
280 }
281
282 return ret;
283}
284
285static const AVFilterPad areverse_inputs[] = {
286 {
287 .name = "default",
288 .type = AVMEDIA_TYPE_AUDIO,
290 .filter_frame = filter_frame,
291 },
292};
293
294static const AVFilterPad areverse_outputs[] = {
295 {
296 .name = "default",
297 .type = AVMEDIA_TYPE_AUDIO,
298 .request_frame = areverse_request_frame,
299 },
300};
301
302const FFFilter ff_af_areverse = {
303 .p.name = "areverse",
304 .p.description = NULL_IF_CONFIG_SMALL("Reverse an audio clip."),
305 .priv_size = sizeof(ReverseContext),
306 .init = init,
307 .uninit = uninit,
308 FILTER_INPUTS(areverse_inputs),
309 FILTER_OUTPUTS(areverse_outputs),
310};
311
312#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:87
static int request_frame(AVFilterLink *outlink)
Definition af_aecho.c:272
const FFFilter ff_vf_reverse
const FFFilter ff_af_areverse
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:1068
int ff_request_frame(AVFilterLink *link)
Request an input frame from the filter at the other end of the link.
Definition avfilter.c:483
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
#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:64
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:495
@ 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:114
@ 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:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
#define AVFILTERPAD_FLAG_NEEDS_WRITABLE
The filter expects writable frames from its input link, duplicating data buffers if needed.
Definition filters.h:59
#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:88
#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:273
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:472
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition frame.h:574
int64_t duration
Duration of the frame, in the same units as pts.
Definition frame.h:820
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)
static FILE * out
Definition movenc.c:55
static AVFormatContext * ctx
Definition movenc.c:49