Commit 34d0ea52 authored by Clément Bœsch's avatar Clément Bœsch

lavfi/deshake: support named options.

parent c0bfc2b9
...@@ -2320,8 +2320,10 @@ Attempt to fix small changes in horizontal and/or vertical shift. This ...@@ -2320,8 +2320,10 @@ Attempt to fix small changes in horizontal and/or vertical shift. This
filter helps remove camera shake from hand-holding a camera, bumping a filter helps remove camera shake from hand-holding a camera, bumping a
tripod, moving on a vehicle, etc. tripod, moving on a vehicle, etc.
The filter accepts parameters as a string of the form The filter accepts parameters as a list of @var{key}=@var{value}
"@var{x}:@var{y}:@var{w}:@var{h}:@var{rx}:@var{ry}:@var{edge}:@var{blocksize}:@var{contrast}:@var{search}:@var{filename}" pairs, separated by ":". If the key of the first options is omitted,
the arguments are interpreted according to the syntax
@var{x}:@var{y}:@var{w}:@var{h}:@var{rx}:@var{ry}:@var{edge}:@var{blocksize}:@var{contrast}:@var{search}:@var{filename}.
A description of the accepted parameters follows. A description of the accepted parameters follows.
...@@ -2351,19 +2353,18 @@ range 0-64 pixels. Default 16. ...@@ -2351,19 +2353,18 @@ range 0-64 pixels. Default 16.
@item edge @item edge
Specify how to generate pixels to fill blanks at the edge of the Specify how to generate pixels to fill blanks at the edge of the
frame. An integer from 0 to 3 as follows: frame. Available values are:
@table @option @table @samp
@item 0 @item blank, 0
Fill zeroes at blank locations Fill zeroes at blank locations
@item 1 @item original, 1
Original image at blank locations Original image at blank locations
@item 2 @item clamp, 2
Extruded edge value at blank locations Extruded edge value at blank locations
@item 3 @item mirror, 3
Mirrored edge at blank locations Mirrored edge at blank locations
@end table @end table
Default value is @samp{mirror}.
The default setting is mirror edge at blank locations.
@item blocksize @item blocksize
Specify the blocksize to use for motion search. Range 4-128 pixels, Specify the blocksize to use for motion search. Range 4-128 pixels,
...@@ -2375,8 +2376,14 @@ the specified contrast (difference between darkest and lightest ...@@ -2375,8 +2376,14 @@ the specified contrast (difference between darkest and lightest
pixels) will be considered. Range 1-255, default 125. pixels) will be considered. Range 1-255, default 125.
@item search @item search
Specify the search strategy 0 = exhaustive search, 1 = less exhaustive Specify the search strategy. Available values are:
search. Default - exhaustive search. @table @samp
@item exhaustive, 0
Set exhaustive search
@item less, 1
Set less exhaustive search.
@end table
Default value is @samp{exhaustive}.
@item filename @item filename
If set then a detailed log of the motion search is written to the If set then a detailed log of the motion search is written to the
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#define LIBAVFILTER_VERSION_MAJOR 3 #define LIBAVFILTER_VERSION_MAJOR 3
#define LIBAVFILTER_VERSION_MINOR 42 #define LIBAVFILTER_VERSION_MINOR 42
#define LIBAVFILTER_VERSION_MICRO 102 #define LIBAVFILTER_VERSION_MICRO 103
#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, \
......
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
#include "video.h" #include "video.h"
#include "libavutil/common.h" #include "libavutil/common.h"
#include "libavutil/mem.h" #include "libavutil/mem.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h" #include "libavutil/pixdesc.h"
#include "libavcodec/dsputil.h" #include "libavcodec/dsputil.h"
...@@ -86,7 +87,7 @@ typedef struct { ...@@ -86,7 +87,7 @@ typedef struct {
} Transform; } Transform;
typedef struct { typedef struct {
AVClass av_class; const AVClass *class;
AVFilterBufferRef *ref; ///< Previous frame AVFilterBufferRef *ref; ///< Previous frame
int rx; ///< Maximum horizontal shift int rx; ///< Maximum horizontal shift
int ry; ///< Maximum vertical shift int ry; ///< Maximum vertical shift
...@@ -104,8 +105,35 @@ typedef struct { ...@@ -104,8 +105,35 @@ typedef struct {
int ch; int ch;
int cx; int cx;
int cy; int cy;
char *filename; ///< Motion search detailed log filename
} DeshakeContext; } DeshakeContext;
#define OFFSET(x) offsetof(DeshakeContext, x)
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
static const AVOption deshake_options[] = {
{ "x", "set x for the rectangular search area", OFFSET(cx), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, .flags = FLAGS },
{ "y", "set y for the rectangular search area", OFFSET(cy), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, .flags = FLAGS },
{ "w", "set width for the rectangular search area", OFFSET(cw), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, .flags = FLAGS },
{ "h", "set height for the rectangular search area", OFFSET(ch), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, .flags = FLAGS },
{ "rx", "set x for the rectangular search area", OFFSET(rx), AV_OPT_TYPE_INT, {.i64=16}, 0, 64, .flags = FLAGS },
{ "ry", "set y for the rectangular search area", OFFSET(ry), AV_OPT_TYPE_INT, {.i64=16}, 0, 64, .flags = FLAGS },
{ "edge", "set edge mode", OFFSET(edge), AV_OPT_TYPE_INT, {.i64=FILL_MIRROR}, FILL_BLANK, FILL_COUNT-1, FLAGS, "edge"},
{ "blank", "fill zeroes at blank locations", 0, AV_OPT_TYPE_CONST, {.i64=FILL_BLANK}, INT_MIN, INT_MAX, FLAGS, "edge" },
{ "original", "original image at blank locations", 0, AV_OPT_TYPE_CONST, {.i64=FILL_ORIGINAL}, INT_MIN, INT_MAX, FLAGS, "edge" },
{ "clamp", "extruded edge value at blank locations", 0, AV_OPT_TYPE_CONST, {.i64=FILL_CLAMP}, INT_MIN, INT_MAX, FLAGS, "edge" },
{ "mirror", "mirrored edge at blank locations", 0, AV_OPT_TYPE_CONST, {.i64=FILL_MIRROR}, INT_MIN, INT_MAX, FLAGS, "edge" },
{ "blocksize", "set motion search blocksize", OFFSET(blocksize), AV_OPT_TYPE_INT, {.i64=8}, 4, 128, .flags = FLAGS },
{ "contrast", "set contrast threshold for blocks", OFFSET(contrast), AV_OPT_TYPE_INT, {.i64=125}, 1, 255, .flags = FLAGS },
{ "search", "set search strategy", OFFSET(search), AV_OPT_TYPE_INT, {.i64=EXHAUSTIVE}, EXHAUSTIVE, SEARCH_COUNT-1, FLAGS, "smode" },
{ "exhaustive", "exhaustive search", 0, AV_OPT_TYPE_CONST, {.i64=EXHAUSTIVE}, INT_MIN, INT_MAX, FLAGS, "smode" },
{ "less", "less exhaustive search", 0, AV_OPT_TYPE_CONST, {.i64=SMART_EXHAUSTIVE}, INT_MIN, INT_MAX, FLAGS, "smode" },
{ "filename", "set motion search detailed log file name", OFFSET(filename), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
{ NULL }
};
AVFILTER_DEFINE_CLASS(deshake);
static int cmp(const double *a, const double *b) static int cmp(const double *a, const double *b)
{ {
return *a < *b ? -1 : ( *a > *b ? 1 : 0 ); return *a < *b ? -1 : ( *a > *b ? 1 : 0 );
...@@ -334,40 +362,28 @@ static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2, ...@@ -334,40 +362,28 @@ static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2,
static av_cold int init(AVFilterContext *ctx, const char *args) static av_cold int init(AVFilterContext *ctx, const char *args)
{ {
int ret;
DeshakeContext *deshake = ctx->priv; DeshakeContext *deshake = ctx->priv;
char filename[256] = {0}; static const char *shorthand[] = {
"x", "y", "w", "h", "rx", "ry", "edge",
deshake->rx = 16; "blocksize", "contrast", "search", "filename",
deshake->ry = 16; NULL
deshake->edge = FILL_MIRROR; };
deshake->blocksize = 8;
deshake->contrast = 125;
deshake->search = EXHAUSTIVE;
deshake->refcount = 20;
deshake->cw = -1;
deshake->ch = -1;
deshake->cx = -1;
deshake->cy = -1;
if (args) {
sscanf(args, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%255s",
&deshake->cx, &deshake->cy, &deshake->cw, &deshake->ch,
&deshake->rx, &deshake->ry, &deshake->edge,
&deshake->blocksize, &deshake->contrast, &deshake->search, filename);
deshake->blocksize /= 2;
deshake->rx = av_clip(deshake->rx, 0, 64);
deshake->ry = av_clip(deshake->ry, 0, 64);
deshake->edge = av_clip(deshake->edge, FILL_BLANK, FILL_COUNT - 1);
deshake->blocksize = av_clip(deshake->blocksize, 4, 128);
deshake->contrast = av_clip(deshake->contrast, 1, 255);
deshake->search = av_clip(deshake->search, EXHAUSTIVE, SEARCH_COUNT - 1);
} deshake->refcount = 20; // XXX: add to options?
if (*filename)
deshake->fp = fopen(filename, "w"); deshake->class = &deshake_class;
av_opt_set_defaults(deshake);
ret = av_opt_set_from_string(deshake, args, shorthand, "=", ":");
if (ret < 0)
return ret;
deshake->blocksize /= 2;
deshake->blocksize = av_clip(deshake->blocksize, 4, 128);
if (deshake->filename)
deshake->fp = fopen(deshake->filename, "w");
if (deshake->fp) if (deshake->fp)
fwrite("Ori x, Avg x, Fin x, Ori y, Avg y, Fin y, Ori angle, Avg angle, Fin angle, Ori zoom, Avg zoom, Fin zoom\n", sizeof(char), 104, deshake->fp); fwrite("Ori x, Avg x, Fin x, Ori y, Avg y, Fin y, Ori angle, Avg angle, Fin angle, Ori zoom, Avg zoom, Fin zoom\n", sizeof(char), 104, deshake->fp);
...@@ -424,6 +440,7 @@ static av_cold void uninit(AVFilterContext *ctx) ...@@ -424,6 +440,7 @@ static av_cold void uninit(AVFilterContext *ctx)
if (deshake->avctx) if (deshake->avctx)
avcodec_close(deshake->avctx); avcodec_close(deshake->avctx);
av_freep(&deshake->avctx); av_freep(&deshake->avctx);
av_opt_free(deshake);
} }
static int filter_frame(AVFilterLink *link, AVFilterBufferRef *in) static int filter_frame(AVFilterLink *link, AVFilterBufferRef *in)
...@@ -565,4 +582,5 @@ AVFilter avfilter_vf_deshake = { ...@@ -565,4 +582,5 @@ AVFilter avfilter_vf_deshake = {
.query_formats = query_formats, .query_formats = query_formats,
.inputs = deshake_inputs, .inputs = deshake_inputs,
.outputs = deshake_outputs, .outputs = deshake_outputs,
.priv_class = &deshake_class,
}; };
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment