]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_deshake.c
avcodec/x86: use function pointers for {put,add}_pixels_clamped
[ffmpeg] / libavfilter / vf_deshake.c
index 95a6c51413b7dbc1a4f33fc61accb16321e0489d..b5d5457c5e9431860b2abe3feb1481e62b58231b 100644 (file)
@@ -67,8 +67,6 @@
 #define OFFSET(x) offsetof(DeshakeContext, x)
 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
 
-#define MAX_R 64
-
 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 },
@@ -242,19 +240,19 @@ static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2,
 {
     int x, y;
     IntMotionVector mv = {0, 0};
-    int counts[2*MAX_R+1][2*MAX_R+1];
     int count_max_value = 0;
     int contrast;
 
     int pos;
-    double *angles = av_malloc_array(width * height / (16 * deshake->blocksize), sizeof(*angles));
     int center_x = 0, center_y = 0;
     double p_x, p_y;
 
+    av_fast_malloc(&deshake->angles, &deshake->angles_size, width * height / (16 * deshake->blocksize) * sizeof(*deshake->angles));
+
     // Reset counts to zero
     for (x = 0; x < deshake->rx * 2 + 1; x++) {
         for (y = 0; y < deshake->ry * 2 + 1; y++) {
-            counts[x][y] = 0;
+            deshake->counts[x][y] = 0;
         }
     }
 
@@ -270,9 +268,9 @@ static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2,
                 //av_log(NULL, AV_LOG_ERROR, "%d\n", contrast);
                 find_block_motion(deshake, src1, src2, x, y, stride, &mv);
                 if (mv.x != -1 && mv.y != -1) {
-                    counts[mv.x + deshake->rx][mv.y + deshake->ry] += 1;
+                    deshake->counts[mv.x + deshake->rx][mv.y + deshake->ry] += 1;
                     if (x > deshake->rx && y > deshake->ry)
-                        angles[pos++] = block_angle(x, y, 0, 0, &mv);
+                        deshake->angles[pos++] = block_angle(x, y, 0, 0, &mv);
 
                     center_x += mv.x;
                     center_y += mv.y;
@@ -284,7 +282,7 @@ static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2,
     if (pos) {
          center_x /= pos;
          center_y /= pos;
-         t->angle = clean_mean(angles, pos);
+         t->angle = clean_mean(deshake->angles, pos);
          if (t->angle < 0.001)
               t->angle = 0;
     } else {
@@ -294,11 +292,11 @@ static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2,
     // Find the most common motion vector in the frame and use it as the gmv
     for (y = deshake->ry * 2; y >= 0; y--) {
         for (x = 0; x < deshake->rx * 2 + 1; x++) {
-            //av_log(NULL, AV_LOG_ERROR, "%5d ", counts[x][y]);
-            if (counts[x][y] > count_max_value) {
-                t->vector.x = x - deshake->rx;
-                t->vector.y = y - deshake->ry;
-                count_max_value = counts[x][y];
+            //av_log(NULL, AV_LOG_ERROR, "%5d ", deshake->counts[x][y]);
+            if (deshake->counts[x][y] > count_max_value) {
+                t->vec.x = x - deshake->rx;
+                t->vec.y = y - deshake->ry;
+                count_max_value = deshake->counts[x][y];
             }
         }
         //av_log(NULL, AV_LOG_ERROR, "\n");
@@ -306,16 +304,15 @@ static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2,
 
     p_x = (center_x - width / 2.0);
     p_y = (center_y - height / 2.0);
-    t->vector.x += (cos(t->angle)-1)*p_x  - sin(t->angle)*p_y;
-    t->vector.y += sin(t->angle)*p_x  + (cos(t->angle)-1)*p_y;
+    t->vec.x += (cos(t->angle)-1)*p_x  - sin(t->angle)*p_y;
+    t->vec.y += sin(t->angle)*p_x  + (cos(t->angle)-1)*p_y;
 
     // Clamp max shift & rotation?
-    t->vector.x = av_clipf(t->vector.x, -deshake->rx * 2, deshake->rx * 2);
-    t->vector.y = av_clipf(t->vector.y, -deshake->ry * 2, deshake->ry * 2);
+    t->vec.x = av_clipf(t->vec.x, -deshake->rx * 2, deshake->rx * 2);
+    t->vec.y = av_clipf(t->vec.y, -deshake->ry * 2, deshake->ry * 2);
     t->angle = av_clipf(t->angle, -0.1, 0.1);
 
     //av_log(NULL, AV_LOG_ERROR, "%d x %d\n", avg->x, avg->y);
-    av_free(angles);
 }
 
 static int deshake_transform_c(AVFilterContext *ctx,
@@ -410,8 +407,8 @@ static int config_props(AVFilterLink *link)
     DeshakeContext *deshake = link->dst->priv;
 
     deshake->ref = NULL;
-    deshake->last.vector.x = 0;
-    deshake->last.vector.y = 0;
+    deshake->last.vec.x = 0;
+    deshake->last.vec.y = 0;
     deshake->last.angle = 0;
     deshake->last.zoom = 0;
 
@@ -425,6 +422,8 @@ static av_cold void uninit(AVFilterContext *ctx)
         ff_opencl_deshake_uninit(ctx);
     }
     av_frame_free(&deshake->ref);
+    av_freep(&deshake->angles);
+    deshake->angles_size = 0;
     if (deshake->fp)
         fclose(deshake->fp);
 }
@@ -477,57 +476,57 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
 
 
     // Copy transform so we can output it later to compare to the smoothed value
-    orig.vector.x = t.vector.x;
-    orig.vector.y = t.vector.y;
+    orig.vec.x = t.vec.x;
+    orig.vec.y = t.vec.y;
     orig.angle = t.angle;
     orig.zoom = t.zoom;
 
     // Generate a one-sided moving exponential average
-    deshake->avg.vector.x = alpha * t.vector.x + (1.0 - alpha) * deshake->avg.vector.x;
-    deshake->avg.vector.y = alpha * t.vector.y + (1.0 - alpha) * deshake->avg.vector.y;
+    deshake->avg.vec.x = alpha * t.vec.x + (1.0 - alpha) * deshake->avg.vec.x;
+    deshake->avg.vec.y = alpha * t.vec.y + (1.0 - alpha) * deshake->avg.vec.y;
     deshake->avg.angle = alpha * t.angle + (1.0 - alpha) * deshake->avg.angle;
     deshake->avg.zoom = alpha * t.zoom + (1.0 - alpha) * deshake->avg.zoom;
 
     // Remove the average from the current motion to detect the motion that
     // is not on purpose, just as jitter from bumping the camera
-    t.vector.x -= deshake->avg.vector.x;
-    t.vector.y -= deshake->avg.vector.y;
+    t.vec.x -= deshake->avg.vec.x;
+    t.vec.y -= deshake->avg.vec.y;
     t.angle -= deshake->avg.angle;
     t.zoom -= deshake->avg.zoom;
 
     // Invert the motion to undo it
-    t.vector.x *= -1;
-    t.vector.y *= -1;
+    t.vec.x *= -1;
+    t.vec.y *= -1;
     t.angle *= -1;
 
     // Write statistics to file
     if (deshake->fp) {
-        snprintf(tmp, 256, "%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f\n", orig.vector.x, deshake->avg.vector.x, t.vector.x, orig.vector.y, deshake->avg.vector.y, t.vector.y, orig.angle, deshake->avg.angle, t.angle, orig.zoom, deshake->avg.zoom, t.zoom);
+        snprintf(tmp, 256, "%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f\n", orig.vec.x, deshake->avg.vec.x, t.vec.x, orig.vec.y, deshake->avg.vec.y, t.vec.y, orig.angle, deshake->avg.angle, t.angle, orig.zoom, deshake->avg.zoom, t.zoom);
         fwrite(tmp, sizeof(char), strlen(tmp), deshake->fp);
     }
 
     // Turn relative current frame motion into absolute by adding it to the
     // last absolute motion
-    t.vector.x += deshake->last.vector.x;
-    t.vector.y += deshake->last.vector.y;
+    t.vec.x += deshake->last.vec.x;
+    t.vec.y += deshake->last.vec.y;
     t.angle += deshake->last.angle;
     t.zoom += deshake->last.zoom;
 
     // Shrink motion by 10% to keep things centered in the camera frame
-    t.vector.x *= 0.9;
-    t.vector.y *= 0.9;
+    t.vec.x *= 0.9;
+    t.vec.y *= 0.9;
     t.angle *= 0.9;
 
     // Store the last absolute motion information
-    deshake->last.vector.x = t.vector.x;
-    deshake->last.vector.y = t.vector.y;
+    deshake->last.vec.x = t.vec.x;
+    deshake->last.vec.y = t.vec.y;
     deshake->last.angle = t.angle;
     deshake->last.zoom = t.zoom;
 
     // Generate a luma transformation matrix
-    avfilter_get_matrix(t.vector.x, t.vector.y, t.angle, 1.0 + t.zoom / 100.0, matrix_y);
+    avfilter_get_matrix(t.vec.x, t.vec.y, t.angle, 1.0 + t.zoom / 100.0, matrix_y);
     // Generate a chroma transformation matrix
-    avfilter_get_matrix(t.vector.x / (link->w / CHROMA_WIDTH(link)), t.vector.y / (link->h / CHROMA_HEIGHT(link)), t.angle, 1.0 + t.zoom / 100.0, matrix_uv);
+    avfilter_get_matrix(t.vec.x / (link->w / CHROMA_WIDTH(link)), t.vec.y / (link->h / CHROMA_HEIGHT(link)), t.angle, 1.0 + t.zoom / 100.0, matrix_uv);
     // Transform the luma and chroma planes
     ret = deshake->transform(link->dst, link->w, link->h, CHROMA_WIDTH(link), CHROMA_HEIGHT(link),
                              matrix_y, matrix_uv, INTERPOLATE_BILINEAR, deshake->edge, in, out);