annotate ffmpeg/libavfilter/vf_cropdetect.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) 2002 A'rpi
yading@10 3 * This file is part of FFmpeg.
yading@10 4 *
yading@10 5 * FFmpeg is free software; you can redistribute it and/or modify
yading@10 6 * it under the terms of the GNU General Public License as published by
yading@10 7 * the Free Software Foundation; either version 2 of the License, or
yading@10 8 * (at your option) any later version.
yading@10 9 *
yading@10 10 * FFmpeg is distributed in the hope that it will be useful,
yading@10 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
yading@10 13 * GNU General Public License for more details.
yading@10 14 *
yading@10 15 * You should have received a copy of the GNU General Public License along
yading@10 16 * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
yading@10 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
yading@10 18 */
yading@10 19
yading@10 20 /**
yading@10 21 * @file
yading@10 22 * border detection filter
yading@10 23 * Ported from MPlayer libmpcodecs/vf_cropdetect.c.
yading@10 24 */
yading@10 25
yading@10 26 #include "libavutil/imgutils.h"
yading@10 27 #include "libavutil/internal.h"
yading@10 28 #include "libavutil/opt.h"
yading@10 29
yading@10 30 #include "avfilter.h"
yading@10 31 #include "formats.h"
yading@10 32 #include "internal.h"
yading@10 33 #include "video.h"
yading@10 34
yading@10 35 typedef struct {
yading@10 36 const AVClass *class;
yading@10 37 int x1, y1, x2, y2;
yading@10 38 int limit;
yading@10 39 int round;
yading@10 40 int reset_count;
yading@10 41 int frame_nb;
yading@10 42 int max_pixsteps[4];
yading@10 43 } CropDetectContext;
yading@10 44
yading@10 45 static int query_formats(AVFilterContext *ctx)
yading@10 46 {
yading@10 47 static const enum AVPixelFormat pix_fmts[] = {
yading@10 48 AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVJ420P,
yading@10 49 AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVJ422P,
yading@10 50 AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P,
yading@10 51 AV_PIX_FMT_YUV411P, AV_PIX_FMT_GRAY8,
yading@10 52 AV_PIX_FMT_NV12, AV_PIX_FMT_NV21,
yading@10 53 AV_PIX_FMT_NONE
yading@10 54 };
yading@10 55
yading@10 56 ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
yading@10 57 return 0;
yading@10 58 }
yading@10 59
yading@10 60 static int checkline(void *ctx, const unsigned char *src, int stride, int len, int bpp)
yading@10 61 {
yading@10 62 int total = 0;
yading@10 63 int div = len;
yading@10 64
yading@10 65 switch (bpp) {
yading@10 66 case 1:
yading@10 67 while (--len >= 0) {
yading@10 68 total += src[0];
yading@10 69 src += stride;
yading@10 70 }
yading@10 71 break;
yading@10 72 case 3:
yading@10 73 case 4:
yading@10 74 while (--len >= 0) {
yading@10 75 total += src[0] + src[1] + src[2];
yading@10 76 src += stride;
yading@10 77 }
yading@10 78 div *= 3;
yading@10 79 break;
yading@10 80 }
yading@10 81 total /= div;
yading@10 82
yading@10 83 av_log(ctx, AV_LOG_DEBUG, "total:%d\n", total);
yading@10 84 return total;
yading@10 85 }
yading@10 86
yading@10 87 static av_cold int init(AVFilterContext *ctx)
yading@10 88 {
yading@10 89 CropDetectContext *cd = ctx->priv;
yading@10 90
yading@10 91 cd->frame_nb = -2;
yading@10 92
yading@10 93 av_log(ctx, AV_LOG_VERBOSE, "limit:%d round:%d reset_count:%d\n",
yading@10 94 cd->limit, cd->round, cd->reset_count);
yading@10 95
yading@10 96 return 0;
yading@10 97 }
yading@10 98
yading@10 99 static int config_input(AVFilterLink *inlink)
yading@10 100 {
yading@10 101 AVFilterContext *ctx = inlink->dst;
yading@10 102 CropDetectContext *cd = ctx->priv;
yading@10 103
yading@10 104 av_image_fill_max_pixsteps(cd->max_pixsteps, NULL,
yading@10 105 av_pix_fmt_desc_get(inlink->format));
yading@10 106
yading@10 107 cd->x1 = inlink->w - 1;
yading@10 108 cd->y1 = inlink->h - 1;
yading@10 109 cd->x2 = 0;
yading@10 110 cd->y2 = 0;
yading@10 111
yading@10 112 return 0;
yading@10 113 }
yading@10 114
yading@10 115 static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
yading@10 116 {
yading@10 117 AVFilterContext *ctx = inlink->dst;
yading@10 118 CropDetectContext *cd = ctx->priv;
yading@10 119 int bpp = cd->max_pixsteps[0];
yading@10 120 int w, h, x, y, shrink_by;
yading@10 121
yading@10 122 // ignore first 2 frames - they may be empty
yading@10 123 if (++cd->frame_nb > 0) {
yading@10 124 // Reset the crop area every reset_count frames, if reset_count is > 0
yading@10 125 if (cd->reset_count > 0 && cd->frame_nb > cd->reset_count) {
yading@10 126 cd->x1 = frame->width - 1;
yading@10 127 cd->y1 = frame->height - 1;
yading@10 128 cd->x2 = 0;
yading@10 129 cd->y2 = 0;
yading@10 130 cd->frame_nb = 1;
yading@10 131 }
yading@10 132
yading@10 133 for (y = 0; y < cd->y1; y++) {
yading@10 134 if (checkline(ctx, frame->data[0] + frame->linesize[0] * y, bpp, frame->width, bpp) > cd->limit) {
yading@10 135 cd->y1 = y;
yading@10 136 break;
yading@10 137 }
yading@10 138 }
yading@10 139
yading@10 140 for (y = frame->height - 1; y > cd->y2; y--) {
yading@10 141 if (checkline(ctx, frame->data[0] + frame->linesize[0] * y, bpp, frame->width, bpp) > cd->limit) {
yading@10 142 cd->y2 = y;
yading@10 143 break;
yading@10 144 }
yading@10 145 }
yading@10 146
yading@10 147 for (y = 0; y < cd->x1; y++) {
yading@10 148 if (checkline(ctx, frame->data[0] + bpp*y, frame->linesize[0], frame->height, bpp) > cd->limit) {
yading@10 149 cd->x1 = y;
yading@10 150 break;
yading@10 151 }
yading@10 152 }
yading@10 153
yading@10 154 for (y = frame->width - 1; y > cd->x2; y--) {
yading@10 155 if (checkline(ctx, frame->data[0] + bpp*y, frame->linesize[0], frame->height, bpp) > cd->limit) {
yading@10 156 cd->x2 = y;
yading@10 157 break;
yading@10 158 }
yading@10 159 }
yading@10 160
yading@10 161 // round x and y (up), important for yuv colorspaces
yading@10 162 // make sure they stay rounded!
yading@10 163 x = (cd->x1+1) & ~1;
yading@10 164 y = (cd->y1+1) & ~1;
yading@10 165
yading@10 166 w = cd->x2 - x + 1;
yading@10 167 h = cd->y2 - y + 1;
yading@10 168
yading@10 169 // w and h must be divisible by 2 as well because of yuv
yading@10 170 // colorspace problems.
yading@10 171 if (cd->round <= 1)
yading@10 172 cd->round = 16;
yading@10 173 if (cd->round % 2)
yading@10 174 cd->round *= 2;
yading@10 175
yading@10 176 shrink_by = w % cd->round;
yading@10 177 w -= shrink_by;
yading@10 178 x += (shrink_by/2 + 1) & ~1;
yading@10 179
yading@10 180 shrink_by = h % cd->round;
yading@10 181 h -= shrink_by;
yading@10 182 y += (shrink_by/2 + 1) & ~1;
yading@10 183
yading@10 184 av_log(ctx, AV_LOG_INFO,
yading@10 185 "x1:%d x2:%d y1:%d y2:%d w:%d h:%d x:%d y:%d pts:%"PRId64" t:%f crop=%d:%d:%d:%d\n",
yading@10 186 cd->x1, cd->x2, cd->y1, cd->y2, w, h, x, y, frame->pts,
yading@10 187 frame->pts == AV_NOPTS_VALUE ? -1 : frame->pts * av_q2d(inlink->time_base),
yading@10 188 w, h, x, y);
yading@10 189 }
yading@10 190
yading@10 191 return ff_filter_frame(inlink->dst->outputs[0], frame);
yading@10 192 }
yading@10 193
yading@10 194 #define OFFSET(x) offsetof(CropDetectContext, x)
yading@10 195 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
yading@10 196
yading@10 197 static const AVOption cropdetect_options[] = {
yading@10 198 { "limit", "Threshold below which the pixel is considered black", OFFSET(limit), AV_OPT_TYPE_INT, { .i64 = 24 }, 0, 255, FLAGS },
yading@10 199 { "round", "Value by which the width/height should be divisible", OFFSET(round), AV_OPT_TYPE_INT, { .i64 = 16 }, 0, INT_MAX, FLAGS },
yading@10 200 { "reset", "Recalculate the crop area after this many frames", OFFSET(reset_count), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
yading@10 201 { "reset_count", "Recalculate the crop area after this many frames",OFFSET(reset_count),AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, INT_MAX, FLAGS },
yading@10 202 { NULL },
yading@10 203 };
yading@10 204
yading@10 205 AVFILTER_DEFINE_CLASS(cropdetect);
yading@10 206
yading@10 207 static const AVFilterPad avfilter_vf_cropdetect_inputs[] = {
yading@10 208 {
yading@10 209 .name = "default",
yading@10 210 .type = AVMEDIA_TYPE_VIDEO,
yading@10 211 .config_props = config_input,
yading@10 212 .get_video_buffer = ff_null_get_video_buffer,
yading@10 213 .filter_frame = filter_frame,
yading@10 214 },
yading@10 215 { NULL }
yading@10 216 };
yading@10 217
yading@10 218 static const AVFilterPad avfilter_vf_cropdetect_outputs[] = {
yading@10 219 {
yading@10 220 .name = "default",
yading@10 221 .type = AVMEDIA_TYPE_VIDEO
yading@10 222 },
yading@10 223 { NULL }
yading@10 224 };
yading@10 225
yading@10 226 AVFilter avfilter_vf_cropdetect = {
yading@10 227 .name = "cropdetect",
yading@10 228 .description = NULL_IF_CONFIG_SMALL("Auto-detect crop size."),
yading@10 229
yading@10 230 .priv_size = sizeof(CropDetectContext),
yading@10 231 .priv_class = &cropdetect_class,
yading@10 232 .init = init,
yading@10 233 .query_formats = query_formats,
yading@10 234 .inputs = avfilter_vf_cropdetect_inputs,
yading@10 235 .outputs = avfilter_vf_cropdetect_outputs,
yading@10 236 };