]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_deshake.c
ffprobe: add -show_program_version and -show_library_versions options
[ffmpeg] / libavfilter / vf_deshake.c
index 6128cb9b6057600ada7aa9d0a6ede475e118cb82..7013f6ccc1d254b72e2425d5ce89aa776d47f05b 100644 (file)
@@ -92,12 +92,14 @@ typedef struct {
     int refcount;              ///< Number of reference frames (defines averaging window)
     FILE *fp;
     Transform avg;
+    int cw;                    ///< Crop motion search to this box
+    int ch;
+    int cx;
+    int cy;
 } DeshakeContext;
 
-static int cmp(void const *ca, void const *cb)
+static int cmp(const double *a, const double *b)
 {
-    double *a = (double *) ca;
-    double *b = (double *) cb;
     return *a < *b ? -1 : ( *a > *b ? 1 : 0 );
 }
 
@@ -110,7 +112,7 @@ static double clean_mean(double *values, int count)
     int cut = count / 5;
     int x;
 
-    qsort(values, count, sizeof(double), cmp);
+    qsort(values, count, sizeof(double), (void*)cmp);
 
     for (x = cut; x < count - cut; x++) {
         mean += values[x];
@@ -343,8 +345,15 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
     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:%255s", &deshake->rx, &deshake->ry, (int *)&deshake->edge,
+        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, (int *)&deshake->edge,
                &deshake->blocksize, &deshake->contrast, (int *)&deshake->search, filename);
 
         deshake->blocksize /= 2;
@@ -355,13 +364,22 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
         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);
+
     }
     if (*filename)
         deshake->fp = fopen(filename, "w");
     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);
 
-    av_log(ctx, AV_LOG_INFO, "rx: %d, ry: %d, edge: %d blocksize: %d contrast: %d search: %d\n",
+    // Quadword align left edge of box for MMX code, adjust width if necessary
+    // to keep right margin
+    if (deshake->cx > 0) {
+        deshake->cw += deshake->cx - (deshake->cx & ~15);
+        deshake->cx &= ~15;
+    }
+
+    av_log(ctx, AV_LOG_INFO, "cx: %d, cy: %d, cw: %d, ch: %d, rx: %d, ry: %d, edge: %d blocksize: %d contrast: %d search: %d\n",
+           deshake->cx, deshake->cy, deshake->cw, deshake->ch,
            deshake->rx, deshake->ry, deshake->edge, deshake->blocksize * 2, deshake->contrast, deshake->search);
 
     return 0;
@@ -416,8 +434,28 @@ static void end_frame(AVFilterLink *link)
     char tmp[256];
     Transform orig;
 
-    // Find the most likely global motion for the current frame
-    find_motion(deshake, (deshake->ref == NULL) ? in->data[0] : deshake->ref->data[0], in->data[0], link->w, link->h, in->linesize[0], &t);
+    if (deshake->cx < 0 || deshake->cy < 0 || deshake->cw < 0 || deshake->ch < 0) {
+        // Find the most likely global motion for the current frame
+        find_motion(deshake, (deshake->ref == NULL) ? in->data[0] : deshake->ref->data[0], in->data[0], link->w, link->h, in->linesize[0], &t);
+    } else {
+        uint8_t *src1 = (deshake->ref == NULL) ? in->data[0] : deshake->ref->data[0];
+        uint8_t *src2 = in->data[0];
+
+        deshake->cx = FFMIN(deshake->cx, link->w);
+        deshake->cy = FFMIN(deshake->cy, link->h);
+
+        if ((unsigned)deshake->cx + (unsigned)deshake->cw > link->w) deshake->cw = link->w - deshake->cx;
+        if ((unsigned)deshake->cy + (unsigned)deshake->ch > link->h) deshake->ch = link->h - deshake->cy;
+
+        // Quadword align right margin
+        deshake->cw &= ~15;
+
+        src1 += deshake->cy * in->linesize[0] + deshake->cx;
+        src2 += deshake->cy * in->linesize[0] + deshake->cx;
+
+        find_motion(deshake, src1, src2, deshake->cw, deshake->ch, in->linesize[0], &t);
+    }
+
 
     // Copy transform so we can output it later to compare to the smoothed value
     orig.vector.x = t.vector.x;
@@ -508,7 +546,7 @@ AVFilter avfilter_vf_deshake = {
     .uninit = uninit,
     .query_formats = query_formats,
 
-    .inputs    = (AVFilterPad[]) {{ .name             = "default",
+    .inputs    = (const AVFilterPad[]) {{ .name       = "default",
                                     .type             = AVMEDIA_TYPE_VIDEO,
                                     .draw_slice       = draw_slice,
                                     .end_frame        = end_frame,
@@ -516,7 +554,7 @@ AVFilter avfilter_vf_deshake = {
                                     .min_perms        = AV_PERM_READ, },
                                   { .name = NULL}},
 
-    .outputs   = (AVFilterPad[]) {{ .name             = "default",
+    .outputs   = (const AVFilterPad[]) {{ .name       = "default",
                                     .type             = AVMEDIA_TYPE_VIDEO, },
                                   { .name = NULL}},
 };