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

Unified · Split

libavfilter/trim.c+131−83
@@ -31,6 +31,7 @@ · 30 unmodified lines
3131 #include "audio.h"
3232 #include "avfilter.h"
3333 #include "internal.h"
34+#include "filters.h"
3435
3536 typedef struct TrimContext {
3637 const AVClass *class;
@@ -68,6 +69,8 @@ typedef struct TrimContext { · 31 unmodified lines
6869 int64_t next_pts;
6970
7071 int eof;
72+
73+ int (*filter_frame)(AVFilterLink *inlink, AVFrame *frame);
7174 } TrimContext;
7275
7376 static av_cold int init(AVFilterContext *ctx)
@@ -79,47 +82,6 @@ static av_cold int init(AVFilterContext *ctx) · 5 unmodified lines
7982 return 0;
8083 }
8184
82−static 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−
12385 #if CONFIG_TRIM_FILTER
12486 static int trim_filter_frame(AVFilterLink *inlink, AVFrame *frame)
12587 {
@@ -161,7 +123,8 @@ static int trim_filter_frame(AVFilterLink *inlink, AVFrame *frame) · 35 unmodified lines
161123
162124 if (drop) {
163125 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);
165128 goto drop;
166129 }
167130 }
@@ -171,49 +134,12 @@ static int trim_filter_frame(AVFilterLink *inlink, AVFrame *frame) · 3 unmodified lines
171134 return ff_filter_frame(ctx->outputs[0], frame);
172135
173136 drop:
137+ if (!s->eof)
138+ ff_filter_set_ready(ctx, 100);
174139 s->nb_frames++;
175140 av_frame_free(&frame);
176141 return 0;
177142 }
178−
179−#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
180−static 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−
190−AVFILTER_DEFINE_CLASS(trim);
191−
192−static 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−
201−static const AVFilterPad trim_outputs[] = {
202− {
203− .name = "default",
204− .type = AVMEDIA_TYPE_VIDEO,
205− },
206−};
207−
208−const 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−};
217143 #endif // CONFIG_TRIM_FILTER
218144
219145 #if CONFIG_ATRIM_FILTER
@@ -290,7 +216,8 @@ static int atrim_filter_frame(AVFilterLink *inlink, AVFrame *frame) · 70 unmodified lines
290216
291217 if (drop) {
292218 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);
294221 goto drop;
295222 }
296223 }
@@ -324,10 +251,131 @@ static int atrim_filter_frame(AVFilterLink *inlink, AVFrame *frame) · 27 unmodified lines
324251 return ff_filter_frame(ctx->outputs[0], frame);
325252
326253 drop:
254+ if (!s->eof)
255+ ff_filter_set_ready(ctx, 100);
327256 s->nb_samples += frame->nb_samples;
328257 av_frame_free(&frame);
329258 return 0;
330259 }
260+#endif // CONFIG_ATRIM_FILTER
261+
262+static 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+
293+static 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
339+static 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+
349+AVFILTER_DEFINE_CLASS(trim);
350+
351+static const AVFilterPad trim_inputs[] = {
352+ {
353+ .name = "default",
354+ .type = AVMEDIA_TYPE_VIDEO,
355+ .config_props = config_input,
356+ },
357+};
358+
359+static const AVFilterPad trim_outputs[] = {
360+ {
361+ .name = "default",
362+ .type = AVMEDIA_TYPE_VIDEO,
363+ },
364+};
365+
366+const 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
331379
332380 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
333381 static const AVOption atrim_options[] = {
@@ -346,7 +394,6 @@ static const AVFilterPad atrim_inputs[] = { · 12 unmodified lines
346394 {
347395 .name = "default",
348396 .type = AVMEDIA_TYPE_AUDIO,
349− .filter_frame = atrim_filter_frame,
350397 .config_props = config_input,
351398 },
352399 };
@@ -362,6 +409,7 @@ const AVFilter ff_af_atrim = { · 9 unmodified lines
362409 .name = "atrim",
363410 .description = NULL_IF_CONFIG_SMALL("Pick one continuous section from the input, drop the rest."),
364411 .init = init,
412+ .activate = activate,
365413 .priv_size = sizeof(TrimContext),
366414 .priv_class = &atrim_class,
367415 .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