FFmpeg
Loading...
Searching...
No Matches
vf_deshake.c File Reference

fast deshake / depan video filter More...

#include "avfilter.h"
#include "filters.h"
#include "transform.h"
#include "video.h"
#include "libavutil/common.h"
#include "libavutil/file_open.h"
#include "libavutil/mem.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#include "libavutil/pixelutils.h"
#include "libavutil/qsort.h"

Go to the source code of this file.

Data Structures

struct  IntMotionVector
 
struct  MotionVector
 
struct  Transform
 
struct  DeshakeContext
 

Macros

#define MAX_R   64
 
#define OFFSET(x)
 
#define FLAGS   AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
 
#define CMP(i, j)
 

Enumerations

enum  SearchMethod { EXHAUSTIVE , SMART_EXHAUSTIVE , SEARCH_COUNT }
 

Functions

 AVFILTER_DEFINE_CLASS (deshake)
 
static int cmp (const void *a, const void *b)
 
static double clean_mean (double *values, int count)
 Cleaned mean (cuts off 20% of values to remove outliers and then averages)
 
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.
 
static int block_contrast (uint8_t *src, int x, int y, int stride, int blocksize)
 Find the contrast of a given block.
 
static double block_angle (int x, int y, int cx, int cy, IntMotionVector *shift)
 Find the rotation for a given block.
 
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.
 
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)
 
static av_cold int init (AVFilterContext *ctx)
 
static int config_props (AVFilterLink *link)
 
static av_cold void uninit (AVFilterContext *ctx)
 
static int filter_frame (AVFilterLink *link, AVFrame *in)
 

Variables

static const AVOption deshake_options []
 
static enum AVPixelFormat pix_fmts []
 
static const AVFilterPad deshake_inputs []
 
const FFFilter ff_vf_deshake
 

Detailed Description

fast deshake / depan video filter

SAD block-matching motion compensation to fix small changes in horizontal and/or vertical shift. This filter helps remove camera shake from hand-holding a camera, bumping a tripod, moving on a vehicle, etc.

Algorithm:

  • For each frame with one previous reference frame
    • For each block in the frame
      • If contrast > threshold then find likely motion vector
    • For all found motion vectors
      • Find most common, store as global motion vector
    • Find most likely rotation angle
    • Transform image along global motion

TODO:

  • Fill frame edges based on previous/next reference frames
  • Fill frame edges by stretching image near the edges?
    • Can this be done quickly and look decent?

Dark Shikari links to http://wiki.videolan.org/SoC_x264_2010#GPU_Motion_Estimation_2 for an algorithm similar to what could be used here to get the gmv It requires only a couple diamond searches + fast downscaling

Special thanks to Jason Kotenko for his help with the algorithm and my inability to see simple errors in C code.

Definition in file vf_deshake.c.

Macro Definition Documentation

◆ MAX_R

#define MAX_R   64

Definition at line 87 of file vf_deshake.c.

◆ OFFSET

#define OFFSET ( x)
Value:

Definition at line 117 of file vf_deshake.c.

◆ FLAGS

Definition at line 118 of file vf_deshake.c.

◆ CMP

#define CMP ( i,
j )
Value:
deshake->sad(src1 + cy * stride + cx, stride,\
src2 + (j) * stride + (i), stride)
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
const pixel * src2
#define stride
#define src1
Definition h264pred.c:141

Referenced by find_block_motion().

Enumeration Type Documentation

◆ SearchMethod

Enumerator
EXHAUSTIVE 

Search all possible positions.

SMART_EXHAUSTIVE 

Search most possible positions (faster)

SEARCH_COUNT 

Definition at line 65 of file vf_deshake.c.

Function Documentation

◆ AVFILTER_DEFINE_CLASS()

AVFILTER_DEFINE_CLASS ( deshake )

◆ cmp()

static int cmp ( const void * a,
const void * b )
static

Definition at line 144 of file vf_deshake.c.

◆ clean_mean()

static double clean_mean ( double * values,
int count )
static

Cleaned mean (cuts off 20% of values to remove outliers and then averages)

Definition at line 152 of file vf_deshake.c.

Referenced by find_motion().

◆ find_block_motion()

static void find_block_motion ( DeshakeContext * deshake,
uint8_t * src1,
uint8_t * src2,
int cx,
int cy,
int stride,
IntMotionVector * mv )
static

Find the most likely shift in motion between two frames for a given macroblock.

Test each block against several shifts given by the rx and ry attributes. Searches using a simple matrix of those shifts and chooses the most likely shift by the smallest difference in blocks.

Definition at line 173 of file vf_deshake.c.

Referenced by find_motion().

◆ block_contrast()

static int block_contrast ( uint8_t * src,
int x,
int y,
int stride,
int blocksize )
static

Find the contrast of a given block.

When searching for global motion we really only care about the high contrast blocks, so using this method we can actually skip blocks we don't care much about.

Definition at line 242 of file vf_deshake.c.

Referenced by find_motion().

◆ block_angle()

static double block_angle ( int x,
int y,
int cx,
int cy,
IntMotionVector * shift )
static

Find the rotation for a given block.

Definition at line 266 of file vf_deshake.c.

Referenced by find_motion().

◆ find_motion()

static void find_motion ( DeshakeContext * deshake,
uint8_t * src1,
uint8_t * src2,
int width,
int height,
int stride,
Transform * t )
static

Find the estimated global motion for a scene given the most likely shift for each block in the frame.

The global motion is estimated to be the same as the motion from most blocks in the frame, so if most blocks move one pixel to the right and two pixels down, this would yield a motion vector (1, -2).

Definition at line 287 of file vf_deshake.c.

Referenced by filter_frame().

◆ deshake_transform_c()

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 )
static

Definition at line 367 of file vf_deshake.c.

Referenced by init().

◆ init()

static av_cold int init ( AVFilterContext * ctx)
static

Definition at line 394 of file vf_deshake.c.

◆ config_props()

static int config_props ( AVFilterLink * link)
static

Definition at line 433 of file vf_deshake.c.

◆ uninit()

static av_cold void uninit ( AVFilterContext * ctx)
static

Definition at line 446 of file vf_deshake.c.

◆ filter_frame()

static int filter_frame ( AVFilterLink * link,
AVFrame * in )
static

Definition at line 456 of file vf_deshake.c.

Variable Documentation

◆ deshake_options

const AVOption deshake_options[]
static
Initial value:
= {
{ "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 },
{ "w", "set width for the rectangular search area", OFFSET(cw), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, .flags = FLAGS },
{ "h", "set height for the rectangular search area", OFFSET(ch), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, .flags = FLAGS },
{ "rx", "set x for the rectangular search area", OFFSET(rx), AV_OPT_TYPE_INT, {.i64=16}, 0, MAX_R, .flags = FLAGS },
{ "ry", "set y for the rectangular search area", OFFSET(ry), AV_OPT_TYPE_INT, {.i64=16}, 0, MAX_R, .flags = FLAGS },
{ "edge", "set edge mode", OFFSET(edge), AV_OPT_TYPE_INT, {.i64=FILL_MIRROR}, FILL_BLANK, FILL_COUNT-1, FLAGS, .unit = "edge"},
{ "blank", "fill zeroes at blank locations", 0, AV_OPT_TYPE_CONST, {.i64=FILL_BLANK}, INT_MIN, INT_MAX, FLAGS, .unit = "edge" },
{ "original", "original image at blank locations", 0, AV_OPT_TYPE_CONST, {.i64=FILL_ORIGINAL}, INT_MIN, INT_MAX, FLAGS, .unit = "edge" },
{ "clamp", "extruded edge value at blank locations", 0, AV_OPT_TYPE_CONST, {.i64=FILL_CLAMP}, INT_MIN, INT_MAX, FLAGS, .unit = "edge" },
{ "mirror", "mirrored edge at blank locations", 0, AV_OPT_TYPE_CONST, {.i64=FILL_MIRROR}, INT_MIN, INT_MAX, FLAGS, .unit = "edge" },
{ "blocksize", "set motion search blocksize", OFFSET(blocksize), AV_OPT_TYPE_INT, {.i64=8}, 4, 128, .flags = FLAGS },
{ "contrast", "set contrast threshold for blocks", OFFSET(contrast), AV_OPT_TYPE_INT, {.i64=125}, 1, 255, .flags = FLAGS },
{ "search", "set search strategy", OFFSET(search), AV_OPT_TYPE_INT, {.i64=EXHAUSTIVE}, EXHAUSTIVE, SEARCH_COUNT-1, FLAGS, .unit = "smode" },
{ "exhaustive", "exhaustive search", 0, AV_OPT_TYPE_CONST, {.i64=EXHAUSTIVE}, INT_MIN, INT_MAX, FLAGS, .unit = "smode" },
{ "less", "less exhaustive search", 0, AV_OPT_TYPE_CONST, {.i64=SMART_EXHAUSTIVE}, INT_MIN, INT_MAX, FLAGS, .unit = "smode" },
{ "filename", "set motion search detailed log file name", OFFSET(filename), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
{ "opencl", "ignored", OFFSET(opencl), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS },
{ NULL }
}
#define FLAGS
Definition cmdutils.c:598
#define NULL
Definition coverity.c:32
#define OFFSET(x)
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition opt.h:326
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
@ FILL_BLANK
Definition transform.h:52
@ FILL_MIRROR
Definition transform.h:55
@ FILL_COUNT
Definition transform.h:56
@ FILL_CLAMP
Definition transform.h:54
@ FILL_ORIGINAL
Definition transform.h:53
@ SEARCH_COUNT
Definition vf_deshake.c:68
@ SMART_EXHAUSTIVE
Search most possible positions (faster)
Definition vf_deshake.c:67
@ EXHAUSTIVE
Search all possible positions.
Definition vf_deshake.c:66
#define MAX_R
Definition vf_deshake.c:87
static float search(FOCContext *foc, int pass, int maxpass, int xmin, int xmax, int ymin, int ymax, int *best_x, int *best_y, float best_score)

Definition at line 120 of file vf_deshake.c.

◆ pix_fmts

enum AVPixelFormat pix_fmts[]
static
Initial value:
= {
}
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition pixfmt.h:106
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:77
@ AV_PIX_FMT_YUVJ440P
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range
Definition pixfmt.h:107
@ AV_PIX_FMT_YUV410P
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition pixfmt.h:79
@ AV_PIX_FMT_YUV411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition pixfmt.h:80
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition pixfmt.h:78
@ AV_PIX_FMT_YUVJ422P
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
Definition pixfmt.h:86
@ AV_PIX_FMT_YUVJ444P
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition pixfmt.h:87
@ AV_PIX_FMT_YUVJ420P
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition pixfmt.h:85

Definition at line 427 of file vf_deshake.c.

◆ deshake_inputs

const AVFilterPad deshake_inputs[]
static
Initial value:
= {
{
.name = "default",
.filter_frame = filter_frame,
.config_props = config_props,
},
}
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
Definition dolby_e.c:1067
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
static int config_props(AVBitStreamFilterLink *link)
Definition source.c:181

Definition at line 583 of file vf_deshake.c.

◆ ff_vf_deshake

const FFFilter ff_vf_deshake
Initial value:
= {
.p.name = "deshake",
.p.description = NULL_IF_CONFIG_SMALL("Stabilize shaky video."),
.p.priv_class = &deshake_class,
.priv_size = sizeof(DeshakeContext),
.init = init,
}
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
static av_cold void uninit(AVBitStreamFilterContext *ctx)
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
#define FILTER_PIXFMTS_ARRAY(array)
Definition filters.h:244
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
static enum AVPixelFormat pix_fmts[]
Definition libkvazaar.c:296
static const AVFilterPad deshake_inputs[]
Definition vf_deshake.c:583
const AVFilterPad ff_video_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_VIDEO.
Definition video.c:37

Definition at line 592 of file vf_deshake.c.