static void end_frame(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; BBoxContext *bbox = ctx->priv; AVFilterBufferRef *picref = inlink->cur_buf; FFBoundingBox box; int has_bbox, w, h; has_bbox = ff_calculate_bounding_box(&box, picref->data[0], picref->linesize[0], inlink->w, inlink->h, 16); w = box.x2 - box.x1 + 1; h = box.y2 - box.y1 + 1; av_log(ctx, AV_LOG_INFO, "n:%d pts:%s pts_time:%s", bbox->frame, av_ts2str(picref->pts), av_ts2timestr(picref->pts, &inlink->time_base)); if (has_bbox) { av_log(ctx, AV_LOG_INFO, "x1:%d x2:%d y1:%d y2:%d w:%d h:%d" " crop=%d:%d:%d:%d drawbox=%d:%d:%d:%d", box.x1, box.x2, box.y1, box.y2, w, h, w, h, box.x1, box.y1, /* crop params */ box.x1, box.y1, w, h); /* drawbox params */ } av_log(ctx, AV_LOG_INFO, "\n"); bbox->frame++; avfilter_end_frame(inlink->dst->outputs[0]); }
static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; BBoxContext *bbox = ctx->priv; FFBoundingBox box; int has_bbox, w, h; has_bbox = ff_calculate_bounding_box(&box, frame->data[0], frame->linesize[0], inlink->w, inlink->h, bbox->min_val); w = box.x2 - box.x1 + 1; h = box.y2 - box.y1 + 1; av_log(ctx, AV_LOG_INFO, "n:%"PRId64" pts:%s pts_time:%s", inlink->frame_count_out, av_ts2str(frame->pts), av_ts2timestr(frame->pts, &inlink->time_base)); if (has_bbox) { AVDictionary **metadata = &frame->metadata; SET_META("lavfi.bbox.x1", box.x1) SET_META("lavfi.bbox.x2", box.x2) SET_META("lavfi.bbox.y1", box.y1) SET_META("lavfi.bbox.y2", box.y2) SET_META("lavfi.bbox.w", w) SET_META("lavfi.bbox.h", h) av_log(ctx, AV_LOG_INFO, " x1:%d x2:%d y1:%d y2:%d w:%d h:%d" " crop=%d:%d:%d:%d drawbox=%d:%d:%d:%d", box.x1, box.x2, box.y1, box.y2, w, h, w, h, box.x1, box.y1, /* crop params */ box.x1, box.y1, w, h); /* drawbox params */ } av_log(ctx, AV_LOG_INFO, "\n"); return ff_filter_frame(inlink->dst->outputs[0], frame); }
static av_cold int init(AVFilterContext *ctx, const char *args) { RemovelogoContext *removelogo = ctx->priv; int ***mask; int ret = 0; int a, b, c, w, h; int full_max_mask_size, half_max_mask_size; if (!args) { av_log(ctx, AV_LOG_ERROR, "An image file must be specified as argument\n"); return AVERROR(EINVAL); } /* Load our mask image. */ if ((ret = load_mask(&removelogo->full_mask_data, &w, &h, args, ctx)) < 0) return ret; removelogo->mask_w = w; removelogo->mask_h = h; convert_mask_to_strength_mask(removelogo->full_mask_data, w, w, h, 16, &full_max_mask_size); /* Create the scaled down mask image for the chroma planes. */ if (!(removelogo->half_mask_data = av_mallocz(w/2 * h/2))) return AVERROR(ENOMEM); generate_half_size_image(removelogo->full_mask_data, w, removelogo->half_mask_data, w/2, w, h, &half_max_mask_size); removelogo->max_mask_size = FFMAX(full_max_mask_size, half_max_mask_size); /* Create a circular mask for each size up to max_mask_size. When the filter is applied, the mask size is determined on a pixel by pixel basis, with pixels nearer the edge of the logo getting smaller mask sizes. */ mask = (int ***)av_malloc(sizeof(int **) * (removelogo->max_mask_size + 1)); if (!mask) return AVERROR(ENOMEM); for (a = 0; a <= removelogo->max_mask_size; a++) { mask[a] = (int **)av_malloc(sizeof(int *) * ((a * 2) + 1)); if (!mask[a]) return AVERROR(ENOMEM); for (b = -a; b <= a; b++) { mask[a][b + a] = (int *)av_malloc(sizeof(int) * ((a * 2) + 1)); if (!mask[a][b + a]) return AVERROR(ENOMEM); for (c = -a; c <= a; c++) { if ((b * b) + (c * c) <= (a * a)) /* Circular 0/1 mask. */ mask[a][b + a][c + a] = 1; else mask[a][b + a][c + a] = 0; } } } removelogo->mask = mask; /* Calculate our bounding rectangles, which determine in what * region the logo resides for faster processing. */ ff_calculate_bounding_box(&removelogo->full_mask_bbox, removelogo->full_mask_data, w, w, h, 0); ff_calculate_bounding_box(&removelogo->half_mask_bbox, removelogo->half_mask_data, w/2, w/2, h/2, 0); #define SHOW_LOGO_INFO(mask_type) \ av_log(ctx, AV_LOG_VERBOSE, #mask_type " x1:%d x2:%d y1:%d y2:%d max_mask_size:%d\n", \ removelogo->mask_type##_mask_bbox.x1, removelogo->mask_type##_mask_bbox.x2, \ removelogo->mask_type##_mask_bbox.y1, removelogo->mask_type##_mask_bbox.y2, \ mask_type##_max_mask_size); SHOW_LOGO_INFO(full); SHOW_LOGO_INFO(half); return 0; }