Libav 0.7.1
|
00001 /* 00002 * Copyright (c) 2002 A'rpi 00003 * This file is part of Libav. 00004 * 00005 * Libav is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * Libav is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License along 00016 * with Libav; if not, write to the Free Software Foundation, Inc., 00017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00018 */ 00019 00026 #include "libavutil/imgutils.h" 00027 #include "avfilter.h" 00028 00029 typedef struct { 00030 int x1, y1, x2, y2; 00031 int limit; 00032 int round; 00033 int reset_count; 00034 int frame_nb; 00035 int max_pixsteps[4]; 00036 } CropDetectContext; 00037 00038 static int query_formats(AVFilterContext *ctx) 00039 { 00040 static const enum PixelFormat pix_fmts[] = { 00041 PIX_FMT_YUV420P, PIX_FMT_YUVJ420P, 00042 PIX_FMT_YUV422P, PIX_FMT_YUVJ422P, 00043 PIX_FMT_YUV444P, PIX_FMT_YUVJ444P, 00044 PIX_FMT_YUV411P, PIX_FMT_GRAY8, 00045 PIX_FMT_NV12, PIX_FMT_NV21, 00046 PIX_FMT_NONE 00047 }; 00048 00049 avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts)); 00050 return 0; 00051 } 00052 00053 static int checkline(void *ctx, const unsigned char *src, int stride, int len, int bpp) 00054 { 00055 int total = 0; 00056 int div = len; 00057 00058 switch (bpp) { 00059 case 1: 00060 while (--len >= 0) { 00061 total += src[0]; 00062 src += stride; 00063 } 00064 break; 00065 case 3: 00066 case 4: 00067 while (--len >= 0) { 00068 total += src[0] + src[1] + src[2]; 00069 src += stride; 00070 } 00071 div *= 3; 00072 break; 00073 } 00074 total /= div; 00075 00076 av_log(ctx, AV_LOG_DEBUG, "total:%d\n", total); 00077 return total; 00078 } 00079 00080 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) 00081 { 00082 CropDetectContext *cd = ctx->priv; 00083 00084 cd->limit = 24; 00085 cd->round = 0; 00086 cd->reset_count = 0; 00087 cd->frame_nb = -2; 00088 00089 if (args) 00090 sscanf(args, "%d:%d:%d", &cd->limit, &cd->round, &cd->reset_count); 00091 00092 av_log(ctx, AV_LOG_INFO, "limit:%d round:%d reset_count:%d\n", 00093 cd->limit, cd->round, cd->reset_count); 00094 00095 return 0; 00096 } 00097 00098 static int config_input(AVFilterLink *inlink) 00099 { 00100 AVFilterContext *ctx = inlink->dst; 00101 CropDetectContext *cd = ctx->priv; 00102 00103 av_image_fill_max_pixsteps(cd->max_pixsteps, NULL, 00104 &av_pix_fmt_descriptors[inlink->format]); 00105 00106 cd->x1 = inlink->w - 1; 00107 cd->y1 = inlink->h - 1; 00108 cd->x2 = 0; 00109 cd->y2 = 0; 00110 00111 return 0; 00112 } 00113 00114 static void end_frame(AVFilterLink *inlink) 00115 { 00116 AVFilterContext *ctx = inlink->dst; 00117 CropDetectContext *cd = ctx->priv; 00118 AVFilterBufferRef *picref = inlink->cur_buf; 00119 int bpp = cd->max_pixsteps[0]; 00120 int w, h, x, y, shrink_by; 00121 00122 // ignore first 2 frames - they may be empty 00123 if (++cd->frame_nb > 0) { 00124 // Reset the crop area every reset_count frames, if reset_count is > 0 00125 if (cd->reset_count > 0 && cd->frame_nb > cd->reset_count) { 00126 cd->x1 = picref->video->w-1; 00127 cd->y1 = picref->video->h-1; 00128 cd->x2 = 0; 00129 cd->y2 = 0; 00130 cd->frame_nb = 1; 00131 } 00132 00133 for (y = 0; y < cd->y1; y++) { 00134 if (checkline(ctx, picref->data[0] + picref->linesize[0] * y, bpp, picref->video->w, bpp) > cd->limit) { 00135 cd->y1 = y; 00136 break; 00137 } 00138 } 00139 00140 for (y = picref->video->h-1; y > cd->y2; y--) { 00141 if (checkline(ctx, picref->data[0] + picref->linesize[0] * y, bpp, picref->video->w, bpp) > cd->limit) { 00142 cd->y2 = y; 00143 break; 00144 } 00145 } 00146 00147 for (y = 0; y < cd->x1; y++) { 00148 if (checkline(ctx, picref->data[0] + bpp*y, picref->linesize[0], picref->video->h, bpp) > cd->limit) { 00149 cd->x1 = y; 00150 break; 00151 } 00152 } 00153 00154 for (y = picref->video->w-1; y > cd->x2; y--) { 00155 if (checkline(ctx, picref->data[0] + bpp*y, picref->linesize[0], picref->video->h, bpp) > cd->limit) { 00156 cd->x2 = y; 00157 break; 00158 } 00159 } 00160 00161 // round x and y (up), important for yuv colorspaces 00162 // make sure they stay rounded! 00163 x = (cd->x1+1) & ~1; 00164 y = (cd->y1+1) & ~1; 00165 00166 w = cd->x2 - x + 1; 00167 h = cd->y2 - y + 1; 00168 00169 // w and h must be divisible by 2 as well because of yuv 00170 // colorspace problems. 00171 if (cd->round <= 1) 00172 cd->round = 16; 00173 if (cd->round % 2) 00174 cd->round *= 2; 00175 00176 shrink_by = w % cd->round; 00177 w -= shrink_by; 00178 x += (shrink_by/2 + 1) & ~1; 00179 00180 shrink_by = h % cd->round; 00181 h -= shrink_by; 00182 y += (shrink_by/2 + 1) & ~1; 00183 00184 av_log(ctx, AV_LOG_INFO, 00185 "x1:%d x2:%d y1:%d y2:%d w:%d h:%d x:%d y:%d pos:%"PRId64" pts:%"PRId64" t:%f crop=%d:%d:%d:%d\n", 00186 cd->x1, cd->x2, cd->y1, cd->y2, w, h, x, y, picref->pos, picref->pts, 00187 picref->pts == AV_NOPTS_VALUE ? -1 : picref->pts * av_q2d(inlink->time_base), 00188 w, h, x, y); 00189 } 00190 00191 avfilter_end_frame(inlink->dst->outputs[0]); 00192 } 00193 00194 AVFilter avfilter_vf_cropdetect = { 00195 .name = "cropdetect", 00196 .description = NULL_IF_CONFIG_SMALL("Auto-detect crop size."), 00197 00198 .priv_size = sizeof(CropDetectContext), 00199 .init = init, 00200 00201 .query_formats = query_formats, 00202 00203 .inputs = (AVFilterPad[]) {{ .name = "default", 00204 .type = AVMEDIA_TYPE_VIDEO, 00205 .config_props = config_input, 00206 .get_video_buffer = avfilter_null_get_video_buffer, 00207 .start_frame = avfilter_null_start_frame, 00208 .end_frame = end_frame, }, 00209 { .name = NULL}}, 00210 00211 .outputs = (AVFilterPad[]) {{ .name = "default", 00212 .type = AVMEDIA_TYPE_VIDEO }, 00213 { .name = NULL}}, 00214 };