FFmpeg
Loading...
Searching...
No Matches
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
22#include "libavutil/opt.h"
23#include "avfilter.h"
24#include "audio.h"
25#include "filters.h"
26#include "formats.h"
27#include "drawutils.h"
28#include "video.h"
29
35
53
54#define OFFSET(x) offsetof(TPadContext, x)
55#define VF AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
56
57static const AVOption tpad_options[] = {
58 { "start", "set the number of frames to delay input", OFFSET(pad_start), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, VF },
59 { "stop", "set the number of frames to add after input finished", OFFSET(pad_stop), AV_OPT_TYPE_INT, {.i64=0}, -1, INT_MAX, VF },
60 { "start_mode", "set the mode of added frames to start", OFFSET(start_mode), AV_OPT_TYPE_INT, {.i64=MODE_ADD}, 0, NB_MODE-1, VF, .unit = "mode" },
61 { "add", "add solid-color frames", 0, AV_OPT_TYPE_CONST, {.i64=MODE_ADD}, 0, 0, VF, .unit = "mode" },
62 { "clone", "clone first/last frame", 0, AV_OPT_TYPE_CONST, {.i64=MODE_CLONE}, 0, 0, VF, .unit = "mode" },
63 { "stop_mode", "set the mode of added frames to end", OFFSET(stop_mode), AV_OPT_TYPE_INT, {.i64=MODE_ADD}, 0, NB_MODE-1, VF, .unit = "mode" },
64 { "start_duration", "set the duration to delay input", OFFSET(start_duration), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT64_MAX, VF },
65 { "stop_duration", "set the duration to pad input", OFFSET(stop_duration), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT64_MAX, VF },
66 { "color", "set the color of the added frames", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, VF },
67 { NULL }
68};
69
71
72static int needs_drawing(const TPadContext *s) {
73 return (
74 (s->stop_mode == MODE_ADD && (s->pad_stop != 0 || s->stop_duration != 0)) ||
75 (s->start_mode == MODE_ADD && (s->pad_start != 0 || s->start_duration != 0))
76 );
77}
78
80 AVFilterFormatsConfig **cfg_in,
81 AVFilterFormatsConfig **cfg_out)
82{
83 const TPadContext *s = ctx->priv;
84 if (needs_drawing(s))
85 return ff_set_common_formats2(ctx, cfg_in, cfg_out,
87
88 return ff_set_common_formats2(ctx, cfg_in, cfg_out,
90}
91
93{
94 AVFilterLink *inlink = ctx->inputs[0];
95 AVFilterLink *outlink = ctx->outputs[0];
96 FilterLink *l = ff_filter_link(outlink);
97 TPadContext *s = ctx->priv;
99 int ret, status;
101
102 FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
103
104 if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) {
105 if (status == AVERROR_EOF) {
106 pts = av_rescale_q(pts, inlink->time_base, outlink->time_base);
107 if (!s->pad_stop && !s->pad_start) {
108 ff_outlink_set_status(outlink, status, pts);
109 return 0;
110 }
111 s->eof = 1;
112 s->pts += pts;
113 }
114 }
115
116 if (s->start_mode == MODE_ADD && s->pad_start > 0 && ff_outlink_frame_wanted(outlink)) {
117 frame = ff_get_video_buffer(outlink, outlink->w, outlink->h);
118 if (!frame)
119 return AVERROR(ENOMEM);
120 ff_fill_rectangle(&s->draw, &s->color,
121 frame->data, frame->linesize,
122 0, 0, frame->width, frame->height);
124 frame->pts = s->pts;
125 frame->duration = duration;
126 s->pts += duration;
127 s->pad_start--;
128 return ff_filter_frame(outlink, frame);
129 }
130
131 if (s->start_mode == MODE_CLONE && s->pad_start > 0) {
132 if (s->eof) {
134 return 0;
135 } else if (!s->cache_start && ff_inlink_queued_frames(inlink)) {
136 s->cache_start = ff_inlink_peek_frame(inlink, 0);
137 } else if (!s->cache_start) {
138 FF_FILTER_FORWARD_WANTED(outlink, inlink);
139 }
140 frame = av_frame_clone(s->cache_start);
141 if (!frame)
142 return AVERROR(ENOMEM);
144 frame->pts = s->pts;
145 frame->duration = duration;
146 s->pts += duration;
147 s->pad_start--;
148 if (s->pad_start == 0)
149 s->cache_start = NULL;
150 return ff_filter_frame(outlink, frame);
151 }
152
153 if (!s->eof && !s->pad_start) {
154 ret = ff_inlink_consume_frame(inlink, &frame);
155 if (ret < 0)
156 return ret;
157 if (ret > 0) {
158 if (s->stop_mode == MODE_CLONE && s->pad_stop != 0) {
159 av_frame_free(&s->cache_stop);
160 s->cache_stop = av_frame_clone(frame);
161 }
162 frame->pts += s->pts;
163 return ff_filter_frame(outlink, frame);
164 }
165 }
166
167 if (s->eof) {
168 if (!s->pad_stop) {
169 ff_outlink_set_status(outlink, AVERROR_EOF, s->pts);
170 return 0;
171 }
172 if (s->stop_mode == MODE_ADD) {
173 frame = ff_get_video_buffer(outlink, outlink->w, outlink->h);
174 if (!frame)
175 return AVERROR(ENOMEM);
176 ff_fill_rectangle(&s->draw, &s->color,
177 frame->data, frame->linesize,
178 0, 0, frame->width, frame->height);
179 } else if (s->stop_mode == MODE_CLONE) {
180 if (!s->cache_stop) {
181 s->pad_stop = 0;
182 ff_outlink_set_status(outlink, AVERROR_EOF, s->pts);
183 return 0;
184 }
185 frame = av_frame_clone(s->cache_stop);
186 if (!frame)
187 return AVERROR(ENOMEM);
188 }
190 frame->pts = s->pts;
191 frame->duration = duration;
192 s->pts += duration;
193 if (s->pad_stop > 0)
194 s->pad_stop--;
195 return ff_filter_frame(outlink, frame);
196 }
197
198 if (!s->pad_start)
199 FF_FILTER_FORWARD_WANTED(outlink, inlink);
200
201 return FFERROR_NOT_READY;
202}
203
204static int config_input(AVFilterLink *inlink)
205{
206 AVFilterContext *ctx = inlink->dst;
207 FilterLink *l = ff_filter_link(inlink);
208 TPadContext *s = ctx->priv;
209 int ret;
210
211 if (needs_drawing(s)) {
212 ret = ff_draw_init_from_link(&s->draw, inlink, 0);
213 if (ret < 0) {
214 av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
215 return ret;
216 }
217 ff_draw_color(&s->draw, &s->color, s->rgba_color);
218 }
219
220 if (s->start_duration)
221 s->pad_start = av_rescale_q(s->start_duration, l->frame_rate, av_inv_q(AV_TIME_BASE_Q));
222 if (s->stop_duration)
223 s->pad_stop = av_rescale_q(s->stop_duration, l->frame_rate, av_inv_q(AV_TIME_BASE_Q));
224
225 return 0;
226}
227
229{
230 TPadContext *s = ctx->priv;
231
232 av_frame_free(&s->cache_stop);
233}
234
235static const AVFilterPad tpad_inputs[] = {
236 {
237 .name = "default",
238 .type = AVMEDIA_TYPE_VIDEO,
239 .config_props = config_input,
240 },
241};
242
244 .p.name = "tpad",
245 .p.description = NULL_IF_CONFIG_SMALL("Temporarily pad video frames."),
246 .p.priv_class = &tpad_class,
247 .priv_size = sizeof(TPadContext),
249 .uninit = uninit,
253};
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition aeval.c:246
static int config_input(AVFilterLink *inlink)
const FFFilter ff_vf_tpad
Definition vf_tpad.c:243
static AVFormatContext * ctx
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:1467
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
int ff_outlink_frame_wanted(AVFilterLink *link)
Test if a frame is wanted on an output link.
Definition avfilter.c:1690
size_t ff_inlink_queued_frames(AVFilterLink *link)
Get the number of frames available on the link.
Definition avfilter.c:1483
AVFrame * ff_inlink_peek_frame(AVFilterLink *link, size_t idx)
Access a frame in the link fifo without consuming it.
Definition avfilter.c:1561
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
Definition avfilter.c:1520
Main libavfilter public API header.
#define s(width, name)
Definition cbs_vp9.c:198
Public libavutil channel layout APIs header.
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static AVFrame * frame
void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
Prepare a color.
Definition drawutils.c:179
AVFilterFormats * ff_draw_supported_pixel_formats(unsigned flags)
Return the list of pixel formats supported by the draw functions.
Definition drawutils.c:670
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:258
int ff_draw_init_from_link(FFDrawContext *draw, const AVFilterLink *link, unsigned flags)
Init a draw context, taking the format, colorspace and range from the given filter link.
Definition drawutils.c:168
misc drawing utilities
static int64_t duration
Definition ffplay.c:330
AVFilterFormats * ff_all_formats(enum AVMediaType type)
Return a list of all formats supported by FFmpeg for the given media type.
Definition formats.c:602
int ff_set_common_formats2(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out, AVFilterFormats *formats)
Definition formats.c:1137
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_DURATION
Underlying C type is int64_t.
Definition opt.h:318
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_COLOR
Underlying C type is uint8_t[4].
Definition opt.h:322
#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
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition frame.c:483
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition rational.h:159
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition avutil.h:263
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int activate(AVBitStreamFilterContext *ctx)
#define VF
Definition af_afir.c:733
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
#define FF_FILTER_FORWARD_WANTED(outlink, inlink)
Forward the frame_wanted_out flag from an output link to an input link.
Definition filters.h:694
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:629
#define FFERROR_NOT_READY
Filters implementation helper functions and internal structures.
Definition filters.h:34
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
Definition filters.h:639
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition filters.h:199
#define AVFILTER_DEFINE_CLASS(fname)
Definition filters.h:478
#define FILTER_QUERY_FUNC2(func)
Definition filters.h:241
#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
AVOptions.
Describe the class of an AVClass context structure.
Definition log.h:76
An instance of a filter.
Definition avfilter.h:273
Lists of formats / etc.
Definition avfilter.h:120
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
AVOption.
Definition opt.h:428
int64_t pts
Definition vf_tpad.c:48
FFDrawColor color
Definition vf_tpad.c:47
AVFrame * cache_start
Definition vf_tpad.c:50
int64_t stop_duration
Definition vf_tpad.c:43
int pad_stop
Definition vf_tpad.c:39
int64_t start_duration
Definition vf_tpad.c:42
int start_mode
Definition vf_tpad.c:40
uint8_t rgba_color[4]
color for the padding area
Definition vf_tpad.c:44
AVFrame * cache_stop
Definition vf_tpad.c:51
FFDrawContext draw
Definition vf_tpad.c:46
int stop_mode
Definition vf_tpad.c:41
int pad_start
Definition vf_tpad.c:38
#define av_log(a,...)
static int64_t pts
@ NB_MODE
static const AVOption tpad_options[]
Definition vf_tpad.c:57
static int config_input(AVFilterLink *inlink)
Definition vf_tpad.c:204
static const AVFilterPad tpad_inputs[]
Definition vf_tpad.c:235
PadMode
Definition vf_tpad.c:30
@ MODE_ADD
Definition vf_tpad.c:31
@ MODE_CLONE
Definition vf_tpad.c:32
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition vf_tpad.c:79
static int activate(AVFilterContext *ctx)
Definition vf_tpad.c:92
static av_cold void uninit(AVFilterContext *ctx)
Definition vf_tpad.c:228
static int needs_drawing(const TPadContext *s)
Definition vf_tpad.c:72
#define OFFSET(x)
Definition vf_tpad.c:54
const AVFilterPad ff_video_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_VIDEO.
Definition video.c:37
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition video.c:89