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 | - blackdetect filter | ||||
| - libutvideo encoder wrapper (--enable-libutvideo) | - libutvideo encoder wrapper (--enable-libutvideo) | ||||
| - swapuv filter | - swapuv filter | ||||
| - bbox filter | |||||
| version 0.10: | version 0.10: | ||||
| @@ -761,6 +761,16 @@ video, use the command: | |||||
| ass=sub.ass | ass=sub.ass | ||||
| @end example | @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 | @section blackdetect | ||||
| Detect video intervals that are (almost) completely black. Can be | 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_ANULLSINK_FILTER) += asink_anullsink.o | ||||
| OBJS-$(CONFIG_ASS_FILTER) += vf_ass.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_BLACKDETECT_FILTER) += vf_blackdetect.o | ||||
| OBJS-$(CONFIG_BLACKFRAME_FILTER) += vf_blackframe.o | OBJS-$(CONFIG_BLACKFRAME_FILTER) += vf_blackframe.o | ||||
| OBJS-$(CONFIG_BOXBLUR_FILTER) += vf_boxblur.o | OBJS-$(CONFIG_BOXBLUR_FILTER) += vf_boxblur.o | ||||
| @@ -56,6 +56,7 @@ void avfilter_register_all(void) | |||||
| REGISTER_FILTER (ANULLSINK, anullsink, asink); | REGISTER_FILTER (ANULLSINK, anullsink, asink); | ||||
| REGISTER_FILTER (ASS, ass, vf); | REGISTER_FILTER (ASS, ass, vf); | ||||
| REGISTER_FILTER (BBOX, bbox, vf); | |||||
| REGISTER_FILTER (BLACKDETECT, blackdetect, vf); | REGISTER_FILTER (BLACKDETECT, blackdetect, vf); | ||||
| REGISTER_FILTER (BLACKFRAME, blackframe, vf); | REGISTER_FILTER (BLACKFRAME, blackframe, vf); | ||||
| REGISTER_FILTER (BOXBLUR, boxblur, 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" | #include "libavutil/avutil.h" | ||||
| #define LIBAVFILTER_VERSION_MAJOR 2 | #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, \ | #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ | ||||
| LIBAVFILTER_VERSION_MINOR, \ | 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 } | |||||
| }, | |||||
| }; | |||||