vf_deshake.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010 Georg Martius <georg.martius@web.de>
3  * Copyright (C) 2010 Daniel G. Taylor <dan@programmer-art.org>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * fast deshake / depan video filter
25  *
26  * SAD block-matching motion compensation to fix small changes in
27  * horizontal and/or vertical shift. This filter helps remove camera shake
28  * from hand-holding a camera, bumping a tripod, moving on a vehicle, etc.
29  *
30  * Algorithm:
31  * - For each frame with one previous reference frame
32  * - For each block in the frame
33  * - If contrast > threshold then find likely motion vector
34  * - For all found motion vectors
35  * - Find most common, store as global motion vector
36  * - Find most likely rotation angle
37  * - Transform image along global motion
38  *
39  * TODO:
40  * - Fill frame edges based on previous/next reference frames
41  * - Fill frame edges by stretching image near the edges?
42  * - Can this be done quickly and look decent?
43  *
44  * Dark Shikari links to http://wiki.videolan.org/SoC_x264_2010#GPU_Motion_Estimation_2
45  * for an algorithm similar to what could be used here to get the gmv
46  * It requires only a couple diamond searches + fast downscaling
47  *
48  * Special thanks to Jason Kotenko for his help with the algorithm and my
49  * inability to see simple errors in C code.
50  */
51 
52 #include "avfilter.h"
53 #include "formats.h"
54 #include "internal.h"
55 #include "video.h"
56 #include "libavutil/common.h"
57 #include "libavutil/mem.h"
58 #include "libavutil/opt.h"
59 #include "libavutil/pixdesc.h"
60 #include "libavcodec/dsputil.h"
61 
62 #include "deshake.h"
63 #include "deshake_opencl.h"
64 
65 #define CHROMA_WIDTH(link) -((-link->w) >> av_pix_fmt_desc_get(link->format)->log2_chroma_w)
66 #define CHROMA_HEIGHT(link) -((-link->h) >> av_pix_fmt_desc_get(link->format)->log2_chroma_h)
67 
68 #define OFFSET(x) offsetof(DeshakeContext, x)
69 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
70 
71 #define MAX_R 64
72 
73 static const AVOption deshake_options[] = {
74  { "x", "set x for the rectangular search area", OFFSET(cx), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, .flags = FLAGS },
75  { "y", "set y for the rectangular search area", OFFSET(cy), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, .flags = FLAGS },
76  { "w", "set width for the rectangular search area", OFFSET(cw), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, .flags = FLAGS },
77  { "h", "set height for the rectangular search area", OFFSET(ch), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, .flags = FLAGS },
78  { "rx", "set x for the rectangular search area", OFFSET(rx), AV_OPT_TYPE_INT, {.i64=16}, 0, MAX_R, .flags = FLAGS },
79  { "ry", "set y for the rectangular search area", OFFSET(ry), AV_OPT_TYPE_INT, {.i64=16}, 0, MAX_R, .flags = FLAGS },
80  { "edge", "set edge mode", OFFSET(edge), AV_OPT_TYPE_INT, {.i64=FILL_MIRROR}, FILL_BLANK, FILL_COUNT-1, FLAGS, "edge"},
81  { "blank", "fill zeroes at blank locations", 0, AV_OPT_TYPE_CONST, {.i64=FILL_BLANK}, INT_MIN, INT_MAX, FLAGS, "edge" },
82  { "original", "original image at blank locations", 0, AV_OPT_TYPE_CONST, {.i64=FILL_ORIGINAL}, INT_MIN, INT_MAX, FLAGS, "edge" },
83  { "clamp", "extruded edge value at blank locations", 0, AV_OPT_TYPE_CONST, {.i64=FILL_CLAMP}, INT_MIN, INT_MAX, FLAGS, "edge" },
84  { "mirror", "mirrored edge at blank locations", 0, AV_OPT_TYPE_CONST, {.i64=FILL_MIRROR}, INT_MIN, INT_MAX, FLAGS, "edge" },
85  { "blocksize", "set motion search blocksize", OFFSET(blocksize), AV_OPT_TYPE_INT, {.i64=8}, 4, 128, .flags = FLAGS },
86  { "contrast", "set contrast threshold for blocks", OFFSET(contrast), AV_OPT_TYPE_INT, {.i64=125}, 1, 255, .flags = FLAGS },
87  { "search", "set search strategy", OFFSET(search), AV_OPT_TYPE_INT, {.i64=EXHAUSTIVE}, EXHAUSTIVE, SEARCH_COUNT-1, FLAGS, "smode" },
88  { "exhaustive", "exhaustive search", 0, AV_OPT_TYPE_CONST, {.i64=EXHAUSTIVE}, INT_MIN, INT_MAX, FLAGS, "smode" },
89  { "less", "less exhaustive search", 0, AV_OPT_TYPE_CONST, {.i64=SMART_EXHAUSTIVE}, INT_MIN, INT_MAX, FLAGS, "smode" },
90  { "filename", "set motion search detailed log file name", OFFSET(filename), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
91  { "opencl", "use OpenCL filtering capabilities", OFFSET(opencl), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, .flags = FLAGS },
92  { NULL }
93 };
94 
95 AVFILTER_DEFINE_CLASS(deshake);
96 
97 static int cmp(const double *a, const double *b)
98 {
99  return *a < *b ? -1 : ( *a > *b ? 1 : 0 );
100 }
101 
102 /**
103  * Cleaned mean (cuts off 20% of values to remove outliers and then averages)
104  */
105 static double clean_mean(double *values, int count)
106 {
107  double mean = 0;
108  int cut = count / 5;
109  int x;
110 
111  qsort(values, count, sizeof(double), (void*)cmp);
112 
113  for (x = cut; x < count - cut; x++) {
114  mean += values[x];
115  }
116 
117  return mean / (count - cut * 2);
118 }
119 
120 /**
121  * Find the most likely shift in motion between two frames for a given
122  * macroblock. Test each block against several shifts given by the rx
123  * and ry attributes. Searches using a simple matrix of those shifts and
124  * chooses the most likely shift by the smallest difference in blocks.
125  */
126 static void find_block_motion(DeshakeContext *deshake, uint8_t *src1,
127  uint8_t *src2, int cx, int cy, int stride,
129 {
130  int x, y;
131  int diff;
132  int smallest = INT_MAX;
133  int tmp, tmp2;
134 
135  #define CMP(i, j) deshake->c.sad[0](deshake, src1 + cy * stride + cx, \
136  src2 + (j) * stride + (i), stride, \
137  deshake->blocksize)
138 
139  if (deshake->search == EXHAUSTIVE) {
140  // Compare every possible position - this is sloooow!
141  for (y = -deshake->ry; y <= deshake->ry; y++) {
142  for (x = -deshake->rx; x <= deshake->rx; x++) {
143  diff = CMP(cx - x, cy - y);
144  if (diff < smallest) {
145  smallest = diff;
146  mv->x = x;
147  mv->y = y;
148  }
149  }
150  }
151  } else if (deshake->search == SMART_EXHAUSTIVE) {
152  // Compare every other possible position and find the best match
153  for (y = -deshake->ry + 1; y < deshake->ry; y += 2) {
154  for (x = -deshake->rx + 1; x < deshake->rx; x += 2) {
155  diff = CMP(cx - x, cy - y);
156  if (diff < smallest) {
157  smallest = diff;
158  mv->x = x;
159  mv->y = y;
160  }
161  }
162  }
163 
164  // Hone in on the specific best match around the match we found above
165  tmp = mv->x;
166  tmp2 = mv->y;
167 
168  for (y = tmp2 - 1; y <= tmp2 + 1; y++) {
169  for (x = tmp - 1; x <= tmp + 1; x++) {
170  if (x == tmp && y == tmp2)
171  continue;
172 
173  diff = CMP(cx - x, cy - y);
174  if (diff < smallest) {
175  smallest = diff;
176  mv->x = x;
177  mv->y = y;
178  }
179  }
180  }
181  }
182 
183  if (smallest > 512) {
184  mv->x = -1;
185  mv->y = -1;
186  }
187  emms_c();
188  //av_log(NULL, AV_LOG_ERROR, "%d\n", smallest);
189  //av_log(NULL, AV_LOG_ERROR, "Final: (%d, %d) = %d x %d\n", cx, cy, mv->x, mv->y);
190 }
191 
192 /**
193  * Find the contrast of a given block. When searching for global motion we
194  * really only care about the high contrast blocks, so using this method we
195  * can actually skip blocks we don't care much about.
196  */
197 static int block_contrast(uint8_t *src, int x, int y, int stride, int blocksize)
198 {
199  int highest = 0;
200  int lowest = 0;
201  int i, j, pos;
202 
203  for (i = 0; i <= blocksize * 2; i++) {
204  // We use a width of 16 here to match the libavcodec sad functions
205  for (j = 0; i <= 15; i++) {
206  pos = (y - i) * stride + (x - j);
207  if (src[pos] < lowest)
208  lowest = src[pos];
209  else if (src[pos] > highest) {
210  highest = src[pos];
211  }
212  }
213  }
214 
215  return highest - lowest;
216 }
217 
218 /**
219  * Find the rotation for a given block.
220  */
221 static double block_angle(int x, int y, int cx, int cy, IntMotionVector *shift)
222 {
223  double a1, a2, diff;
224 
225  a1 = atan2(y - cy, x - cx);
226  a2 = atan2(y - cy + shift->y, x - cx + shift->x);
227 
228  diff = a2 - a1;
229 
230  return (diff > M_PI) ? diff - 2 * M_PI :
231  (diff < -M_PI) ? diff + 2 * M_PI :
232  diff;
233 }
234 
235 /**
236  * Find the estimated global motion for a scene given the most likely shift
237  * for each block in the frame. The global motion is estimated to be the
238  * same as the motion from most blocks in the frame, so if most blocks
239  * move one pixel to the right and two pixels down, this would yield a
240  * motion vector (1, -2).
241  */
242 static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2,
243  int width, int height, int stride, Transform *t)
244 {
245  int x, y;
246  IntMotionVector mv = {0, 0};
247  int counts[2*MAX_R+1][2*MAX_R+1];
248  int count_max_value = 0;
249  int contrast;
250 
251  int pos;
252  double *angles = av_malloc(sizeof(*angles) * width * height / (16 * deshake->blocksize));
253  int center_x = 0, center_y = 0;
254  double p_x, p_y;
255 
256  // Reset counts to zero
257  for (x = 0; x < deshake->rx * 2 + 1; x++) {
258  for (y = 0; y < deshake->ry * 2 + 1; y++) {
259  counts[x][y] = 0;
260  }
261  }
262 
263  pos = 0;
264  // Find motion for every block and store the motion vector in the counts
265  for (y = deshake->ry; y < height - deshake->ry - (deshake->blocksize * 2); y += deshake->blocksize * 2) {
266  // We use a width of 16 here to match the libavcodec sad functions
267  for (x = deshake->rx; x < width - deshake->rx - 16; x += 16) {
268  // If the contrast is too low, just skip this block as it probably
269  // won't be very useful to us.
270  contrast = block_contrast(src2, x, y, stride, deshake->blocksize);
271  if (contrast > deshake->contrast) {
272  //av_log(NULL, AV_LOG_ERROR, "%d\n", contrast);
273  find_block_motion(deshake, src1, src2, x, y, stride, &mv);
274  if (mv.x != -1 && mv.y != -1) {
275  counts[mv.x + deshake->rx][mv.y + deshake->ry] += 1;
276  if (x > deshake->rx && y > deshake->ry)
277  angles[pos++] = block_angle(x, y, 0, 0, &mv);
278 
279  center_x += mv.x;
280  center_y += mv.y;
281  }
282  }
283  }
284  }
285 
286  if (pos) {
287  center_x /= pos;
288  center_y /= pos;
289  t->angle = clean_mean(angles, pos);
290  if (t->angle < 0.001)
291  t->angle = 0;
292  } else {
293  t->angle = 0;
294  }
295 
296  // Find the most common motion vector in the frame and use it as the gmv
297  for (y = deshake->ry * 2; y >= 0; y--) {
298  for (x = 0; x < deshake->rx * 2 + 1; x++) {
299  //av_log(NULL, AV_LOG_ERROR, "%5d ", counts[x][y]);
300  if (counts[x][y] > count_max_value) {
301  t->vector.x = x - deshake->rx;
302  t->vector.y = y - deshake->ry;
303  count_max_value = counts[x][y];
304  }
305  }
306  //av_log(NULL, AV_LOG_ERROR, "\n");
307  }
308 
309  p_x = (center_x - width / 2);
310  p_y = (center_y - height / 2);
311  t->vector.x += (cos(t->angle)-1)*p_x - sin(t->angle)*p_y;
312  t->vector.y += sin(t->angle)*p_x + (cos(t->angle)-1)*p_y;
313 
314  // Clamp max shift & rotation?
315  t->vector.x = av_clipf(t->vector.x, -deshake->rx * 2, deshake->rx * 2);
316  t->vector.y = av_clipf(t->vector.y, -deshake->ry * 2, deshake->ry * 2);
317  t->angle = av_clipf(t->angle, -0.1, 0.1);
318 
319  //av_log(NULL, AV_LOG_ERROR, "%d x %d\n", avg->x, avg->y);
320  av_free(angles);
321 }
322 
324  int width, int height, int cw, int ch,
325  const float *matrix_y, const float *matrix_uv,
327  enum FillMethod fill, AVFrame *in, AVFrame *out)
328 {
329  int i = 0, ret = 0;
330  const float *matrixs[3];
331  int plane_w[3], plane_h[3];
332  matrixs[0] = matrix_y;
333  matrixs[1] = matrixs[2] = matrix_uv;
334  plane_w[0] = width;
335  plane_w[1] = plane_w[2] = cw;
336  plane_h[0] = height;
337  plane_h[1] = plane_h[2] = ch;
338 
339  for (i = 0; i < 3; i++) {
340  // Transform the luma and chroma planes
341  ret = avfilter_transform(in->data[i], out->data[i], in->linesize[i], out->linesize[i],
342  plane_w[i], plane_h[i], matrixs[i], interpolate, fill);
343  if (ret < 0)
344  return ret;
345  }
346  return ret;
347 }
348 
349 static av_cold int init(AVFilterContext *ctx)
350 {
351  int ret;
352  DeshakeContext *deshake = ctx->priv;
353 
354  deshake->refcount = 20; // XXX: add to options?
355  deshake->blocksize /= 2;
356  deshake->blocksize = av_clip(deshake->blocksize, 4, 128);
357 
358  if (deshake->filename)
359  deshake->fp = fopen(deshake->filename, "w");
360  if (deshake->fp)
361  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);
362 
363  // Quadword align left edge of box for MMX code, adjust width if necessary
364  // to keep right margin
365  if (deshake->cx > 0) {
366  deshake->cw += deshake->cx - (deshake->cx & ~15);
367  deshake->cx &= ~15;
368  }
369  deshake->transform = deshake_transform_c;
370  if (!CONFIG_OPENCL && deshake->opencl) {
371  av_log(ctx, AV_LOG_ERROR, "OpenCL support was not enabled in this build, cannot be selected\n");
372  return AVERROR(EINVAL);
373  }
374 
375  if (CONFIG_OPENCL && deshake->opencl) {
376  deshake->transform = ff_opencl_transform;
377  ret = ff_opencl_deshake_init(ctx);
378  if (ret < 0)
379  return ret;
380  }
381  av_log(ctx, AV_LOG_VERBOSE, "cx: %d, cy: %d, cw: %d, ch: %d, rx: %d, ry: %d, edge: %d blocksize: %d contrast: %d search: %d\n",
382  deshake->cx, deshake->cy, deshake->cw, deshake->ch,
383  deshake->rx, deshake->ry, deshake->edge, deshake->blocksize * 2, deshake->contrast, deshake->search);
384 
385  return 0;
386 }
387 
389 {
390  static const enum AVPixelFormat pix_fmts[] = {
394  };
395 
397 
398  return 0;
399 }
400 
402 {
403  DeshakeContext *deshake = link->dst->priv;
404 
405  deshake->ref = NULL;
406  deshake->last.vector.x = 0;
407  deshake->last.vector.y = 0;
408  deshake->last.angle = 0;
409  deshake->last.zoom = 0;
410 
411  deshake->avctx = avcodec_alloc_context3(NULL);
412  avpriv_dsputil_init(&deshake->c, deshake->avctx);
413 
414  return 0;
415 }
416 
417 static av_cold void uninit(AVFilterContext *ctx)
418 {
419  DeshakeContext *deshake = ctx->priv;
420  if (CONFIG_OPENCL && deshake->opencl) {
422  }
423  av_frame_free(&deshake->ref);
424  if (deshake->fp)
425  fclose(deshake->fp);
426  if (deshake->avctx)
427  avcodec_close(deshake->avctx);
428  av_freep(&deshake->avctx);
429 }
430 
432 {
433  DeshakeContext *deshake = link->dst->priv;
434  AVFilterLink *outlink = link->dst->outputs[0];
435  AVFrame *out;
436  Transform t = {{0},0}, orig = {{0},0};
437  float matrix_y[9], matrix_uv[9];
438  float alpha = 2.0 / deshake->refcount;
439  char tmp[256];
440  int ret = 0;
441 
442  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
443  if (!out) {
444  av_frame_free(&in);
445  return AVERROR(ENOMEM);
446  }
447  av_frame_copy_props(out, in);
448 
449  if (CONFIG_OPENCL && deshake->opencl) {
450  ret = ff_opencl_deshake_process_inout_buf(link->dst,in, out);
451  if (ret < 0)
452  return ret;
453  }
454 
455  if (deshake->cx < 0 || deshake->cy < 0 || deshake->cw < 0 || deshake->ch < 0) {
456  // Find the most likely global motion for the current frame
457  find_motion(deshake, (deshake->ref == NULL) ? in->data[0] : deshake->ref->data[0], in->data[0], link->w, link->h, in->linesize[0], &t);
458  } else {
459  uint8_t *src1 = (deshake->ref == NULL) ? in->data[0] : deshake->ref->data[0];
460  uint8_t *src2 = in->data[0];
461 
462  deshake->cx = FFMIN(deshake->cx, link->w);
463  deshake->cy = FFMIN(deshake->cy, link->h);
464 
465  if ((unsigned)deshake->cx + (unsigned)deshake->cw > link->w) deshake->cw = link->w - deshake->cx;
466  if ((unsigned)deshake->cy + (unsigned)deshake->ch > link->h) deshake->ch = link->h - deshake->cy;
467 
468  // Quadword align right margin
469  deshake->cw &= ~15;
470 
471  src1 += deshake->cy * in->linesize[0] + deshake->cx;
472  src2 += deshake->cy * in->linesize[0] + deshake->cx;
473 
474  find_motion(deshake, src1, src2, deshake->cw, deshake->ch, in->linesize[0], &t);
475  }
476 
477 
478  // Copy transform so we can output it later to compare to the smoothed value
479  orig.vector.x = t.vector.x;
480  orig.vector.y = t.vector.y;
481  orig.angle = t.angle;
482  orig.zoom = t.zoom;
483 
484  // Generate a one-sided moving exponential average
485  deshake->avg.vector.x = alpha * t.vector.x + (1.0 - alpha) * deshake->avg.vector.x;
486  deshake->avg.vector.y = alpha * t.vector.y + (1.0 - alpha) * deshake->avg.vector.y;
487  deshake->avg.angle = alpha * t.angle + (1.0 - alpha) * deshake->avg.angle;
488  deshake->avg.zoom = alpha * t.zoom + (1.0 - alpha) * deshake->avg.zoom;
489 
490  // Remove the average from the current motion to detect the motion that
491  // is not on purpose, just as jitter from bumping the camera
492  t.vector.x -= deshake->avg.vector.x;
493  t.vector.y -= deshake->avg.vector.y;
494  t.angle -= deshake->avg.angle;
495  t.zoom -= deshake->avg.zoom;
496 
497  // Invert the motion to undo it
498  t.vector.x *= -1;
499  t.vector.y *= -1;
500  t.angle *= -1;
501 
502  // Write statistics to file
503  if (deshake->fp) {
504  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);
505  fwrite(tmp, sizeof(char), strlen(tmp), deshake->fp);
506  }
507 
508  // Turn relative current frame motion into absolute by adding it to the
509  // last absolute motion
510  t.vector.x += deshake->last.vector.x;
511  t.vector.y += deshake->last.vector.y;
512  t.angle += deshake->last.angle;
513  t.zoom += deshake->last.zoom;
514 
515  // Shrink motion by 10% to keep things centered in the camera frame
516  t.vector.x *= 0.9;
517  t.vector.y *= 0.9;
518  t.angle *= 0.9;
519 
520  // Store the last absolute motion information
521  deshake->last.vector.x = t.vector.x;
522  deshake->last.vector.y = t.vector.y;
523  deshake->last.angle = t.angle;
524  deshake->last.zoom = t.zoom;
525 
526  // Generate a luma transformation matrix
527  avfilter_get_matrix(t.vector.x, t.vector.y, t.angle, 1.0 + t.zoom / 100.0, matrix_y);
528  // Generate a chroma transformation matrix
529  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);
530  // Transform the luma and chroma planes
531  ret = deshake->transform(link->dst, link->w, link->h, CHROMA_WIDTH(link), CHROMA_HEIGHT(link),
532  matrix_y, matrix_uv, INTERPOLATE_BILINEAR, deshake->edge, in, out);
533 
534  // Cleanup the old reference frame
535  av_frame_free(&deshake->ref);
536 
537  if (ret < 0)
538  return ret;
539 
540  // Store the current frame as the reference frame for calculating the
541  // motion of the next frame
542  deshake->ref = in;
543 
544  return ff_filter_frame(outlink, out);
545 }
546 
547 static const AVFilterPad deshake_inputs[] = {
548  {
549  .name = "default",
550  .type = AVMEDIA_TYPE_VIDEO,
551  .filter_frame = filter_frame,
552  .config_props = config_props,
553  },
554  { NULL }
555 };
556 
557 static const AVFilterPad deshake_outputs[] = {
558  {
559  .name = "default",
560  .type = AVMEDIA_TYPE_VIDEO,
561  },
562  { NULL }
563 };
564 
566  .name = "deshake",
567  .description = NULL_IF_CONFIG_SMALL("Stabilize shaky video."),
568  .priv_size = sizeof(DeshakeContext),
569  .init = init,
570  .uninit = uninit,
572  .inputs = deshake_inputs,
573  .outputs = deshake_outputs,
574  .priv_class = &deshake_class,
575 };
static int shift(int a, int b)
Definition: sonic.c:86
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:424
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
#define OFFSET(x)
Definition: vf_deshake.c:68
AVOption.
Definition: opt.h:251
int ry
Maximum vertical shift.
Definition: deshake.h:79
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:73
static const AVFilterPad outputs[]
Definition: af_ashowinfo.c:117
external API header
memory handling functions
#define FLAGS
Definition: vf_deshake.c:69
int y
Vertical shift.
Definition: deshake.h:41
About Git write you should know how to use GIT properly Luckily Git comes with excellent documentation git help man git shows you the available git< command > help man git< command > shows information about the subcommand< command > The most comprehensive manual is the website Git Reference visit they are quite exhaustive You do not need a special username or password All you need is to provide a ssh public key to the Git server admin What follows now is a basic introduction to Git and some FFmpeg specific guidelines Read it at least if you are granted commit privileges to the FFmpeg project you are expected to be familiar with these rules I if not You can get git from etc no matter how small Every one of them has been saved from looking like a fool by this many times It s very easy for stray debug output or cosmetic modifications to slip in
Definition: git-howto.txt:5
#define a1
Definition: regdef.h:47
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:143
double angle
Angle of rotation.
Definition: deshake.h:51
int stride
Definition: mace.c:144
AVFilter avfilter_vf_deshake
Definition: vf_deshake.c:565
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:308
InterpolateMethod
Definition: transform.h:39
const char * name
Pad name.
AVCodecContext * avctx
Definition: deshake.h:84
double zoom
Zoom percentage.
Definition: deshake.h:52
uint8_t
it can be given away to ff_start_frame *A reference passed to ff_filter_frame(or the deprecated ff_start_frame) is given away and must no longer be used.*A reference created with avfilter_ref_buffer belongs to the code that created it.*A reference obtained with ff_get_video_buffer or ff_get_audio_buffer belongs to the code that requested it.*A reference given as return value by the get_video_buffer or get_audio_buffer method is given away and must no longer be used.Link reference fields---------------------The AVFilterLink structure has a few AVFilterBufferRef fields.The cur_buf and out_buf were used with the deprecated start_frame/draw_slice/end_frame API and should no longer be used.src_buf
#define av_cold
Definition: attributes.h:78
AVOptions.
#define b
Definition: input.c:42
static void find_block_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2, int cx, int cy, int stride, IntMotionVector *mv)
Find the most likely shift in motion between two frames for a given macroblock.
Definition: vf_deshake.c:126
#define emms_c()
int avfilter_transform(const uint8_t *src, uint8_t *dst, int src_stride, int dst_stride, int width, int height, const float *matrix, enum InterpolateMethod interpolate, enum FillMethod fill)
Do an affine transformation with the given interpolation method.
Definition: transform.c:149
static double clean_mean(double *values, int count)
Cleaned mean (cuts off 20% of values to remove outliers and then averages)
Definition: vf_deshake.c:105
static void interpolate(float *out, float v1, float v2, int size)
Definition: twinvq.c:280
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of PIX_FMT_YUV440P and setting color_range ...
Definition: pixfmt.h:104
int(* transform)(AVFilterContext *ctx, int width, int height, int cw, int ch, const float *matrix_y, const float *matrix_uv, enum InterpolateMethod interpolate, enum FillMethod fill, AVFrame *in, AVFrame *out)
Definition: deshake.h:99
int blocksize
Size of blocks to compare.
Definition: deshake.h:81
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV422P and setting color_...
Definition: pixfmt.h:81
FILE * fp
Definition: deshake.h:88
void ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:545
#define CONFIG_OPENCL
Definition: config.h:348
A filter pad used for either input or output.
Discrete Time axis x
int avcodec_close(AVCodecContext *avctx)
Close a given AVCodecContext and free all the data associated with it (but not the AVCodecContext its...
int refcount
Number of reference frames (defines averaging window)
Definition: deshake.h:87
int rx
Maximum horizontal shift.
Definition: deshake.h:78
int ff_opencl_transform(AVFilterContext *ctx, int width, int height, int cw, int ch, const float *matrix_y, const float *matrix_uv, enum InterpolateMethod interpolate, enum FillMethod fill, AVFrame *in, AVFrame *out)
static double alpha(void *priv, double x, double y)
Definition: vf_geq.c:86
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
#define MAX_R
Definition: vf_deshake.c:71
AVFILTER_DEFINE_CLASS(deshake)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
char * filename
Motion search detailed log filename.
Definition: deshake.h:94
void * priv
private data for use by the filter
Definition: avfilter.h:545
static int filter_frame(AVFilterLink *link, AVFrame *in)
Definition: vf_deshake.c:431
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
double x
Horizontal shift.
Definition: deshake.h:45
static int query_formats(AVFilterContext *ctx)
Definition: vf_deshake.c:388
static const AVFilterPad deshake_inputs[]
Definition: vf_deshake.c:547
int contrast
Contrast threshold.
Definition: deshake.h:82
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a link
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:72
static double block_angle(int x, int y, int cx, int cy, IntMotionVector *shift)
Find the rotation for a given block.
Definition: vf_deshake.c:221
#define AV_LOG_VERBOSE
Definition: log.h:157
static int deshake_transform_c(AVFilterContext *ctx, int width, int height, int cw, int ch, const float *matrix_y, const float *matrix_uv, enum InterpolateMethod interpolate, enum FillMethod fill, AVFrame *in, AVFrame *out)
Definition: vf_deshake.c:323
FillMethod
Definition: transform.h:51
#define FFMIN(a, b)
Definition: common.h:58
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV420P and setting color_...
Definition: pixfmt.h:80
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
ret
Definition: avfilter.c:821
static void find_motion(DeshakeContext *deshake, uint8_t *src1, uint8_t *src2, int width, int height, int stride, Transform *t)
Find the estimated global motion for a scene given the most likely shift for each block in the frame...
Definition: vf_deshake.c:242
t
Definition: genspecsines3.m:6
#define a2
Definition: regdef.h:48
int edge
Edge fill method.
Definition: deshake.h:80
int search
Motion search method.
Definition: deshake.h:83
DSPContext c
Context providing optimized SAD methods.
Definition: deshake.h:85
#define diff(a, as, b, bs)
Definition: vf_phase.c:80
#define CHROMA_HEIGHT(link)
Definition: vf_deshake.c:66
static const AVOption deshake_options[]
Definition: vf_deshake.c:73
double y
Vertical shift.
Definition: deshake.h:46
static const int8_t mv[256][2]
Search all possible positions.
Definition: deshake.h:34
int ff_opencl_deshake_process_inout_buf(AVFilterContext *ctx, AVFrame *in, AVFrame *out)
NULL
Definition: eval.c:55
static int width
Definition: tests/utils.c:158
AVS_Value src
Definition: avisynth_c.h:523
static int block_contrast(uint8_t *src, int x, int y, int stride, int blocksize)
Find the contrast of a given block.
Definition: vf_deshake.c:197
AVFrame * ref
Previous frame.
Definition: deshake.h:77
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:101
Close file fclose(fid)
Transform avg
Definition: deshake.h:89
Search most possible positions (faster)
Definition: deshake.h:35
#define CHROMA_WIDTH(link)
Definition: vf_deshake.c:65
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
spectrum bins to fill(1-based indexing) for m
BYTE int const BYTE int int int height
Definition: avisynth_c.h:713
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:74
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
Filter definition.
Definition: avfilter.h:436
static int config_props(AVFilterLink *link)
Definition: vf_deshake.c:401
synthesis window for stochastic i
static av_cold int init(AVFilterContext *ctx)
Definition: vf_deshake.c:349
const char * name
filter name
Definition: avfilter.h:437
#define snprintf
Definition: snprintf.h:34
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:539
#define CMP(i, j)
static int cmp(const double *a, const double *b)
Definition: vf_deshake.c:97
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
int cw
Crop motion search to this box.
Definition: deshake.h:90
Transform last
Transform from last frame.
Definition: deshake.h:86
int ff_opencl_deshake_init(AVFilterContext *ctx)
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:68
common internal and external API header
MotionVector vector
Motion vector.
Definition: deshake.h:50
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:108
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV444P and setting color_...
Definition: pixfmt.h:82
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:75
function y
Definition: D.m:1
DSP utils.
int x
Horizontal shift.
Definition: deshake.h:40
static const AVFilterPad deshake_outputs[]
Definition: vf_deshake.c:557
void avfilter_get_matrix(float x_shift, float y_shift, float angle, float zoom, float *matrix)
Get an affine transformation matrix from a given translation, rotation, and zoom factor.
Definition: transform.c:106
An instance of a filter.
Definition: avfilter.h:524
void INT64 INT64 count
Definition: avisynth_c.h:594
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:103
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=av_sample_fmt_is_planar(in_fmt);out_planar=av_sample_fmt_is_planar(out_fmt);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_dlog(ac->avr,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> out
#define M_PI
Definition: mathematics.h:46
av_cold void avpriv_dsputil_init(DSPContext *c, AVCodecContext *avctx)
Definition: dsputil.c:2932
internal API functions
AVPixelFormat
Pixel format.
Definition: pixfmt.h:66
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_deshake.c:417
void ff_opencl_deshake_uninit(AVFilterContext *ctx)
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame This method is called when a frame is wanted on an output For an it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return values