History

avfilter/trim: switch to activate

This also signals EOF to filter inlink so that unnecessary extra processing that is immediately dropped by this filter is not done any more.

Paul B Mahol committed 3 years ago

Commit 90fba271 parent c6b63561 file · +131 −83Browse files

Showing the changes to libavfilter (1 of 1 file). Show all

Unified · Split

libavfilter/trim.c+131−83
@@ -31,6 +31,7 @@ · 30 unmodified lines
31#include "audio.h"31#include "audio.h"
32#include "avfilter.h"32#include "avfilter.h"
33#include "internal.h"33#include "internal.h"
34#include "filters.h"
34 35
35typedef struct TrimContext {36typedef struct TrimContext {
36 const AVClass *class;37 const AVClass *class;
@@ -68,6 +69,8 @@ typedef struct TrimContext { · 31 unmodified lines
68 int64_t next_pts;69 int64_t next_pts;
69 70
70 int eof;71 int eof;
72
73 int (*filter_frame)(AVFilterLink *inlink, AVFrame *frame);
71} TrimContext;74} TrimContext;
72 75
73static av_cold int init(AVFilterContext *ctx)76static av_cold int init(AVFilterContext *ctx)
@@ -79,47 +82,6 @@ static av_cold int init(AVFilterContext *ctx) · 5 unmodified lines
79 return 0;82 return 0;
80}83}
81 84
82static int config_input(AVFilterLink *inlink)
83{
84 AVFilterContext *ctx = inlink->dst;
85 TrimContext *s = ctx->priv;
86 AVRational tb = (inlink->type == AVMEDIA_TYPE_VIDEO) ?
87 inlink->time_base : (AVRational){ 1, inlink->sample_rate };
88
89 if (s->start_time != INT64_MAX) {
90 int64_t start_pts = av_rescale_q(s->start_time, AV_TIME_BASE_Q, tb);
91 if (s->start_pts == AV_NOPTS_VALUE || start_pts < s->start_pts)
92 s->start_pts = start_pts;
93 }
94 if (s->end_time != INT64_MAX) {
95 int64_t end_pts = av_rescale_q(s->end_time, AV_TIME_BASE_Q, tb);
96 if (s->end_pts == AV_NOPTS_VALUE || end_pts > s->end_pts)
97 s->end_pts = end_pts;
98 }
99 if (s->duration)
100 s->duration_tb = av_rescale_q(s->duration, AV_TIME_BASE_Q, tb);
101
102 return 0;
103}
104
105#define OFFSET(x) offsetof(TrimContext, x)
106#define COMMON_OPTS \
107 { "start", "Timestamp of the first frame that " \
108 "should be passed", OFFSET(start_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \
109 { "starti", "Timestamp of the first frame that " \
110 "should be passed", OFFSET(start_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \
111 { "end", "Timestamp of the first frame that " \
112 "should be dropped again", OFFSET(end_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \
113 { "endi", "Timestamp of the first frame that " \
114 "should be dropped again", OFFSET(end_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \
115 { "start_pts", "Timestamp of the first frame that should be " \
116 " passed", OFFSET(start_pts), AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, FLAGS }, \
117 { "end_pts", "Timestamp of the first frame that should be " \
118 "dropped again", OFFSET(end_pts), AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, FLAGS }, \
119 { "duration", "Maximum duration of the output", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, FLAGS }, \
120 { "durationi", "Maximum duration of the output", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, FLAGS },
121
122
123#if CONFIG_TRIM_FILTER85#if CONFIG_TRIM_FILTER
124static int trim_filter_frame(AVFilterLink *inlink, AVFrame *frame)86static int trim_filter_frame(AVFilterLink *inlink, AVFrame *frame)
125{87{
@@ -161,7 +123,8 @@ static int trim_filter_frame(AVFilterLink *inlink, AVFrame *frame) · 35 unmodified lines
161 123
162 if (drop) {124 if (drop) {
163 s->eof = 1;125 s->eof = 1;
164 ff_avfilter_link_set_out_status(inlink, AVERROR_EOF, AV_NOPTS_VALUE);126 ff_inlink_set_status(inlink, AVERROR_EOF);
127 ff_outlink_set_status(ctx->outputs[0], AVERROR_EOF, frame->pts);
165 goto drop;128 goto drop;
166 }129 }
167 }130 }
@@ -171,49 +134,12 @@ static int trim_filter_frame(AVFilterLink *inlink, AVFrame *frame) · 3 unmodified lines
171 return ff_filter_frame(ctx->outputs[0], frame);134 return ff_filter_frame(ctx->outputs[0], frame);
172 135
173drop:136drop:
137 if (!s->eof)
138 ff_filter_set_ready(ctx, 100);
174 s->nb_frames++;139 s->nb_frames++;
175 av_frame_free(&frame);140 av_frame_free(&frame);
176 return 0;141 return 0;
177}142}
178
179#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
180static const AVOption trim_options[] = {
181 COMMON_OPTS
182 { "start_frame", "Number of the first frame that should be passed "
183 "to the output", OFFSET(start_frame), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, FLAGS },
184 { "end_frame", "Number of the first frame that should be dropped "
185 "again", OFFSET(end_frame), AV_OPT_TYPE_INT64, { .i64 = INT64_MAX }, 0, INT64_MAX, FLAGS },
186 { NULL }
187};
188#undef FLAGS
189
190AVFILTER_DEFINE_CLASS(trim);
191
192static const AVFilterPad trim_inputs[] = {
193 {
194 .name = "default",
195 .type = AVMEDIA_TYPE_VIDEO,
196 .filter_frame = trim_filter_frame,
197 .config_props = config_input,
198 },
199};
200
201static const AVFilterPad trim_outputs[] = {
202 {
203 .name = "default",
204 .type = AVMEDIA_TYPE_VIDEO,
205 },
206};
207
208const AVFilter ff_vf_trim = {
209 .name = "trim",
210 .description = NULL_IF_CONFIG_SMALL("Pick one continuous section from the input, drop the rest."),
211 .init = init,
212 .priv_size = sizeof(TrimContext),
213 .priv_class = &trim_class,
214 FILTER_INPUTS(trim_inputs),
215 FILTER_OUTPUTS(trim_outputs),
216};
217#endif // CONFIG_TRIM_FILTER143#endif // CONFIG_TRIM_FILTER
218 144
219#if CONFIG_ATRIM_FILTER145#if CONFIG_ATRIM_FILTER
@@ -290,7 +216,8 @@ static int atrim_filter_frame(AVFilterLink *inlink, AVFrame *frame) · 70 unmodified lines
290 216
291 if (drop) {217 if (drop) {
292 s->eof = 1;218 s->eof = 1;
293 ff_avfilter_link_set_out_status(inlink, AVERROR_EOF, AV_NOPTS_VALUE);219 ff_inlink_set_status(inlink, AVERROR_EOF);
220 ff_outlink_set_status(ctx->outputs[0], AVERROR_EOF, frame->pts);
294 goto drop;221 goto drop;
295 }222 }
296 }223 }
@@ -324,10 +251,131 @@ static int atrim_filter_frame(AVFilterLink *inlink, AVFrame *frame) · 27 unmodified lines
324 return ff_filter_frame(ctx->outputs[0], frame);251 return ff_filter_frame(ctx->outputs[0], frame);
325 252
326drop:253drop:
254 if (!s->eof)
255 ff_filter_set_ready(ctx, 100);
327 s->nb_samples += frame->nb_samples;256 s->nb_samples += frame->nb_samples;
328 av_frame_free(&frame);257 av_frame_free(&frame);
329 return 0;258 return 0;
330}259}
260#endif // CONFIG_ATRIM_FILTER
261
262static int config_input(AVFilterLink *inlink)
263{
264 AVFilterContext *ctx = inlink->dst;
265 TrimContext *s = ctx->priv;
266 AVRational tb = (inlink->type == AVMEDIA_TYPE_VIDEO) ?
267 inlink->time_base : (AVRational){ 1, inlink->sample_rate };
268
269#if CONFIG_TRIM_FILTER
270 if (inlink->type == AVMEDIA_TYPE_VIDEO)
271 s->filter_frame = trim_filter_frame;
272#endif
273#if CONFIG_ATRIM_FILTER
274 if (inlink->type == AVMEDIA_TYPE_AUDIO)
275 s->filter_frame = atrim_filter_frame;
276#endif
277 if (s->start_time != INT64_MAX) {
278 int64_t start_pts = av_rescale_q(s->start_time, AV_TIME_BASE_Q, tb);
279 if (s->start_pts == AV_NOPTS_VALUE || start_pts < s->start_pts)
280 s->start_pts = start_pts;
281 }
282 if (s->end_time != INT64_MAX) {
283 int64_t end_pts = av_rescale_q(s->end_time, AV_TIME_BASE_Q, tb);
284 if (s->end_pts == AV_NOPTS_VALUE || end_pts > s->end_pts)
285 s->end_pts = end_pts;
286 }
287 if (s->duration)
288 s->duration_tb = av_rescale_q(s->duration, AV_TIME_BASE_Q, tb);
289
290 return 0;
291}
292
293static int activate(AVFilterContext *ctx)
294{
295 TrimContext *s = ctx->priv;
296 AVFilterLink *inlink = ctx->inputs[0];
297 AVFilterLink *outlink = ctx->outputs[0];
298
299 FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
300
301 if (!s->eof && ff_inlink_queued_frames(inlink)) {
302 AVFrame *frame = NULL;
303 int ret;
304
305 ret = ff_inlink_consume_frame(inlink, &frame);
306 if (ret < 0)
307 return ret;
308 if (ret > 0)
309 return s->filter_frame(inlink, frame);
310 }
311
312 FF_FILTER_FORWARD_STATUS(inlink, outlink);
313 FF_FILTER_FORWARD_WANTED(outlink, inlink);
314
315 return FFERROR_NOT_READY;
316}
317
318#define OFFSET(x) offsetof(TrimContext, x)
319#define COMMON_OPTS \
320 { "start", "Timestamp of the first frame that " \
321 "should be passed", OFFSET(start_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \
322 { "starti", "Timestamp of the first frame that " \
323 "should be passed", OFFSET(start_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \
324 { "end", "Timestamp of the first frame that " \
325 "should be dropped again", OFFSET(end_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \
326 { "endi", "Timestamp of the first frame that " \
327 "should be dropped again", OFFSET(end_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \
328 { "start_pts", "Timestamp of the first frame that should be " \
329 " passed", OFFSET(start_pts), AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, FLAGS }, \
330 { "end_pts", "Timestamp of the first frame that should be " \
331 "dropped again", OFFSET(end_pts), AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, FLAGS }, \
332 { "duration", "Maximum duration of the output", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, FLAGS }, \
333 { "durationi", "Maximum duration of the output", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, FLAGS },
334
335
336#if CONFIG_TRIM_FILTER
337
338#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
339static const AVOption trim_options[] = {
340 COMMON_OPTS
341 { "start_frame", "Number of the first frame that should be passed "
342 "to the output", OFFSET(start_frame), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, FLAGS },
343 { "end_frame", "Number of the first frame that should be dropped "
344 "again", OFFSET(end_frame), AV_OPT_TYPE_INT64, { .i64 = INT64_MAX }, 0, INT64_MAX, FLAGS },
345 { NULL }
346};
347#undef FLAGS
348
349AVFILTER_DEFINE_CLASS(trim);
350
351static const AVFilterPad trim_inputs[] = {
352 {
353 .name = "default",
354 .type = AVMEDIA_TYPE_VIDEO,
355 .config_props = config_input,
356 },
357};
358
359static const AVFilterPad trim_outputs[] = {
360 {
361 .name = "default",
362 .type = AVMEDIA_TYPE_VIDEO,
363 },
364};
365
366const AVFilter ff_vf_trim = {
367 .name = "trim",
368 .description = NULL_IF_CONFIG_SMALL("Pick one continuous section from the input, drop the rest."),
369 .init = init,
370 .activate = activate,
371 .priv_size = sizeof(TrimContext),
372 .priv_class = &trim_class,
373 FILTER_INPUTS(trim_inputs),
374 FILTER_OUTPUTS(trim_outputs),
375};
376#endif // CONFIG_TRIM_FILTER
377
378#if CONFIG_ATRIM_FILTER
331 379
332#define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM380#define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
333static const AVOption atrim_options[] = {381static const AVOption atrim_options[] = {
@@ -346,7 +394,6 @@ static const AVFilterPad atrim_inputs[] = { · 12 unmodified lines
346 {394 {
347 .name = "default",395 .name = "default",
348 .type = AVMEDIA_TYPE_AUDIO,396 .type = AVMEDIA_TYPE_AUDIO,
349 .filter_frame = atrim_filter_frame,
350 .config_props = config_input,397 .config_props = config_input,
351 },398 },
352};399};
@@ -362,6 +409,7 @@ const AVFilter ff_af_atrim = { · 9 unmodified lines
362 .name = "atrim",409 .name = "atrim",
363 .description = NULL_IF_CONFIG_SMALL("Pick one continuous section from the input, drop the rest."),410 .description = NULL_IF_CONFIG_SMALL("Pick one continuous section from the input, drop the rest."),
364 .init = init,411 .init = init,
412 .activate = activate,
365 .priv_size = sizeof(TrimContext),413 .priv_size = sizeof(TrimContext),
366 .priv_class = &atrim_class,414 .priv_class = &atrim_class,
367 .flags = AVFILTER_FLAG_METADATA_ONLY,415 .flags = AVFILTER_FLAG_METADATA_ONLY,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t