annotate ffmpeg/libavfilter/vf_mpdecimate.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Copyright (c) 2003 Rich Felker
yading@10 3 * Copyright (c) 2012 Stefano Sabatini
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or modify
yading@10 8 * it under the terms of the GNU General Public License as published by
yading@10 9 * the Free Software Foundation; either version 2 of the License, or
yading@10 10 * (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
yading@10 15 * GNU General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU General Public License along
yading@10 18 * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
yading@10 19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
yading@10 20 */
yading@10 21
yading@10 22 /**
yading@10 23 * @file mpdecimate filter, ported from libmpcodecs/vf_decimate.c by
yading@10 24 * Rich Felker.
yading@10 25 */
yading@10 26
yading@10 27 #include "libavutil/opt.h"
yading@10 28 #include "libavutil/pixdesc.h"
yading@10 29 #include "libavutil/timestamp.h"
yading@10 30 #include "libavcodec/dsputil.h"
yading@10 31 #include "avfilter.h"
yading@10 32 #include "internal.h"
yading@10 33 #include "formats.h"
yading@10 34 #include "video.h"
yading@10 35
yading@10 36 typedef struct {
yading@10 37 const AVClass *class;
yading@10 38 int lo, hi; ///< lower and higher threshold number of differences
yading@10 39 ///< values for 8x8 blocks
yading@10 40
yading@10 41 float frac; ///< threshold of changed pixels over the total fraction
yading@10 42
yading@10 43 int max_drop_count; ///< if positive: maximum number of sequential frames to drop
yading@10 44 ///< if negative: minimum number of frames between two drops
yading@10 45
yading@10 46 int drop_count; ///< if positive: number of frames sequentially dropped
yading@10 47 ///< if negative: number of sequential frames which were not dropped
yading@10 48
yading@10 49 int hsub, vsub; ///< chroma subsampling values
yading@10 50 AVFrame *ref; ///< reference picture
yading@10 51 DSPContext dspctx; ///< context providing optimized diff routines
yading@10 52 AVCodecContext *avctx; ///< codec context required for the DSPContext
yading@10 53 } DecimateContext;
yading@10 54
yading@10 55 #define OFFSET(x) offsetof(DecimateContext, x)
yading@10 56 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
yading@10 57
yading@10 58 static const AVOption mpdecimate_options[] = {
yading@10 59 { "max", "set the maximum number of consecutive dropped frames (positive), or the minimum interval between dropped frames (negative)",
yading@10 60 OFFSET(max_drop_count), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGS },
yading@10 61 { "hi", "set high dropping threshold", OFFSET(hi), AV_OPT_TYPE_INT, {.i64=64*12}, INT_MIN, INT_MAX, FLAGS },
yading@10 62 { "lo", "set low dropping threshold", OFFSET(lo), AV_OPT_TYPE_INT, {.i64=64*5}, INT_MIN, INT_MAX, FLAGS },
yading@10 63 { "frac", "set fraction dropping threshold", OFFSET(frac), AV_OPT_TYPE_FLOAT, {.dbl=0.33}, 0, 1, FLAGS },
yading@10 64 { NULL }
yading@10 65 };
yading@10 66
yading@10 67 AVFILTER_DEFINE_CLASS(mpdecimate);
yading@10 68
yading@10 69 /**
yading@10 70 * Return 1 if the two planes are different, 0 otherwise.
yading@10 71 */
yading@10 72 static int diff_planes(AVFilterContext *ctx,
yading@10 73 uint8_t *cur, uint8_t *ref, int linesize,
yading@10 74 int w, int h)
yading@10 75 {
yading@10 76 DecimateContext *decimate = ctx->priv;
yading@10 77 DSPContext *dspctx = &decimate->dspctx;
yading@10 78
yading@10 79 int x, y;
yading@10 80 int d, c = 0;
yading@10 81 int t = (w/16)*(h/16)*decimate->frac;
yading@10 82 int16_t block[8*8];
yading@10 83
yading@10 84 /* compute difference for blocks of 8x8 bytes */
yading@10 85 for (y = 0; y < h-7; y += 4) {
yading@10 86 for (x = 8; x < w-7; x += 4) {
yading@10 87 dspctx->diff_pixels(block,
yading@10 88 cur+x+y*linesize,
yading@10 89 ref+x+y*linesize, linesize);
yading@10 90 d = dspctx->sum_abs_dctelem(block);
yading@10 91 if (d > decimate->hi)
yading@10 92 return 1;
yading@10 93 if (d > decimate->lo) {
yading@10 94 c++;
yading@10 95 if (c > t)
yading@10 96 return 1;
yading@10 97 }
yading@10 98 }
yading@10 99 }
yading@10 100 return 0;
yading@10 101 }
yading@10 102
yading@10 103 /**
yading@10 104 * Tell if the frame should be decimated, for example if it is no much
yading@10 105 * different with respect to the reference frame ref.
yading@10 106 */
yading@10 107 static int decimate_frame(AVFilterContext *ctx,
yading@10 108 AVFrame *cur, AVFrame *ref)
yading@10 109 {
yading@10 110 DecimateContext *decimate = ctx->priv;
yading@10 111 int plane;
yading@10 112
yading@10 113 if (decimate->max_drop_count > 0 &&
yading@10 114 decimate->drop_count >= decimate->max_drop_count)
yading@10 115 return 0;
yading@10 116 if (decimate->max_drop_count < 0 &&
yading@10 117 (decimate->drop_count-1) > decimate->max_drop_count)
yading@10 118 return 0;
yading@10 119
yading@10 120 for (plane = 0; ref->data[plane] && ref->linesize[plane]; plane++) {
yading@10 121 int vsub = plane == 1 || plane == 2 ? decimate->vsub : 0;
yading@10 122 int hsub = plane == 1 || plane == 2 ? decimate->hsub : 0;
yading@10 123 if (diff_planes(ctx,
yading@10 124 cur->data[plane], ref->data[plane], ref->linesize[plane],
yading@10 125 ref->width>>hsub, ref->height>>vsub))
yading@10 126 return 0;
yading@10 127 }
yading@10 128
yading@10 129 return 1;
yading@10 130 }
yading@10 131
yading@10 132 static av_cold int init(AVFilterContext *ctx)
yading@10 133 {
yading@10 134 DecimateContext *decimate = ctx->priv;
yading@10 135
yading@10 136 av_log(ctx, AV_LOG_VERBOSE, "max_drop_count:%d hi:%d lo:%d frac:%f\n",
yading@10 137 decimate->max_drop_count, decimate->hi, decimate->lo, decimate->frac);
yading@10 138
yading@10 139 decimate->avctx = avcodec_alloc_context3(NULL);
yading@10 140 if (!decimate->avctx)
yading@10 141 return AVERROR(ENOMEM);
yading@10 142 avpriv_dsputil_init(&decimate->dspctx, decimate->avctx);
yading@10 143
yading@10 144 return 0;
yading@10 145 }
yading@10 146
yading@10 147 static av_cold void uninit(AVFilterContext *ctx)
yading@10 148 {
yading@10 149 DecimateContext *decimate = ctx->priv;
yading@10 150 av_frame_free(&decimate->ref);
yading@10 151 if (decimate->avctx) {
yading@10 152 avcodec_close(decimate->avctx);
yading@10 153 av_freep(&decimate->avctx);
yading@10 154 }
yading@10 155 }
yading@10 156
yading@10 157 static int query_formats(AVFilterContext *ctx)
yading@10 158 {
yading@10 159 static const enum AVPixelFormat pix_fmts[] = {
yading@10 160 AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P,
yading@10 161 AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV411P,
yading@10 162 AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV440P,
yading@10 163 AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P,
yading@10 164 AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ440P,
yading@10 165 AV_PIX_FMT_YUVA420P,
yading@10 166 AV_PIX_FMT_NONE
yading@10 167 };
yading@10 168
yading@10 169 ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
yading@10 170
yading@10 171 return 0;
yading@10 172 }
yading@10 173
yading@10 174 static int config_input(AVFilterLink *inlink)
yading@10 175 {
yading@10 176 AVFilterContext *ctx = inlink->dst;
yading@10 177 DecimateContext *decimate = ctx->priv;
yading@10 178 const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
yading@10 179 decimate->hsub = pix_desc->log2_chroma_w;
yading@10 180 decimate->vsub = pix_desc->log2_chroma_h;
yading@10 181
yading@10 182 return 0;
yading@10 183 }
yading@10 184
yading@10 185 static int filter_frame(AVFilterLink *inlink, AVFrame *cur)
yading@10 186 {
yading@10 187 DecimateContext *decimate = inlink->dst->priv;
yading@10 188 AVFilterLink *outlink = inlink->dst->outputs[0];
yading@10 189 int ret;
yading@10 190
yading@10 191 if (decimate->ref && decimate_frame(inlink->dst, cur, decimate->ref)) {
yading@10 192 decimate->drop_count = FFMAX(1, decimate->drop_count+1);
yading@10 193 } else {
yading@10 194 av_frame_free(&decimate->ref);
yading@10 195 decimate->ref = cur;
yading@10 196 decimate->drop_count = FFMIN(-1, decimate->drop_count-1);
yading@10 197
yading@10 198 if (ret = ff_filter_frame(outlink, av_frame_clone(cur)) < 0)
yading@10 199 return ret;
yading@10 200 }
yading@10 201
yading@10 202 av_log(inlink->dst, AV_LOG_DEBUG,
yading@10 203 "%s pts:%s pts_time:%s drop_count:%d\n",
yading@10 204 decimate->drop_count > 0 ? "drop" : "keep",
yading@10 205 av_ts2str(cur->pts), av_ts2timestr(cur->pts, &inlink->time_base),
yading@10 206 decimate->drop_count);
yading@10 207
yading@10 208 if (decimate->drop_count > 0)
yading@10 209 av_frame_free(&cur);
yading@10 210
yading@10 211 return 0;
yading@10 212 }
yading@10 213
yading@10 214 static int request_frame(AVFilterLink *outlink)
yading@10 215 {
yading@10 216 DecimateContext *decimate = outlink->src->priv;
yading@10 217 AVFilterLink *inlink = outlink->src->inputs[0];
yading@10 218 int ret;
yading@10 219
yading@10 220 do {
yading@10 221 ret = ff_request_frame(inlink);
yading@10 222 } while (decimate->drop_count > 0 && ret >= 0);
yading@10 223
yading@10 224 return ret;
yading@10 225 }
yading@10 226
yading@10 227 static const AVFilterPad mpdecimate_inputs[] = {
yading@10 228 {
yading@10 229 .name = "default",
yading@10 230 .type = AVMEDIA_TYPE_VIDEO,
yading@10 231 .get_video_buffer = ff_null_get_video_buffer,
yading@10 232 .config_props = config_input,
yading@10 233 .filter_frame = filter_frame,
yading@10 234 },
yading@10 235 { NULL }
yading@10 236 };
yading@10 237
yading@10 238 static const AVFilterPad mpdecimate_outputs[] = {
yading@10 239 {
yading@10 240 .name = "default",
yading@10 241 .type = AVMEDIA_TYPE_VIDEO,
yading@10 242 .request_frame = request_frame,
yading@10 243 },
yading@10 244 { NULL }
yading@10 245 };
yading@10 246
yading@10 247 AVFilter avfilter_vf_mpdecimate = {
yading@10 248 .name = "mpdecimate",
yading@10 249 .description = NULL_IF_CONFIG_SMALL("Remove near-duplicate frames."),
yading@10 250 .init = init,
yading@10 251 .uninit = uninit,
yading@10 252
yading@10 253 .priv_size = sizeof(DecimateContext),
yading@10 254 .query_formats = query_formats,
yading@10 255 .inputs = mpdecimate_inputs,
yading@10 256 .outputs = mpdecimate_outputs,
yading@10 257 .priv_class = &mpdecimate_class,
yading@10 258 };