|
|
@@ -23,6 +23,7 @@ |
|
|
|
* set field order |
|
|
|
*/ |
|
|
|
|
|
|
|
#include "libavutil/opt.h" |
|
|
|
#include "avfilter.h" |
|
|
|
#include "internal.h" |
|
|
|
#include "video.h" |
|
|
@@ -35,39 +36,39 @@ enum SetFieldMode { |
|
|
|
}; |
|
|
|
|
|
|
|
typedef struct { |
|
|
|
const AVClass *class; |
|
|
|
enum SetFieldMode mode; |
|
|
|
} SetFieldContext; |
|
|
|
|
|
|
|
#define OFFSET(x) offsetof(SetFieldContext, x) |
|
|
|
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM |
|
|
|
|
|
|
|
static const AVOption setfield_options[] = { |
|
|
|
{"mode", "select interlace mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=MODE_AUTO}, -1, MODE_PROG, FLAGS, "mode"}, |
|
|
|
{"auto", "keep the same input field", 0, AV_OPT_TYPE_CONST, {.i64=MODE_AUTO}, INT_MIN, INT_MAX, FLAGS, "mode"}, |
|
|
|
{"bff", "mark as bottom-field-first", 0, AV_OPT_TYPE_CONST, {.i64=MODE_BFF}, INT_MIN, INT_MAX, FLAGS, "mode"}, |
|
|
|
{"tff", "mark as top-field-first", 0, AV_OPT_TYPE_CONST, {.i64=MODE_TFF}, INT_MIN, INT_MAX, FLAGS, "mode"}, |
|
|
|
{"prog", "mark as progressive", 0, AV_OPT_TYPE_CONST, {.i64=MODE_PROG}, INT_MIN, INT_MAX, FLAGS, "mode"}, |
|
|
|
{NULL} |
|
|
|
}; |
|
|
|
|
|
|
|
AVFILTER_DEFINE_CLASS(setfield); |
|
|
|
|
|
|
|
static av_cold int init(AVFilterContext *ctx, const char *args) |
|
|
|
{ |
|
|
|
SetFieldContext *setfield = ctx->priv; |
|
|
|
static const char *shorthand[] = { "mode", NULL }; |
|
|
|
|
|
|
|
setfield->mode = MODE_AUTO; |
|
|
|
|
|
|
|
if (args) { |
|
|
|
char c; |
|
|
|
if (sscanf(args, "%d%c", &setfield->mode, &c) != 1) { |
|
|
|
if (!strcmp("tff", args)) setfield->mode = MODE_TFF; |
|
|
|
else if (!strcmp("bff", args)) setfield->mode = MODE_BFF; |
|
|
|
else if (!strcmp("prog", args)) setfield->mode = MODE_PROG; |
|
|
|
else if (!strcmp("auto", args)) setfield->mode = MODE_AUTO; |
|
|
|
else { |
|
|
|
av_log(ctx, AV_LOG_ERROR, "Invalid argument '%s'\n", args); |
|
|
|
return AVERROR(EINVAL); |
|
|
|
} |
|
|
|
} else { |
|
|
|
if (setfield->mode < -1 || setfield->mode > 1) { |
|
|
|
av_log(ctx, AV_LOG_ERROR, |
|
|
|
"Provided integer value %d must be included between -1 and +1\n", |
|
|
|
setfield->mode); |
|
|
|
return AVERROR(EINVAL); |
|
|
|
} |
|
|
|
av_log(ctx, AV_LOG_WARNING, |
|
|
|
"Using -1/0/1 is deprecated, use auto/tff/bff/prog\n"); |
|
|
|
} |
|
|
|
} |
|
|
|
setfield->class = &setfield_class; |
|
|
|
av_opt_set_defaults(setfield); |
|
|
|
|
|
|
|
return 0; |
|
|
|
return av_opt_set_from_string(setfield, args, shorthand, "=", ":"); |
|
|
|
} |
|
|
|
|
|
|
|
static av_cold void uninit(AVFilterContext *ctx) |
|
|
|
{ |
|
|
|
SetFieldContext *setfield = ctx->priv; |
|
|
|
av_opt_free(setfield); |
|
|
|
} |
|
|
|
|
|
|
|
static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) |
|
|
@@ -105,8 +106,10 @@ AVFilter avfilter_vf_setfield = { |
|
|
|
.name = "setfield", |
|
|
|
.description = NULL_IF_CONFIG_SMALL("Force field for the output video frame."), |
|
|
|
.init = init, |
|
|
|
.uninit = uninit, |
|
|
|
|
|
|
|
.priv_size = sizeof(SetFieldContext), |
|
|
|
.inputs = setfield_inputs, |
|
|
|
.outputs = setfield_outputs, |
|
|
|
.priv_class = &setfield_class, |
|
|
|
}; |