Also add bbox.h and bbox.c files, based on the remove-logo filter by Robert Edele. These files are useful for sharing code with the pending removelogo port.tags/n0.11
| @@ -14,6 +14,7 @@ version next: | |||
| - blackdetect filter | |||
| - libutvideo encoder wrapper (--enable-libutvideo) | |||
| - swapuv filter | |||
| - bbox filter | |||
| version 0.10: | |||
| @@ -761,6 +761,16 @@ video, use the command: | |||
| ass=sub.ass | |||
| @end example | |||
| @section bbox | |||
| Compute the bounding box for the non-black pixels in the input frame | |||
| luminance plane. | |||
| This filter computes the bounding box containing all the pixels with a | |||
| luminance value greater than the minimum allowed value. | |||
| The parameters describing the bounding box are printed on the filter | |||
| log. | |||
| @section blackdetect | |||
| Detect video intervals that are (almost) completely black. Can be | |||
| @@ -48,6 +48,7 @@ OBJS-$(CONFIG_ABUFFERSINK_FILTER) += sink_buffer.o | |||
| OBJS-$(CONFIG_ANULLSINK_FILTER) += asink_anullsink.o | |||
| OBJS-$(CONFIG_ASS_FILTER) += vf_ass.o | |||
| OBJS-$(CONFIG_BBOX_FILTER) += bbox.o vf_bbox.o | |||
| OBJS-$(CONFIG_BLACKDETECT_FILTER) += vf_blackdetect.o | |||
| OBJS-$(CONFIG_BLACKFRAME_FILTER) += vf_blackframe.o | |||
| OBJS-$(CONFIG_BOXBLUR_FILTER) += vf_boxblur.o | |||
| @@ -56,6 +56,7 @@ void avfilter_register_all(void) | |||
| REGISTER_FILTER (ANULLSINK, anullsink, asink); | |||
| REGISTER_FILTER (ASS, ass, vf); | |||
| REGISTER_FILTER (BBOX, bbox, vf); | |||
| REGISTER_FILTER (BLACKDETECT, blackdetect, vf); | |||
| REGISTER_FILTER (BLACKFRAME, blackframe, vf); | |||
| REGISTER_FILTER (BOXBLUR, boxblur, vf); | |||
| @@ -0,0 +1,75 @@ | |||
| /* | |||
| * Copyright (c) 2005 Robert Edele <yartrebo@earthlink.net> | |||
| * | |||
| * This file is part of FFmpeg. | |||
| * | |||
| * FFmpeg is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation; either | |||
| * version 2.1 of the License, or (at your option) any later version. | |||
| * | |||
| * FFmpeg is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| * Lesser General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU Lesser General Public | |||
| * License along with FFmpeg; if not, write to the Free Software | |||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #include "bbox.h" | |||
| int ff_calculate_bounding_box(FFBoundingBox *bbox, | |||
| const uint8_t *data, int linesize, int w, int h, | |||
| int min_val) | |||
| { | |||
| int x, y; | |||
| int start_x; | |||
| int start_y; | |||
| int end_x = w - 1; | |||
| int end_y = h - 1; | |||
| const uint8_t *line; | |||
| /* left bound */ | |||
| for (start_x = 0; start_x < w; start_x++) | |||
| for (y = 0; y < h; y++) | |||
| if ((data[y * linesize + start_x] > min_val)) | |||
| goto outl; | |||
| outl: | |||
| if (start_x == w) /* no points found */ | |||
| return 0; | |||
| /* right bound */ | |||
| for (end_x = w - 1; end_x >= start_x; end_x--) | |||
| for (y = 0; y < h; y++) | |||
| if ((data[y * linesize + end_x] > min_val)) | |||
| goto outr; | |||
| outr: | |||
| /* top bound */ | |||
| line = data; | |||
| for (start_y = 0; start_y < h; start_y++) { | |||
| for (x = 0; x < w; x++) | |||
| if (line[x] > min_val) | |||
| goto outt; | |||
| line += linesize; | |||
| } | |||
| outt: | |||
| /* bottom bound */ | |||
| line = data + (h-1)*linesize; | |||
| for (end_y = h - 1; end_y >= start_y; end_y--) { | |||
| for (x = 0; x < w; x++) | |||
| if (line[x] > min_val) | |||
| goto outb; | |||
| line -= linesize; | |||
| } | |||
| outb: | |||
| bbox->x1 = start_x; | |||
| bbox->y1 = start_y; | |||
| bbox->x2 = end_x; | |||
| bbox->y2 = end_y; | |||
| return 1; | |||
| } | |||
| @@ -0,0 +1,44 @@ | |||
| /* | |||
| * Copyright (c) 2005 Robert Edele <yartrebo@earthlink.net> | |||
| * | |||
| * This file is part of FFmpeg. | |||
| * | |||
| * FFmpeg is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation; either | |||
| * version 2.1 of the License, or (at your option) any later version. | |||
| * | |||
| * FFmpeg is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| * Lesser General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU Lesser General Public | |||
| * License along with FFmpeg; if not, write to the Free Software | |||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #ifndef AVFILTER_BBOX_H | |||
| #define AVFILTER_BBOX_H | |||
| #include <stdint.h> | |||
| typedef struct { | |||
| int x1, x2, y1, y2; | |||
| } FFBoundingBox; | |||
| /** | |||
| * Calculate the smallest rectangle that will encompass the | |||
| * region with values > min_val. | |||
| * | |||
| * @param bbox bounding box structure which is updated with the found values. | |||
| * If no pixels could be found with value > min_val, the | |||
| * structure is not modified. | |||
| * @return 1 in case at least one pixel with value > min_val was found, | |||
| * 0 otherwise | |||
| */ | |||
| int ff_calculate_bounding_box(FFBoundingBox *bbox, | |||
| const uint8_t *data, int linesize, | |||
| int w, int h, int min_val); | |||
| #endif /* AVFILTER_BBOX_H */ | |||
| @@ -29,8 +29,8 @@ | |||
| #include "libavutil/avutil.h" | |||
| #define LIBAVFILTER_VERSION_MAJOR 2 | |||
| #define LIBAVFILTER_VERSION_MINOR 64 | |||
| #define LIBAVFILTER_VERSION_MICRO 101 | |||
| #define LIBAVFILTER_VERSION_MINOR 65 | |||
| #define LIBAVFILTER_VERSION_MICRO 100 | |||
| #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ | |||
| LIBAVFILTER_VERSION_MINOR, \ | |||
| @@ -0,0 +1,113 @@ | |||
| /* | |||
| * Copyright (c) 2012 Stefano Sabatini | |||
| * | |||
| * This file is part of FFmpeg. | |||
| * | |||
| * FFmpeg is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation; either | |||
| * version 2.1 of the License, or (at your option) any later version. | |||
| * | |||
| * FFmpeg is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| * Lesser General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU Lesser General Public | |||
| * License along with FFmpeg; if not, write to the Free Software | |||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| /** | |||
| * @file | |||
| * bounding box detection filter | |||
| */ | |||
| #include "libavutil/pixdesc.h" | |||
| #include "libavutil/timestamp.h" | |||
| #include "avfilter.h" | |||
| #include "bbox.h" | |||
| typedef struct { | |||
| unsigned int frame; | |||
| int vsub, hsub; | |||
| } BBoxContext; | |||
| static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) | |||
| { | |||
| BBoxContext *bbox = ctx->priv; | |||
| bbox->frame = 0; | |||
| return 0; | |||
| } | |||
| static int query_formats(AVFilterContext *ctx) | |||
| { | |||
| static const enum PixelFormat pix_fmts[] = { | |||
| PIX_FMT_YUV420P, | |||
| PIX_FMT_YUV444P, | |||
| PIX_FMT_YUV440P, | |||
| PIX_FMT_YUV422P, | |||
| PIX_FMT_YUV411P, | |||
| PIX_FMT_NONE, | |||
| }; | |||
| avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); | |||
| return 0; | |||
| } | |||
| 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]); | |||
| } | |||
| AVFilter avfilter_vf_bbox = { | |||
| .name = "bbox", | |||
| .description = NULL_IF_CONFIG_SMALL("Compute bounding box for each frame."), | |||
| .priv_size = sizeof(BBoxContext), | |||
| .query_formats = query_formats, | |||
| .init = init, | |||
| .inputs = (const AVFilterPad[]) { | |||
| { .name = "default", | |||
| .type = AVMEDIA_TYPE_VIDEO, | |||
| .get_video_buffer = avfilter_null_get_video_buffer, | |||
| .start_frame = avfilter_null_start_frame, | |||
| .end_frame = end_frame, | |||
| .min_perms = AV_PERM_READ, }, | |||
| { .name = NULL } | |||
| }, | |||
| .outputs = (const AVFilterPad[]) { | |||
| { .name = "default", | |||
| .type = AVMEDIA_TYPE_VIDEO }, | |||
| { .name = NULL } | |||
| }, | |||
| }; | |||