avfilter/af_afftdn: add alias for sample_noise end
[ffmpeg.git] / libavfilter / vf_vidstabtransform.c
index ca24c46..d1ec139 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "vidstabutils.h"
 
-typedef struct {
+typedef struct TransformContext {
     const AVClass *class;
 
     VSTransformData td;
@@ -39,6 +39,7 @@ typedef struct {
     VSTransformations trans;    // transformations
     char *input;                // name of transform file
     int tripod;
+    int debug;
 } TransformContext;
 
 #define OFFSET(x) offsetof(TransformContext, x)
@@ -46,29 +47,44 @@ typedef struct {
 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
 
 static const AVOption vidstabtransform_options[] = {
-    {"input",     "path to the file storing the transforms",                        OFFSET(input),
+    {"input",     "set path to the file storing the transforms", OFFSET(input),
                    AV_OPT_TYPE_STRING, {.str = DEFAULT_INPUT_NAME}, .flags = FLAGS },
-    {"smoothing", "number of frames*2 + 1 used for lowpass filtering",              OFFSETC(smoothing),
-                   AV_OPT_TYPE_INT,    {.i64 = 10},       1, 1000, FLAGS},
-    {"maxshift",  "maximal number of pixels to translate image",                    OFFSETC(maxShift),
+    {"smoothing", "set number of frames*2 + 1 used for lowpass filtering", OFFSETC(smoothing),
+                   AV_OPT_TYPE_INT,    {.i64 = 15},       0, 1000, FLAGS},
+
+    {"optalgo",   "set camera path optimization algo", OFFSETC(camPathAlgo),
+                   AV_OPT_TYPE_INT,    {.i64 = VSOptimalL1}, VSOptimalL1, VSAvg, FLAGS, "optalgo"},
+    {  "opt",     "global optimization",                                            0, // from version 1.0 on
+                   AV_OPT_TYPE_CONST,  {.i64 = VSOptimalL1 }, 0, 0, FLAGS, "optalgo"},
+    {  "gauss",   "gaussian kernel",                                                0,
+                   AV_OPT_TYPE_CONST,  {.i64 = VSGaussian }, 0, 0, FLAGS,  "optalgo"},
+    {  "avg",     "simple averaging on motion",                                     0,
+                   AV_OPT_TYPE_CONST,  {.i64 = VSAvg },      0, 0, FLAGS,  "optalgo"},
+
+    {"maxshift",  "set maximal number of pixels to translate image", OFFSETC(maxShift),
                    AV_OPT_TYPE_INT,    {.i64 = -1},      -1, 500,  FLAGS},
-    {"maxangle",  "maximal angle in rad to rotate image",                           OFFSETC(maxAngle),
+    {"maxangle",  "set maximal angle in rad to rotate image", OFFSETC(maxAngle),
                    AV_OPT_TYPE_DOUBLE, {.dbl = -1.0},  -1.0, 3.14, FLAGS},
-    {"crop",      "set cropping mode",                                              OFFSETC(crop),
+
+    {"crop",      "set cropping mode", OFFSETC(crop),
                    AV_OPT_TYPE_INT,    {.i64 = 0},        0, 1,    FLAGS, "crop"},
     {  "keep",    "keep border",                                                    0,
                    AV_OPT_TYPE_CONST,  {.i64 = VSKeepBorder }, 0, 0, FLAGS, "crop"},
     {  "black",   "black border",                                                   0,
                    AV_OPT_TYPE_CONST,  {.i64 = VSCropBorder }, 0, 0, FLAGS, "crop"},
-    {"invert",    "1: invert transforms",                                           OFFSETC(invert),
+
+    {"invert",    "invert transforms", OFFSETC(invert),
                    AV_OPT_TYPE_INT,    {.i64 = 0},        0, 1,    FLAGS},
-    {"relative",  "consider transforms as 0: absolute, 1: relative",                OFFSETC(relative),
-                   AV_OPT_TYPE_INT,    {.i64 = 1},        0, 1,    FLAGS},
-    {"zoom",      "percentage to zoom >0: zoom in, <0 zoom out",                    OFFSETC(zoom),
-                   AV_OPT_TYPE_DOUBLE, {.dbl = 0},        0, 100,  FLAGS},
-    {"optzoom",   "0: nothing, 1: determine optimal zoom (added to 'zoom')",        OFFSETC(optZoom),
+    {"relative",  "consider transforms as relative", OFFSETC(relative),
                    AV_OPT_TYPE_INT,    {.i64 = 1},        0, 1,    FLAGS},
-    {"interpol",  "type of interpolation",                                          OFFSETC(interpolType),
+    {"zoom",      "set percentage to zoom (>0: zoom in, <0: zoom out", OFFSETC(zoom),
+                   AV_OPT_TYPE_DOUBLE, {.dbl = 0},     -100, 100,  FLAGS},
+    {"optzoom",   "set optimal zoom (0: nothing, 1: optimal static zoom, 2: optimal dynamic zoom)", OFFSETC(optZoom),
+                   AV_OPT_TYPE_INT,    {.i64 = 1},        0, 2,    FLAGS},
+    {"zoomspeed", "for adative zoom: percent to zoom maximally each frame",         OFFSETC(zoomSpeed),
+                   AV_OPT_TYPE_DOUBLE, {.dbl = 0.25},     0, 5,    FLAGS},
+
+    {"interpol",  "set type of interpolation", OFFSETC(interpolType),
                    AV_OPT_TYPE_INT,    {.i64 = 2},        0, 3,    FLAGS, "interpol"},
     {  "no",      "no interpolation",                                               0,
                    AV_OPT_TYPE_CONST,  {.i64 = VS_Zero  },  0, 0,  FLAGS, "interpol"},
@@ -78,8 +94,11 @@ static const AVOption vidstabtransform_options[] = {
                    AV_OPT_TYPE_CONST,  {.i64 = VS_BiLinear},0, 0,  FLAGS, "interpol"},
     {  "bicubic", "bi-cubic",                                                       0,
                    AV_OPT_TYPE_CONST,  {.i64 = VS_BiCubic },0, 0,  FLAGS, "interpol"},
-    {"tripod",    "if 1: virtual tripod mode (equiv. to relative=0:smoothing=0)",   OFFSET(tripod),
-                   AV_OPT_TYPE_INT,    {.i64 = 0},        0, 1,    FLAGS},
+
+    {"tripod",    "enable virtual tripod mode (same as relative=0:smoothing=0)", OFFSET(tripod),
+                   AV_OPT_TYPE_BOOL,   {.i64 = 0},        0, 1,    FLAGS},
+    {"debug",     "enable debug mode and writer global motions information to file", OFFSET(debug),
+                   AV_OPT_TYPE_BOOL,   {.i64 = 0},        0, 1,    FLAGS},
     {NULL}
 };
 
@@ -88,7 +107,7 @@ AVFILTER_DEFINE_CLASS(vidstabtransform);
 static av_cold int init(AVFilterContext *ctx)
 {
     TransformContext *tc = ctx->priv;
-    vs_set_mem_and_log_functions();
+    ff_vs_init();
     tc->class = &vidstabtransform_class;
     av_log(ctx, AV_LOG_VERBOSE, "vidstabtransform filter: init %s\n", LIBVIDSTAB_VERSION);
     return 0;
@@ -113,8 +132,10 @@ static int query_formats(AVFilterContext *ctx)
         AV_PIX_FMT_NONE
     };
 
-    ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
-    return 0;
+    AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
+    if (!fmts_list)
+        return AVERROR(ENOMEM);
+    return ff_set_common_formats(ctx, fmts_list);
 }
 
 
@@ -125,6 +146,7 @@ static int config_input(AVFilterLink *inlink)
     FILE *f;
 
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
+    int is_planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR;
 
     VSTransformData *td = &(tc->td);
 
@@ -132,15 +154,15 @@ static int config_input(AVFilterLink *inlink)
     VSFrameInfo fi_dest;
 
     if (!vsFrameInfoInit(&fi_src, inlink->w, inlink->h,
-                         av_2_vs_pixel_format(ctx, inlink->format)) ||
+                         ff_av2vs_pixfmt(ctx, inlink->format)) ||
         !vsFrameInfoInit(&fi_dest, inlink->w, inlink->h,
-                         av_2_vs_pixel_format(ctx, inlink->format))) {
+                         ff_av2vs_pixfmt(ctx, inlink->format))) {
         av_log(ctx, AV_LOG_ERROR, "unknown pixel format: %i (%s)",
                inlink->format, desc->name);
         return AVERROR(EINVAL);
     }
 
-    if (fi_src.bytesPerPixel != av_get_bits_per_pixel(desc)/8 ||
+    if ((!is_planar && fi_src.bytesPerPixel != av_get_bits_per_pixel(desc)/8) ||
         fi_src.log2ChromaW != desc->log2_chroma_w ||
         fi_src.log2ChromaH != desc->log2_chroma_h) {
         av_log(ctx, AV_LOG_ERROR, "pixel-format error: bpp %i<>%i  ",
@@ -153,12 +175,15 @@ static int config_input(AVFilterLink *inlink)
 
     // set values that are not initializes by the options
     tc->conf.modName = "vidstabtransform";
-    tc->conf.verbose =1;
+    tc->conf.verbose = 1 + tc->debug;
     if (tc->tripod) {
-        av_log(ctx, AV_LOG_INFO, "Virtual tripod mode: relative=0, smoothing=0");
+        av_log(ctx, AV_LOG_INFO, "Virtual tripod mode: relative=0, smoothing=0\n");
         tc->conf.relative  = 0;
         tc->conf.smoothing = 0;
     }
+    tc->conf.simpleMotionCalculation = 0;
+    tc->conf.storeTransforms         = tc->debug;
+    tc->conf.smoothZoom              = 0;
 
     if (vsTransformDataInit(td, &tc->conf, &fi_src, &fi_dest) != VS_OK) {
         av_log(ctx, AV_LOG_ERROR, "initialization of vid.stab transform failed, please report a BUG\n");
@@ -169,24 +194,31 @@ static int config_input(AVFilterLink *inlink)
     av_log(ctx, AV_LOG_INFO, "Video transformation/stabilization settings (pass 2/2):\n");
     av_log(ctx, AV_LOG_INFO, "    input     = %s\n", tc->input);
     av_log(ctx, AV_LOG_INFO, "    smoothing = %d\n", tc->conf.smoothing);
+    av_log(ctx, AV_LOG_INFO, "    optalgo   = %s\n",
+           tc->conf.camPathAlgo == VSOptimalL1 ? "opt" :
+           (tc->conf.camPathAlgo == VSGaussian ? "gauss" : "avg"));
     av_log(ctx, AV_LOG_INFO, "    maxshift  = %d\n", tc->conf.maxShift);
     av_log(ctx, AV_LOG_INFO, "    maxangle  = %f\n", tc->conf.maxAngle);
     av_log(ctx, AV_LOG_INFO, "    crop      = %s\n", tc->conf.crop ? "Black" : "Keep");
     av_log(ctx, AV_LOG_INFO, "    relative  = %s\n", tc->conf.relative ? "True": "False");
     av_log(ctx, AV_LOG_INFO, "    invert    = %s\n", tc->conf.invert ? "True" : "False");
     av_log(ctx, AV_LOG_INFO, "    zoom      = %f\n", tc->conf.zoom);
-    av_log(ctx, AV_LOG_INFO, "    optzoom   = %s\n", tc->conf.optZoom ? "On" : "Off");
+    av_log(ctx, AV_LOG_INFO, "    optzoom   = %s\n",
+           tc->conf.optZoom == 1 ? "Static (1)" : (tc->conf.optZoom == 2 ? "Dynamic (2)" : "Off (0)"));
+    if (tc->conf.optZoom == 2)
+        av_log(ctx, AV_LOG_INFO, "    zoomspeed = %g\n", tc->conf.zoomSpeed);
     av_log(ctx, AV_LOG_INFO, "    interpol  = %s\n", getInterpolationTypeName(tc->conf.interpolType));
 
     f = fopen(tc->input, "r");
-    if (f == NULL) {
+    if (!f) {
+        int ret = AVERROR(errno);
         av_log(ctx, AV_LOG_ERROR, "cannot open input file %s\n", tc->input);
-        return AVERROR(errno);
+        return ret;
     } else {
         VSManyLocalMotions mlms;
         if (vsReadLocalMotionsFile(f, &mlms) == VS_OK) {
             // calculate the actual transforms from the local motions
-            if (vsLocalmotions2TransformsSimple(td, &mlms, &tc->trans) != VS_OK) {
+            if (vsLocalmotions2Transforms(td, &mlms, &tc->trans) != VS_OK) {
                 av_log(ctx, AV_LOG_ERROR, "calculating transformations failed\n");
                 return AVERROR(EINVAL);
             }
@@ -199,7 +231,7 @@ static int config_input(AVFilterLink *inlink)
     }
     fclose(f);
 
-    if (vsPreprocessTransforms(td, &tc->trans) != VS_OK ) {
+    if (vsPreprocessTransforms(td, &tc->trans) != VS_OK) {
         av_log(ctx, AV_LOG_ERROR, "error while preprocessing transforms\n");
         return AVERROR(EINVAL);
     }
@@ -276,7 +308,7 @@ static const AVFilterPad avfilter_vf_vidstabtransform_outputs[] = {
     { NULL }
 };
 
-AVFilter avfilter_vf_vidstabtransform = {
+AVFilter ff_vf_vidstabtransform = {
     .name          = "vidstabtransform",
     .description   = NULL_IF_CONFIG_SMALL("Transform the frames, "
                                           "pass 2 of 2 for stabilization "