mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-02-04 06:08:26 +02:00
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.
This commit is contained in:
parent
c6b6356635
commit
90fba27743
@ -31,6 +31,7 @@
|
||||
#include "audio.h"
|
||||
#include "avfilter.h"
|
||||
#include "internal.h"
|
||||
#include "filters.h"
|
||||
|
||||
typedef struct TrimContext {
|
||||
const AVClass *class;
|
||||
@ -68,6 +69,8 @@ typedef struct TrimContext {
|
||||
int64_t next_pts;
|
||||
|
||||
int eof;
|
||||
|
||||
int (*filter_frame)(AVFilterLink *inlink, AVFrame *frame);
|
||||
} TrimContext;
|
||||
|
||||
static av_cold int init(AVFilterContext *ctx)
|
||||
@ -79,47 +82,6 @@ static av_cold int init(AVFilterContext *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config_input(AVFilterLink *inlink)
|
||||
{
|
||||
AVFilterContext *ctx = inlink->dst;
|
||||
TrimContext *s = ctx->priv;
|
||||
AVRational tb = (inlink->type == AVMEDIA_TYPE_VIDEO) ?
|
||||
inlink->time_base : (AVRational){ 1, inlink->sample_rate };
|
||||
|
||||
if (s->start_time != INT64_MAX) {
|
||||
int64_t start_pts = av_rescale_q(s->start_time, AV_TIME_BASE_Q, tb);
|
||||
if (s->start_pts == AV_NOPTS_VALUE || start_pts < s->start_pts)
|
||||
s->start_pts = start_pts;
|
||||
}
|
||||
if (s->end_time != INT64_MAX) {
|
||||
int64_t end_pts = av_rescale_q(s->end_time, AV_TIME_BASE_Q, tb);
|
||||
if (s->end_pts == AV_NOPTS_VALUE || end_pts > s->end_pts)
|
||||
s->end_pts = end_pts;
|
||||
}
|
||||
if (s->duration)
|
||||
s->duration_tb = av_rescale_q(s->duration, AV_TIME_BASE_Q, tb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define OFFSET(x) offsetof(TrimContext, x)
|
||||
#define COMMON_OPTS \
|
||||
{ "start", "Timestamp of the first frame that " \
|
||||
"should be passed", OFFSET(start_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \
|
||||
{ "starti", "Timestamp of the first frame that " \
|
||||
"should be passed", OFFSET(start_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \
|
||||
{ "end", "Timestamp of the first frame that " \
|
||||
"should be dropped again", OFFSET(end_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \
|
||||
{ "endi", "Timestamp of the first frame that " \
|
||||
"should be dropped again", OFFSET(end_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \
|
||||
{ "start_pts", "Timestamp of the first frame that should be " \
|
||||
" passed", OFFSET(start_pts), AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, FLAGS }, \
|
||||
{ "end_pts", "Timestamp of the first frame that should be " \
|
||||
"dropped again", OFFSET(end_pts), AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, FLAGS }, \
|
||||
{ "duration", "Maximum duration of the output", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, FLAGS }, \
|
||||
{ "durationi", "Maximum duration of the output", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, FLAGS },
|
||||
|
||||
|
||||
#if CONFIG_TRIM_FILTER
|
||||
static int trim_filter_frame(AVFilterLink *inlink, AVFrame *frame)
|
||||
{
|
||||
@ -161,7 +123,8 @@ static int trim_filter_frame(AVFilterLink *inlink, AVFrame *frame)
|
||||
|
||||
if (drop) {
|
||||
s->eof = 1;
|
||||
ff_avfilter_link_set_out_status(inlink, AVERROR_EOF, AV_NOPTS_VALUE);
|
||||
ff_inlink_set_status(inlink, AVERROR_EOF);
|
||||
ff_outlink_set_status(ctx->outputs[0], AVERROR_EOF, frame->pts);
|
||||
goto drop;
|
||||
}
|
||||
}
|
||||
@ -171,49 +134,12 @@ static int trim_filter_frame(AVFilterLink *inlink, AVFrame *frame)
|
||||
return ff_filter_frame(ctx->outputs[0], frame);
|
||||
|
||||
drop:
|
||||
if (!s->eof)
|
||||
ff_filter_set_ready(ctx, 100);
|
||||
s->nb_frames++;
|
||||
av_frame_free(&frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
|
||||
static const AVOption trim_options[] = {
|
||||
COMMON_OPTS
|
||||
{ "start_frame", "Number of the first frame that should be passed "
|
||||
"to the output", OFFSET(start_frame), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, FLAGS },
|
||||
{ "end_frame", "Number of the first frame that should be dropped "
|
||||
"again", OFFSET(end_frame), AV_OPT_TYPE_INT64, { .i64 = INT64_MAX }, 0, INT64_MAX, FLAGS },
|
||||
{ NULL }
|
||||
};
|
||||
#undef FLAGS
|
||||
|
||||
AVFILTER_DEFINE_CLASS(trim);
|
||||
|
||||
static const AVFilterPad trim_inputs[] = {
|
||||
{
|
||||
.name = "default",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.filter_frame = trim_filter_frame,
|
||||
.config_props = config_input,
|
||||
},
|
||||
};
|
||||
|
||||
static const AVFilterPad trim_outputs[] = {
|
||||
{
|
||||
.name = "default",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
},
|
||||
};
|
||||
|
||||
const AVFilter ff_vf_trim = {
|
||||
.name = "trim",
|
||||
.description = NULL_IF_CONFIG_SMALL("Pick one continuous section from the input, drop the rest."),
|
||||
.init = init,
|
||||
.priv_size = sizeof(TrimContext),
|
||||
.priv_class = &trim_class,
|
||||
FILTER_INPUTS(trim_inputs),
|
||||
FILTER_OUTPUTS(trim_outputs),
|
||||
};
|
||||
#endif // CONFIG_TRIM_FILTER
|
||||
|
||||
#if CONFIG_ATRIM_FILTER
|
||||
@ -290,7 +216,8 @@ static int atrim_filter_frame(AVFilterLink *inlink, AVFrame *frame)
|
||||
|
||||
if (drop) {
|
||||
s->eof = 1;
|
||||
ff_avfilter_link_set_out_status(inlink, AVERROR_EOF, AV_NOPTS_VALUE);
|
||||
ff_inlink_set_status(inlink, AVERROR_EOF);
|
||||
ff_outlink_set_status(ctx->outputs[0], AVERROR_EOF, frame->pts);
|
||||
goto drop;
|
||||
}
|
||||
}
|
||||
@ -324,10 +251,131 @@ static int atrim_filter_frame(AVFilterLink *inlink, AVFrame *frame)
|
||||
return ff_filter_frame(ctx->outputs[0], frame);
|
||||
|
||||
drop:
|
||||
if (!s->eof)
|
||||
ff_filter_set_ready(ctx, 100);
|
||||
s->nb_samples += frame->nb_samples;
|
||||
av_frame_free(&frame);
|
||||
return 0;
|
||||
}
|
||||
#endif // CONFIG_ATRIM_FILTER
|
||||
|
||||
static int config_input(AVFilterLink *inlink)
|
||||
{
|
||||
AVFilterContext *ctx = inlink->dst;
|
||||
TrimContext *s = ctx->priv;
|
||||
AVRational tb = (inlink->type == AVMEDIA_TYPE_VIDEO) ?
|
||||
inlink->time_base : (AVRational){ 1, inlink->sample_rate };
|
||||
|
||||
#if CONFIG_TRIM_FILTER
|
||||
if (inlink->type == AVMEDIA_TYPE_VIDEO)
|
||||
s->filter_frame = trim_filter_frame;
|
||||
#endif
|
||||
#if CONFIG_ATRIM_FILTER
|
||||
if (inlink->type == AVMEDIA_TYPE_AUDIO)
|
||||
s->filter_frame = atrim_filter_frame;
|
||||
#endif
|
||||
if (s->start_time != INT64_MAX) {
|
||||
int64_t start_pts = av_rescale_q(s->start_time, AV_TIME_BASE_Q, tb);
|
||||
if (s->start_pts == AV_NOPTS_VALUE || start_pts < s->start_pts)
|
||||
s->start_pts = start_pts;
|
||||
}
|
||||
if (s->end_time != INT64_MAX) {
|
||||
int64_t end_pts = av_rescale_q(s->end_time, AV_TIME_BASE_Q, tb);
|
||||
if (s->end_pts == AV_NOPTS_VALUE || end_pts > s->end_pts)
|
||||
s->end_pts = end_pts;
|
||||
}
|
||||
if (s->duration)
|
||||
s->duration_tb = av_rescale_q(s->duration, AV_TIME_BASE_Q, tb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int activate(AVFilterContext *ctx)
|
||||
{
|
||||
TrimContext *s = ctx->priv;
|
||||
AVFilterLink *inlink = ctx->inputs[0];
|
||||
AVFilterLink *outlink = ctx->outputs[0];
|
||||
|
||||
FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
|
||||
|
||||
if (!s->eof && ff_inlink_queued_frames(inlink)) {
|
||||
AVFrame *frame = NULL;
|
||||
int ret;
|
||||
|
||||
ret = ff_inlink_consume_frame(inlink, &frame);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret > 0)
|
||||
return s->filter_frame(inlink, frame);
|
||||
}
|
||||
|
||||
FF_FILTER_FORWARD_STATUS(inlink, outlink);
|
||||
FF_FILTER_FORWARD_WANTED(outlink, inlink);
|
||||
|
||||
return FFERROR_NOT_READY;
|
||||
}
|
||||
|
||||
#define OFFSET(x) offsetof(TrimContext, x)
|
||||
#define COMMON_OPTS \
|
||||
{ "start", "Timestamp of the first frame that " \
|
||||
"should be passed", OFFSET(start_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \
|
||||
{ "starti", "Timestamp of the first frame that " \
|
||||
"should be passed", OFFSET(start_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \
|
||||
{ "end", "Timestamp of the first frame that " \
|
||||
"should be dropped again", OFFSET(end_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \
|
||||
{ "endi", "Timestamp of the first frame that " \
|
||||
"should be dropped again", OFFSET(end_time), AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX }, INT64_MIN, INT64_MAX, FLAGS }, \
|
||||
{ "start_pts", "Timestamp of the first frame that should be " \
|
||||
" passed", OFFSET(start_pts), AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, FLAGS }, \
|
||||
{ "end_pts", "Timestamp of the first frame that should be " \
|
||||
"dropped again", OFFSET(end_pts), AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, FLAGS }, \
|
||||
{ "duration", "Maximum duration of the output", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, FLAGS }, \
|
||||
{ "durationi", "Maximum duration of the output", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, FLAGS },
|
||||
|
||||
|
||||
#if CONFIG_TRIM_FILTER
|
||||
|
||||
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
|
||||
static const AVOption trim_options[] = {
|
||||
COMMON_OPTS
|
||||
{ "start_frame", "Number of the first frame that should be passed "
|
||||
"to the output", OFFSET(start_frame), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, FLAGS },
|
||||
{ "end_frame", "Number of the first frame that should be dropped "
|
||||
"again", OFFSET(end_frame), AV_OPT_TYPE_INT64, { .i64 = INT64_MAX }, 0, INT64_MAX, FLAGS },
|
||||
{ NULL }
|
||||
};
|
||||
#undef FLAGS
|
||||
|
||||
AVFILTER_DEFINE_CLASS(trim);
|
||||
|
||||
static const AVFilterPad trim_inputs[] = {
|
||||
{
|
||||
.name = "default",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.config_props = config_input,
|
||||
},
|
||||
};
|
||||
|
||||
static const AVFilterPad trim_outputs[] = {
|
||||
{
|
||||
.name = "default",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
},
|
||||
};
|
||||
|
||||
const AVFilter ff_vf_trim = {
|
||||
.name = "trim",
|
||||
.description = NULL_IF_CONFIG_SMALL("Pick one continuous section from the input, drop the rest."),
|
||||
.init = init,
|
||||
.activate = activate,
|
||||
.priv_size = sizeof(TrimContext),
|
||||
.priv_class = &trim_class,
|
||||
FILTER_INPUTS(trim_inputs),
|
||||
FILTER_OUTPUTS(trim_outputs),
|
||||
};
|
||||
#endif // CONFIG_TRIM_FILTER
|
||||
|
||||
#if CONFIG_ATRIM_FILTER
|
||||
|
||||
#define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
|
||||
static const AVOption atrim_options[] = {
|
||||
@ -346,7 +394,6 @@ static const AVFilterPad atrim_inputs[] = {
|
||||
{
|
||||
.name = "default",
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.filter_frame = atrim_filter_frame,
|
||||
.config_props = config_input,
|
||||
},
|
||||
};
|
||||
@ -362,6 +409,7 @@ const AVFilter ff_af_atrim = {
|
||||
.name = "atrim",
|
||||
.description = NULL_IF_CONFIG_SMALL("Pick one continuous section from the input, drop the rest."),
|
||||
.init = init,
|
||||
.activate = activate,
|
||||
.priv_size = sizeof(TrimContext),
|
||||
.priv_class = &atrim_class,
|
||||
.flags = AVFILTER_FLAG_METADATA_ONLY,
|
||||
|
Loading…
x
Reference in New Issue
Block a user