lavfi/avcodec.c: fix copyright
[ffmpeg.git] / libavfilter / vf_deshake.c
index d010389..cdece5c 100644 (file)
@@ -67,6 +67,11 @@ enum SearchMethod {
 };
 
 typedef struct {
+    int x;             ///< Horizontal shift
+    int y;             ///< Vertical shift
+} IntMotionVector;
+
+typedef struct {
     double x;             ///< Horizontal shift
     double y;             ///< Vertical shift
 } MotionVector;
@@ -92,12 +97,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 +117,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];
@@ -127,7 +134,7 @@ static double clean_mean(double *values, int count)
  */
 static void find_block_motion(DeshakeContext *deshake, uint8_t *src1,
                               uint8_t *src2, int cx, int cy, int stride,
-                              MotionVector *mv)
+                              IntMotionVector *mv)
 {
     int x, y;
     int diff;
@@ -220,7 +227,7 @@ static int block_contrast(uint8_t *src, int x, int y, int stride, int blocksize)
 /**
  * Find the rotation for a given block.
  */
-static double block_angle(int x, int y, int cx, int cy, MotionVector *shift)
+static double block_angle(int x, int y, int cx, int cy, IntMotionVector *shift)
 {
     double a1, a2, diff;
 
@@ -245,15 +252,13 @@ static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2,
                         int width, int height, int stride, Transform *t)
 {
     int x, y;
-    MotionVector mv = {0, 0};
+    IntMotionVector mv = {0, 0};
     int counts[128][128];
     int count_max_value = 0;
     int contrast;
 
     int pos;
-    double angles[1200];
-    double totalangles = 0;
-
+    double *angles = av_malloc(sizeof(*angles) * width * height / (16 * deshake->blocksize));
     int center_x = 0, center_y = 0;
     double p_x, p_y;
 
@@ -276,7 +281,7 @@ 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[(int)(mv.x + deshake->rx)][(int)(mv.y + deshake->ry)] += 1;
+                    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);
 
@@ -287,22 +292,16 @@ static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2,
         }
     }
 
-    pos = FFMAX(1, pos);
-
-    center_x /= pos;
-    center_y /= pos;
-
-    for (x = 0; x < pos; x++) {
-        totalangles += angles[x];
+    if (pos) {
+         center_x /= pos;
+         center_y /= pos;
+         t->angle = clean_mean(angles, pos);
+         if (t->angle < 0.001)
+              t->angle = 0;
+    } else {
+         t->angle = 0;
     }
 
-    //av_log(NULL, AV_LOG_ERROR, "Angle: %lf\n", totalangles / (pos - 1));
-    t->angle = totalangles / (pos - 1);
-
-    t->angle = clean_mean(angles, pos);
-    if (t->angle < 0.001)
-        t->angle = 0;
-
     // 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++) {
@@ -327,12 +326,13 @@ static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2,
     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 av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
 {
     DeshakeContext *deshake = ctx->priv;
-    char filename[256]={0};
+    char filename[256] = {0};
 
     deshake->rx = 16;
     deshake->ry = 16;
@@ -342,8 +342,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;
@@ -354,13 +361,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(strlen(filename))
+    if (*filename)
         deshake->fp = fopen(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);
 
-    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;
@@ -389,7 +405,7 @@ static int config_props(AVFilterLink *link)
     deshake->last.angle = 0;
     deshake->last.zoom = 0;
 
-    deshake->avctx= avcodec_alloc_context3(NULL);
+    deshake->avctx = avcodec_alloc_context3(NULL);
     dsputil_init(&deshake->c, deshake->avctx);
 
     return 0;
@@ -400,8 +416,10 @@ static av_cold void uninit(AVFilterContext *ctx)
     DeshakeContext *deshake = ctx->priv;
 
     avfilter_unref_buffer(deshake->ref);
-    if(deshake->fp)
+    if (deshake->fp)
         fclose(deshake->fp);
+    avcodec_close(deshake->avctx);
+    av_freep(&deshake->avctx);
 }
 
 static void end_frame(AVFilterLink *link)
@@ -409,14 +427,33 @@ static void end_frame(AVFilterLink *link)
     DeshakeContext *deshake = link->dst->priv;
     AVFilterBufferRef *in  = link->cur_buf;
     AVFilterBufferRef *out = link->dst->outputs[0]->out_buf;
-    Transform t;
+    Transform t = {{0},0}, orig = {{0},0};
     float matrix[9];
     float alpha = 2.0 / deshake->refcount;
     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;
@@ -443,7 +480,7 @@ static void end_frame(AVFilterLink *link)
     t.angle *= -1;
 
     // Write statistics to file
-    if(deshake->fp){
+    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);
         fwrite(tmp, sizeof(char), strlen(tmp), deshake->fp);
     }
@@ -507,7 +544,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,
@@ -515,7 +552,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}},
 };