lavfi/select: add support to options
Add options introspection, and improve error feedback.
This commit is contained in:
parent
c214cd18e2
commit
6ba1f28008
@ -4637,9 +4637,14 @@ Below is a description of the currently available multimedia filters.
|
|||||||
@section aselect, select
|
@section aselect, select
|
||||||
Select frames to pass in output.
|
Select frames to pass in output.
|
||||||
|
|
||||||
It accepts in input an expression, which is evaluated for each input
|
These filters accept a single option @option{expr} or @option{e}
|
||||||
frame. If the expression is evaluated to a non-zero value, the frame
|
specifying the select expression, which can be specified either by
|
||||||
is selected and passed to the output, otherwise it is discarded.
|
specyfing @code{expr=VALUE} or specifying the expression
|
||||||
|
alone.
|
||||||
|
|
||||||
|
The select expression is evaluated for each input frame. If the
|
||||||
|
evaluation result is a non-zero value, the frame is selected and
|
||||||
|
passed to the output, otherwise it is discarded.
|
||||||
|
|
||||||
The expression can contain the following constants:
|
The expression can contain the following constants:
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "libavutil/eval.h"
|
#include "libavutil/eval.h"
|
||||||
#include "libavutil/fifo.h"
|
#include "libavutil/fifo.h"
|
||||||
#include "libavutil/internal.h"
|
#include "libavutil/internal.h"
|
||||||
|
#include "libavutil/opt.h"
|
||||||
#include "avfilter.h"
|
#include "avfilter.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "formats.h"
|
#include "formats.h"
|
||||||
@ -123,7 +124,9 @@ enum var_name {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
const AVClass *class;
|
||||||
AVExpr *expr;
|
AVExpr *expr;
|
||||||
|
char *expr_str;
|
||||||
double var_values[VAR_VARS_NB];
|
double var_values[VAR_VARS_NB];
|
||||||
int do_scene_detect; ///< 1 if the expression requires scene detection variables, 0 otherwise
|
int do_scene_detect; ///< 1 if the expression requires scene detection variables, 0 otherwise
|
||||||
#if CONFIG_AVCODEC
|
#if CONFIG_AVCODEC
|
||||||
@ -135,22 +138,33 @@ typedef struct {
|
|||||||
double select;
|
double select;
|
||||||
} SelectContext;
|
} SelectContext;
|
||||||
|
|
||||||
static av_cold int init(AVFilterContext *ctx, const char *args)
|
#define OFFSET(x) offsetof(SelectContext, x)
|
||||||
|
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM
|
||||||
|
static const AVOption options[] = {
|
||||||
|
{ "expr", "set selection expression", OFFSET(expr_str), AV_OPT_TYPE_STRING, {.str = "1"}, 0, 0, FLAGS },
|
||||||
|
{ "e", "set selection expression", OFFSET(expr_str), AV_OPT_TYPE_STRING, {.str = "1"}, 0, 0, FLAGS },
|
||||||
|
{NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
static av_cold int init(AVFilterContext *ctx, const char *args, const AVClass *class)
|
||||||
{
|
{
|
||||||
SelectContext *select = ctx->priv;
|
SelectContext *select = ctx->priv;
|
||||||
|
const char *shorthand[] = { "expr", NULL };
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if ((ret = av_expr_parse(&select->expr, args ? args : "1",
|
select->class = class;
|
||||||
|
av_opt_set_defaults(select);
|
||||||
|
|
||||||
|
if ((ret = av_opt_set_from_string(select, args, shorthand, "=", ":")) < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if ((ret = av_expr_parse(&select->expr, select->expr_str,
|
||||||
var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
|
var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) {
|
||||||
av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n", args);
|
av_log(ctx, AV_LOG_ERROR, "Error while parsing expression '%s'\n", select->expr_str);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
select->do_scene_detect = !!strstr(select->expr_str, "scene");
|
||||||
|
|
||||||
select->do_scene_detect = args && strstr(args, "scene");
|
|
||||||
if (select->do_scene_detect && !CONFIG_AVCODEC) {
|
|
||||||
av_log(ctx, AV_LOG_ERROR, "Scene detection is not available without libavcodec.\n");
|
|
||||||
return AVERROR(EINVAL);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,6 +361,7 @@ static av_cold void uninit(AVFilterContext *ctx)
|
|||||||
|
|
||||||
av_expr_free(select->expr);
|
av_expr_free(select->expr);
|
||||||
select->expr = NULL;
|
select->expr = NULL;
|
||||||
|
av_opt_free(select);
|
||||||
|
|
||||||
if (select->do_scene_detect) {
|
if (select->do_scene_detect) {
|
||||||
avfilter_unref_bufferp(&select->prev_picref);
|
avfilter_unref_bufferp(&select->prev_picref);
|
||||||
@ -374,6 +389,26 @@ static int query_formats(AVFilterContext *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_ASELECT_FILTER
|
#if CONFIG_ASELECT_FILTER
|
||||||
|
|
||||||
|
#define aselect_options options
|
||||||
|
AVFILTER_DEFINE_CLASS(aselect);
|
||||||
|
|
||||||
|
static av_cold int aselect_init(AVFilterContext *ctx, const char *args)
|
||||||
|
{
|
||||||
|
SelectContext *select = ctx->priv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ret = init(ctx, args, &aselect_class)) < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (select->do_scene_detect) {
|
||||||
|
av_log(ctx, AV_LOG_ERROR, "Scene detection is ignored in aselect filter\n");
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const AVFilterPad avfilter_af_aselect_inputs[] = {
|
static const AVFilterPad avfilter_af_aselect_inputs[] = {
|
||||||
{
|
{
|
||||||
.name = "default",
|
.name = "default",
|
||||||
@ -396,15 +431,36 @@ static const AVFilterPad avfilter_af_aselect_outputs[] = {
|
|||||||
AVFilter avfilter_af_aselect = {
|
AVFilter avfilter_af_aselect = {
|
||||||
.name = "aselect",
|
.name = "aselect",
|
||||||
.description = NULL_IF_CONFIG_SMALL("Select audio frames to pass in output."),
|
.description = NULL_IF_CONFIG_SMALL("Select audio frames to pass in output."),
|
||||||
.init = init,
|
.init = aselect_init,
|
||||||
.uninit = uninit,
|
.uninit = uninit,
|
||||||
.priv_size = sizeof(SelectContext),
|
.priv_size = sizeof(SelectContext),
|
||||||
.inputs = avfilter_af_aselect_inputs,
|
.inputs = avfilter_af_aselect_inputs,
|
||||||
.outputs = avfilter_af_aselect_outputs,
|
.outputs = avfilter_af_aselect_outputs,
|
||||||
|
.priv_class = &aselect_class,
|
||||||
};
|
};
|
||||||
#endif /* CONFIG_ASELECT_FILTER */
|
#endif /* CONFIG_ASELECT_FILTER */
|
||||||
|
|
||||||
#if CONFIG_SELECT_FILTER
|
#if CONFIG_SELECT_FILTER
|
||||||
|
|
||||||
|
#define select_options options
|
||||||
|
AVFILTER_DEFINE_CLASS(select);
|
||||||
|
|
||||||
|
static av_cold int select_init(AVFilterContext *ctx, const char *args)
|
||||||
|
{
|
||||||
|
SelectContext *select = ctx->priv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ret = init(ctx, args, &select_class)) < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (select->do_scene_detect && !CONFIG_AVCODEC) {
|
||||||
|
av_log(ctx, AV_LOG_ERROR, "Scene detection is not available without libavcodec.\n");
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const AVFilterPad avfilter_vf_select_inputs[] = {
|
static const AVFilterPad avfilter_vf_select_inputs[] = {
|
||||||
{
|
{
|
||||||
.name = "default",
|
.name = "default",
|
||||||
@ -429,7 +485,7 @@ static const AVFilterPad avfilter_vf_select_outputs[] = {
|
|||||||
AVFilter avfilter_vf_select = {
|
AVFilter avfilter_vf_select = {
|
||||||
.name = "select",
|
.name = "select",
|
||||||
.description = NULL_IF_CONFIG_SMALL("Select video frames to pass in output."),
|
.description = NULL_IF_CONFIG_SMALL("Select video frames to pass in output."),
|
||||||
.init = init,
|
.init = select_init,
|
||||||
.uninit = uninit,
|
.uninit = uninit,
|
||||||
.query_formats = query_formats,
|
.query_formats = query_formats,
|
||||||
|
|
||||||
@ -437,5 +493,6 @@ AVFilter avfilter_vf_select = {
|
|||||||
|
|
||||||
.inputs = avfilter_vf_select_inputs,
|
.inputs = avfilter_vf_select_inputs,
|
||||||
.outputs = avfilter_vf_select_outputs,
|
.outputs = avfilter_vf_select_outputs,
|
||||||
|
.priv_class = &select_class,
|
||||||
};
|
};
|
||||||
#endif /* CONFIG_SELECT_FILTER */
|
#endif /* CONFIG_SELECT_FILTER */
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
#define LIBAVFILTER_VERSION_MAJOR 3
|
#define LIBAVFILTER_VERSION_MAJOR 3
|
||||||
#define LIBAVFILTER_VERSION_MINOR 27
|
#define LIBAVFILTER_VERSION_MINOR 27
|
||||||
#define LIBAVFILTER_VERSION_MICRO 100
|
#define LIBAVFILTER_VERSION_MICRO 101
|
||||||
|
|
||||||
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
|
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
|
||||||
LIBAVFILTER_VERSION_MINOR, \
|
LIBAVFILTER_VERSION_MINOR, \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user