54#define OFFSET(x) offsetof(VMAFMotionContext, x)
55#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
64static uint64_t
image_sad(
const uint16_t *img1,
const uint16_t *img2,
int w,
65 int h, ptrdiff_t _img1_stride, ptrdiff_t _img2_stride)
67 ptrdiff_t img1_stride = _img1_stride /
sizeof(*img1);
68 ptrdiff_t img2_stride = _img2_stride /
sizeof(*img2);
72 for (
i = 0;
i <
h;
i++) {
73 for (j = 0; j <
w; j++) {
74 sum +=
abs(img1[j] - img2[j]);
84 uint16_t *
dst,
int w,
int h, ptrdiff_t _src_stride,
85 ptrdiff_t _dst_stride)
87 ptrdiff_t src_stride = _src_stride /
sizeof(*src);
88 ptrdiff_t dst_stride = _dst_stride /
sizeof(*dst);
89 int radius = filt_w / 2;
90 int borders_left = radius;
91 int borders_right =
w - (filt_w - radius);
94 for (
i = 0;
i <
h;
i++) {
95 for (j = 0; j < borders_left; j++) {
97 for (k = 0; k < filt_w; k++) {
98 int j_tap =
FFABS(j - radius + k);
100 j_tap =
w - (j_tap -
w + 1);
102 sum +=
filter[k] *
src[
i * src_stride + j_tap];
107 for (j = borders_left; j < borders_right; j++) {
109 for (k = 0; k < filt_w; k++) {
110 sum +=
filter[k] *
src[
i * src_stride + j - radius + k];
115 for (j = borders_right; j <
w; j++) {
117 for (k = 0; k < filt_w; k++) {
118 int j_tap =
FFABS(j - radius + k);
120 j_tap =
w - (j_tap -
w + 1);
122 sum +=
filter[k] *
src[
i * src_stride + j_tap];
129#define conv_y_fn(type, bits) \
130static void convolution_y_##bits##bit(const uint16_t *filter, int filt_w, \
131 const uint8_t *_src, uint16_t *dst, \
132 int w, int h, ptrdiff_t _src_stride, \
133 ptrdiff_t _dst_stride) \
135 const type *src = (const type *) _src; \
136 ptrdiff_t src_stride = _src_stride / sizeof(*src); \
137 ptrdiff_t dst_stride = _dst_stride / sizeof(*dst); \
138 int radius = filt_w / 2; \
139 int borders_top = radius; \
140 int borders_bottom = h - (filt_w - radius); \
144 for (i = 0; i < borders_top; i++) { \
145 for (j = 0; j < w; j++) { \
147 for (k = 0; k < filt_w; k++) { \
148 int i_tap = FFABS(i - radius + k); \
150 i_tap = h - (i_tap - h + 1); \
152 sum += filter[k] * src[i_tap * src_stride + j]; \
154 dst[i * dst_stride + j] = sum >> bits; \
157 for (i = borders_top; i < borders_bottom; i++) { \
158 for (j = 0; j < w; j++) { \
160 for (k = 0; k < filt_w; k++) { \
161 sum += filter[k] * src[(i - radius + k) * src_stride + j]; \
163 dst[i * dst_stride + j] = sum >> bits; \
166 for (i = borders_bottom; i < h; i++) { \
167 for (j = 0; j < w; j++) { \
169 for (k = 0; k < filt_w; k++) { \
170 int i_tap = FFABS(i - radius + k); \
172 i_tap = h - (i_tap - h + 1); \
174 sum += filter[k] * src[i_tap * src_stride + j]; \
176 dst[i * dst_stride + j] = sum >> bits; \
186 dsp->convolution_y = bpp == 10 ? convolution_y_10bit : convolution_y_8bit;
194 s->vmafdsp.convolution_y(
s->filter, 5,
ref->data[0],
s->temp_data,
195 s->width,
s->height,
ref->linesize[0],
s->stride);
196 s->vmafdsp.convolution_x(
s->filter, 5,
s->temp_data,
s->blur_data[0],
197 s->width,
s->height,
s->stride,
s->stride);
202 uint64_t sad =
s->vmafdsp.sad(
s->blur_data[1],
s->blur_data[0],
203 s->width,
s->height,
s->stride,
s->stride);
208 FFSWAP(uint16_t *,
s->blur_data[0],
s->blur_data[1]);
210 s->motion_sum += score;
228 set_meta(&
ref->metadata,
"lavfi.vmafmotion.score", score);
230 fprintf(
s->stats_file,
231 "n:%"PRId64
" motion:%0.2lf\n",
s->data.nb_frames, score);
248 s->stride =
FFALIGN(
w *
sizeof(uint16_t), 32);
250 data_sz = (size_t)
s->stride *
h;
251 if (!(
s->blur_data[0] =
av_malloc(data_sz)) ||
257 for (
i = 0;
i < 5;
i++) {
261 vmafmotiondsp_init(&
s->vmafdsp,
desc->comp[0].depth);
278 (
desc->comp[0].depth == 8 ||
desc->comp[0].depth == 10) &&
292 ctx->inputs[0]->h,
ctx->inputs[0]->format);
301 return s->nb_frames > 0 ?
s->motion_sum /
s->nb_frames : 0.0;
315 if (
s->stats_file_str) {
316 if (!strcmp(
s->stats_file_str,
"-")) {
317 s->stats_file = stdout;
320 if (!
s->stats_file) {
337 if (
s->data.nb_frames > 0) {
341 if (
s->stats_file &&
s->stats_file != stdout)
342 fclose(
s->stats_file);
355 .p.name =
"vmafmotion",
357 .p.priv_class = &vmafmotion_class,
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
static const char *const format[]
const FFFilter ff_vf_vmafmotion
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Main libavfilter public API header.
static int FUNC metadata(CodedBitstreamContext *ctx, RWContext *rw, APVRawMetadata *current)
#define i(width, name, range_min, range_max)
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
int(* init)(AVBSFContext *ctx)
@ 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...
#define AVFILTER_FLAG_METADATA_ONLY
The filter is a "metadata" filter - it does not modify the frame data in any way.
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
#define AV_LOG_INFO
Standard information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
static av_cold void uninit(AVBitStreamFilterContext *ctx)
#define FILTER_INPUTS(array)
#define FILTER_OUTPUTS(array)
#define AVFILTER_DEFINE_CLASS(fname)
#define FILTER_QUERY_FUNC2(func)
FILE * avpriv_fopen_utf8(const char *path, const char *mode)
Open a file using a UTF-8 filename.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
#define FFSWAP(type, a, b)
Memory handling functions.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
#define AV_PIX_FMT_FLAG_BITSTREAM
All values of a component are bit-wise packed end to end.
#define AV_PIX_FMT_FLAG_RGB
The pixel format contains RGB-like data (as opposed to YUV/grayscale).
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
#define AV_PIX_FMT_FLAG_PLANAR
At least one pixel component is not in the first data plane.
#define AV_PIX_FMT_FLAG_BE
Pixel format is big-endian.
#define AV_PIX_FMT_FLAG_PAL
Pixel format has a palette in data[1], values are indexes in this palette.
AVPixelFormat
Pixel format.
Describe the class of an AVClass context structure.
A link between two filters.
AVFilterContext * dst
dest filter
A filter pad used for either input or output.
This structure describes decoded (raw) audio or video data.
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
void(* filter)(uint8_t *src, ptrdiff_t stride, int qscale)
static int ref[MAX_W *MAX_W]
static AVFormatContext * ctx
static int config_input_ref(AVFilterLink *inlink)
double ff_vmafmotion_uninit(VMAFMotionData *s)
static void do_vmafmotion(AVFilterContext *ctx, AVFrame *ref)
double ff_vmafmotion_process(VMAFMotionData *s, AVFrame *ref)
static void convolution_x(const uint16_t *filter, int filt_w, const uint16_t *src, uint16_t *dst, int w, int h, ptrdiff_t _src_stride, ptrdiff_t _dst_stride)
static uint64_t image_sad(const uint16_t *img1, const uint16_t *img2, int w, int h, ptrdiff_t _img1_stride, ptrdiff_t _img2_stride)
#define conv_y_fn(type, bits)
int ff_vmafmotion_init(VMAFMotionData *s, int w, int h, enum AVPixelFormat fmt)
static int filter_frame(AVFilterLink *inlink, AVFrame *ref)
static const AVFilterPad vmafmotion_inputs[]
static void set_meta(AVDictionary **metadata, const char *key, float d)
static int config_input_ref(AVFilterLink *inlink)
static const AVOption vmafmotion_options[]
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
static av_cold void uninit(AVFilterContext *ctx)
static const float FILTER_5[5]
const AVFilterPad ff_video_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_VIDEO.