FFmpeg  4.3
vf_tpad.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 Paul B Mahol
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 "libavutil/avassert.h"
23 #include "libavutil/opt.h"
24 #include "avfilter.h"
25 #include "audio.h"
26 #include "filters.h"
27 #include "internal.h"
28 #include "formats.h"
29 #include "drawutils.h"
30 
31 typedef struct TPadContext {
32  const AVClass *class;
33  int pad_start;
34  int pad_stop;
36  int stop_mode;
37  int64_t start_duration;
38  int64_t stop_duration;
39  uint8_t rgba_color[4]; ///< color for the padding area
40 
43  int64_t pts;
44  int eof;
47 } TPadContext;
48 
49 #define OFFSET(x) offsetof(TPadContext, x)
50 #define VF AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
51 
52 static const AVOption tpad_options[] = {
53  { "start", "set the number of frames to delay input", OFFSET(pad_start), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, VF },
54  { "stop", "set the number of frames to add after input finished", OFFSET(pad_stop), AV_OPT_TYPE_INT, {.i64=0}, -1, INT_MAX, VF },
55  { "start_mode", "set the mode of added frames to start", OFFSET(start_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, VF, "mode" },
56  { "add", "add solid-color frames", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, VF, "mode" },
57  { "clone", "clone first/last frame", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, VF, "mode" },
58  { "stop_mode", "set the mode of added frames to end", OFFSET(stop_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, VF, "mode" },
59  { "start_duration", "set the duration to delay input", OFFSET(start_duration), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT64_MAX, VF },
60  { "stop_duration", "set the duration to pad input", OFFSET(stop_duration), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT64_MAX, VF },
61  { "color", "set the color of the added frames", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, VF },
62  { NULL }
63 };
64 
66 
68 {
70 }
71 
73 {
74  AVFilterLink *inlink = ctx->inputs[0];
75  AVFilterLink *outlink = ctx->outputs[0];
76  TPadContext *s = ctx->priv;
77  AVFrame *frame = NULL;
78  int ret, status;
79  int64_t pts;
80 
81  FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
82 
83  if (s->start_mode == 0 && s->pad_start > 0 && ff_outlink_frame_wanted(outlink)) {
84  frame = ff_get_video_buffer(outlink, outlink->w, outlink->h);
85  if (!frame)
86  return AVERROR(ENOMEM);
87  ff_fill_rectangle(&s->draw, &s->color,
88  frame->data, frame->linesize,
89  0, 0, frame->width, frame->height);
90  frame->pts = s->pts;
91  s->pts += av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base);
92  s->pad_start--;
93  return ff_filter_frame(outlink, frame);
94  }
95 
96  if (s->start_mode == 1 && s->pad_start > 0) {
97  if (!s->cache_start && ff_inlink_queued_frames(inlink)) {
98  s->cache_start = ff_inlink_peek_frame(inlink, 0);
99  } else if (!s->cache_start) {
100  FF_FILTER_FORWARD_WANTED(outlink, inlink);
101  }
102  frame = av_frame_clone(s->cache_start);
103  if (!frame)
104  return AVERROR(ENOMEM);
105  frame->pts = s->pts;
106  s->pts += av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base);
107  s->pad_start--;
108  if (s->pad_start == 0)
109  s->cache_start = NULL;
110  return ff_filter_frame(outlink, frame);
111  }
112 
113  if (!s->eof && !s->pad_start) {
114  ret = ff_inlink_consume_frame(inlink, &frame);
115  if (ret < 0)
116  return ret;
117  if (ret > 0) {
118  if (s->stop_mode == 1 && s->pad_stop != 0) {
120  s->cache_stop = av_frame_clone(frame);
121  }
122  frame->pts += s->pts;
123  return ff_filter_frame(outlink, frame);
124  }
125  }
126 
127  if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) {
128  if (status == AVERROR_EOF) {
129  if (!s->pad_stop) {
130  ff_outlink_set_status(outlink, status, pts);
131  return 0;
132  }
133  s->eof = 1;
134  s->pts += pts;
135  }
136  }
137 
138  if (s->eof) {
139  if (!s->pad_stop) {
140  ff_outlink_set_status(outlink, AVERROR_EOF, s->pts);
141  return 0;
142  }
143  if (s->stop_mode == 0) {
144  frame = ff_get_video_buffer(outlink, outlink->w, outlink->h);
145  if (!frame)
146  return AVERROR(ENOMEM);
147  ff_fill_rectangle(&s->draw, &s->color,
148  frame->data, frame->linesize,
149  0, 0, frame->width, frame->height);
150  } else if (s->stop_mode == 1) {
151  frame = av_frame_clone(s->cache_stop);
152  if (!frame)
153  return AVERROR(ENOMEM);
154  }
155  frame->pts = s->pts;
156  s->pts += av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base);
157  if (s->pad_stop > 0)
158  s->pad_stop--;
159  return ff_filter_frame(outlink, frame);
160  }
161 
162  if (!s->pad_start)
163  FF_FILTER_FORWARD_WANTED(outlink, inlink);
164 
165  return FFERROR_NOT_READY;
166 }
167 
168 static int config_input(AVFilterLink *inlink)
169 {
170  AVFilterContext *ctx = inlink->dst;
171  TPadContext *s = ctx->priv;
172 
173  ff_draw_init(&s->draw, inlink->format, 0);
174  ff_draw_color(&s->draw, &s->color, s->rgba_color);
175 
176  if (s->start_duration)
178  if (s->stop_duration)
180 
181  return 0;
182 }
183 
185 {
186  TPadContext *s = ctx->priv;
187 
189 }
190 
191 static const AVFilterPad tpad_inputs[] = {
192  {
193  .name = "default",
194  .type = AVMEDIA_TYPE_VIDEO,
195  .config_props = config_input,
196  },
197  { NULL }
198 };
199 
200 static const AVFilterPad tpad_outputs[] = {
201  {
202  .name = "default",
203  .type = AVMEDIA_TYPE_VIDEO,
204  },
205  { NULL }
206 };
207 
209  .name = "tpad",
210  .description = NULL_IF_CONFIG_SMALL("Temporarily pad video frames."),
211  .priv_size = sizeof(TPadContext),
212  .priv_class = &tpad_class,
214  .activate = activate,
215  .uninit = uninit,
216  .inputs = tpad_inputs,
217  .outputs = tpad_outputs,
218 };
AVFilterFormats * ff_draw_supported_pixel_formats(unsigned flags)
Return the list of pixel formats supported by the draw functions.
Definition: drawutils.c:731
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link&#39;s FIFO and update the link&#39;s stats.
Definition: avfilter.c:1476
#define NULL
Definition: coverity.c:32
int start_mode
Definition: vf_tpad.c:35
This structure describes decoded (raw) audio or video data.
Definition: frame.h:300
int64_t stop_duration
Definition: vf_tpad.c:38
AVOption.
Definition: opt.h:246
Main libavfilter public API header.
int eof
Definition: vf_tpad.c:44
#define FFERROR_NOT_READY
Filters implementation helper functions.
Definition: filters.h:34
int64_t pts
Definition: vf_tpad.c:43
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:99
AVFilter ff_vf_tpad
Definition: vf_tpad.c:208
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
Definition: filters.h:189
static int ff_outlink_frame_wanted(AVFilterLink *link)
Test if a frame is wanted on an output link.
Definition: filters.h:172
const char * name
Pad name.
Definition: internal.h:60
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:346
int pad_stop
Definition: vf_tpad.c:34
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1075
AVFrame * cache_stop
Definition: vf_tpad.c:46
uint8_t
#define av_cold
Definition: attributes.h:88
AVOptions.
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:393
static AVFrame * frame
int stop_mode
Definition: vf_tpad.c:36
#define AVERROR_EOF
End of file.
Definition: error.h:55
FFDrawContext draw
Definition: vf_tpad.c:41
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
Definition: filters.h:199
A filter pad used for either input or output.
Definition: internal.h:54
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
Definition: avfilter.c:1431
int width
Definition: frame.h:358
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:600
int64_t start_duration
Definition: vf_tpad.c:37
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
void * priv
private data for use by the filter
Definition: avfilter.h:353
void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
Prepare a color.
Definition: drawutils.c:231
simple assert() macros that are a bit more flexible than ISO C assert().
#define OFFSET(x)
Definition: vf_tpad.c:49
#define VF
Definition: vf_tpad.c:50
#define FF_FILTER_FORWARD_WANTED(outlink, inlink)
Forward the frame_wanted_out flag from an output link to an input link.
Definition: filters.h:254
AVFILTER_DEFINE_CLASS(tpad)
audio channel layout utility functions
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_tpad.c:184
int pad_start
Definition: vf_tpad.c:33
AVFormatContext * ctx
Definition: movenc.c:48
#define s(width, name)
Definition: cbs_vp9.c:257
static const AVFilterPad inputs[]
Definition: af_acontrast.c:193
FFDrawColor color
Definition: vf_tpad.c:42
AVFrame * ff_inlink_peek_frame(AVFilterLink *link, size_t idx)
Access a frame in the link fifo without consuming it.
Definition: avfilter.c:1515
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:541
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
static int config_input(AVFilterLink *inlink)
Definition: vf_tpad.c:168
misc drawing utilities
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:331
static int activate(AVFilterContext *ctx)
Definition: vf_tpad.c:72
static const AVFilterPad tpad_outputs[]
Definition: vf_tpad.c:200
AVFrame * cache_start
Definition: vf_tpad.c:45
Describe the class of an AVClass context structure.
Definition: log.h:67
uint8_t rgba_color[4]
color for the padding area
Definition: vf_tpad.c:39
Filter definition.
Definition: avfilter.h:144
static const AVFilterPad tpad_inputs[]
Definition: vf_tpad.c:191
const char * name
Filter name.
Definition: avfilter.h:148
int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
Init a draw context.
Definition: drawutils.c:178
size_t ff_inlink_queued_frames(AVFilterLink *link)
Get the number of frames available on the link.
Definition: avfilter.c:1446
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:314
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition: rational.h:159
static int query_formats(AVFilterContext *ctx)
Definition: vf_tpad.c:67
void ff_fill_rectangle(FFDrawContext *draw, FFDrawColor *color, uint8_t *dst[], int dst_linesize[], int dst_x, int dst_y, int w, int h)
Fill a rectangle with an uniform color.
Definition: drawutils.c:318
An instance of a filter.
Definition: avfilter.h:338
int height
Definition: frame.h:358
internal API functions
static const AVOption tpad_options[]
Definition: vf_tpad.c:52