Skip to content

Commit

Permalink
lavfi: port libmpcodecs remove-logo filter
Browse files Browse the repository at this point in the history
The code is based on the remove-logo filter in MPlayer/libmpcodecs, by
Robert Edele, relicensed to LGPL with consent of the author.

Address trac issue FFmpeg#249.
  • Loading branch information
saste committed Apr 7, 2012
1 parent 087b9c3 commit 2f83681
Show file tree
Hide file tree
Showing 11 changed files with 832 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Changelog
Expand Up @@ -21,6 +21,8 @@ version next:
- tile video filter
- Metal Gear Solid: The Twin Snakes demuxer
- OpenEXR image decoder
- removelogo filter


version 0.10:
- Fixes: CVE-2011-3929, CVE-2011-3934, CVE-2011-3935, CVE-2011-3936,
Expand Down
1 change: 1 addition & 0 deletions configure
Expand Up @@ -1688,6 +1688,7 @@ mptestsrc_filter_deps="gpl"
negate_filter_deps="lut_filter"
ocv_filter_deps="libopencv"
pan_filter_deps="swresample"
removelogo_filter_deps="avcodec avformat swscale"
scale_filter_deps="swscale"
tinterlace_filter_deps="gpl"
yadif_filter_deps="gpl"
Expand Down
26 changes: 26 additions & 0 deletions doc/filters.texi
Expand Up @@ -2237,6 +2237,32 @@ format=monow, pixdesctest

can be used to test the monowhite pixel format descriptor definition.

@section removelogo

Suppress a TV station logo, using an image file to determine which
pixels comprise the logo. It works by filling in the pixels that
comprise the logo with neighboring pixels.

This filter requires one argument which specifies the filter bitmap
file, which can be any image format supported by libavformat. The
width and height of the image file must match those of the video
stream being processed.

Pixels in the provided bitmap image with a value of zero are not
considered part of the logo, non-zero pixels are considered part of
the logo. If you use white (255) for the logo and black (0) for the
rest, you will be safe. For making the filter bitmap, it is
recommended to take a screen capture of a black frame with the logo
visible, and then using a threshold filter followed by the erode
filter once or twice.

If needed, little splotches can be fixed manually. Remember that if
logo pixels are not covered, the filter quality will be much
reduced. Marking too many pixels as part of the logo does not hurt as
much, but it will increase the amount of blurring needed to cover over
the image and will destroy more information than necessary, and extra
pixels will slow things down on a large logo.

@section scale

Scale the input video to @var{width}:@var{height}[:@var{interl}=@{1|-1@}] and/or convert the image format.
Expand Down
4 changes: 4 additions & 0 deletions libavfilter/Makefile
Expand Up @@ -8,6 +8,7 @@ FFLIBS-$(CONFIG_AMOVIE_FILTER) += avformat avcodec
FFLIBS-$(CONFIG_ARESAMPLE_FILTER) += swresample
FFLIBS-$(CONFIG_MOVIE_FILTER) += avformat avcodec
FFLIBS-$(CONFIG_PAN_FILTER) += swresample
FFLIBS-$(CONFIG_REMOVELOGO_FILTER) += swscale avformat avcodec
FFLIBS-$(CONFIG_SCALE_FILTER) += swscale
FFLIBS-$(CONFIG_MP_FILTER) += avcodec postproc

Expand All @@ -25,6 +26,8 @@ OBJS = allfilters.o \
vsrc_buffer.o

OBJS-$(CONFIG_AVCODEC) += avcodec.o
OBJS-$(CONFIG_AVFORMAT) += lavfutils.o
OBJS-$(CONFIG_SWSCALE) += lswsutils.o

OBJS-$(CONFIG_ACONVERT_FILTER) += af_aconvert.o
OBJS-$(CONFIG_AFORMAT_FILTER) += af_aformat.o
Expand Down Expand Up @@ -80,6 +83,7 @@ OBJS-$(CONFIG_OCV_FILTER) += vf_libopencv.o
OBJS-$(CONFIG_OVERLAY_FILTER) += vf_overlay.o
OBJS-$(CONFIG_PAD_FILTER) += vf_pad.o
OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o
OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o lswsutils.o lavfutils.o vf_removelogo.o
OBJS-$(CONFIG_SCALE_FILTER) += vf_scale.o
OBJS-$(CONFIG_SELECT_FILTER) += vf_select.o
OBJS-$(CONFIG_SETDAR_FILTER) += vf_aspect.o
Expand Down
1 change: 1 addition & 0 deletions libavfilter/allfilters.c
Expand Up @@ -88,6 +88,7 @@ void avfilter_register_all(void)
REGISTER_FILTER (OVERLAY, overlay, vf);
REGISTER_FILTER (PAD, pad, vf);
REGISTER_FILTER (PIXDESCTEST, pixdesctest, vf);
REGISTER_FILTER (REMOVELOGO, removelogo, vf);
REGISTER_FILTER (SCALE, scale, vf);
REGISTER_FILTER (SELECT, select, vf);
REGISTER_FILTER (SETDAR, setdar, vf);
Expand Down
95 changes: 95 additions & 0 deletions libavfilter/lavfutils.c
@@ -0,0 +1,95 @@
/*
* 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 "libavutil/imgutils.h"
#include "lavfutils.h"

int ff_load_image(uint8_t *data[4], int linesize[4],
int *w, int *h, enum PixelFormat *pix_fmt,
const char *filename, void *log_ctx)
{
AVInputFormat *iformat = NULL;
AVFormatContext *format_ctx;
AVCodec *codec;
AVCodecContext *codec_ctx;
AVFrame *frame;
int frame_decoded, ret = 0;
AVPacket pkt;

av_register_all();

iformat = av_find_input_format("image2");
if ((ret = avformat_open_input(&format_ctx, filename, iformat, NULL)) < 0) {
av_log(log_ctx, AV_LOG_ERROR,
"Failed to open input file '%s'\n", filename);
return ret;
}

codec_ctx = format_ctx->streams[0]->codec;
codec = avcodec_find_decoder(codec_ctx->codec_id);
if (!codec) {
av_log(log_ctx, AV_LOG_ERROR, "Failed to find codec\n");
ret = AVERROR(EINVAL);
goto end;
}

if ((ret = avcodec_open2(codec_ctx, codec, NULL)) < 0) {
av_log(log_ctx, AV_LOG_ERROR, "Failed to open codec\n");
goto end;
}

if (!(frame = avcodec_alloc_frame()) ) {
av_log(log_ctx, AV_LOG_ERROR, "Failed to alloc frame\n");
ret = AVERROR(ENOMEM);
goto end;
}

ret = av_read_frame(format_ctx, &pkt);
if (ret < 0) {
av_log(log_ctx, AV_LOG_ERROR, "Failed to read frame from file\n");
goto end;
}

ret = avcodec_decode_video2(codec_ctx, frame, &frame_decoded, &pkt);
if (ret < 0 || !frame_decoded) {
av_log(log_ctx, AV_LOG_ERROR, "Failed to decode image from file\n");
goto end;
}
ret = 0;

*w = frame->width;
*h = frame->height;
*pix_fmt = frame->format;

if ((ret = av_image_alloc(data, linesize, *w, *h, *pix_fmt, 16)) < 0)
goto end;
ret = 0;

av_image_copy(data, linesize, frame->data, frame->linesize, *pix_fmt, *w, *h);

end:
if (codec_ctx)
avcodec_close(codec_ctx);
if (format_ctx)
avformat_close_input(&format_ctx);
av_freep(&frame);

if (ret < 0)
av_log(log_ctx, AV_LOG_ERROR, "Error loading image file '%s'\n", filename);
return ret;
}
43 changes: 43 additions & 0 deletions libavfilter/lavfutils.h
@@ -0,0 +1,43 @@
/*
* 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
* Miscellaneous utilities which make use of the libavformat library
*/

#ifndef AVFILTER_LAVFUTILS_H
#define AVFILTER_LAVFUTILS_H

#include "libavformat/avformat.h"

/**
* Load image from filename and put the resulting image in data.
*
* @param w pointer to the width of the loaded image
* @param h pointer to the height of the loaded image
* @param pix_fmt pointer to the pixel format of the loaded image
* @param filename the name of the image file to load
* @param log_ctx log context
* @return 0 in case of success, a negative error code otherwise.
*/
int ff_load_image(uint8_t *data[4], int linesize[4],
int *w, int *h, enum PixelFormat *pix_fmt,
const char *filename, void *log_ctx);

#endif /* AVFILTER_LAVFUTILS_H */
50 changes: 50 additions & 0 deletions libavfilter/lswsutils.c
@@ -0,0 +1,50 @@
/*
* 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 "libavutil/imgutils.h"
#include "lswsutils.h"

int ff_scale_image(uint8_t *dst_data[4], int dst_linesize[4],
int dst_w, int dst_h, enum PixelFormat dst_pix_fmt,
uint8_t * const src_data[4], int src_linesize[4],
int src_w, int src_h, enum PixelFormat src_pix_fmt,
void *log_ctx)
{
int ret;
struct SwsContext *sws_ctx = sws_getContext(src_w, src_h, src_pix_fmt,
dst_w, dst_h, dst_pix_fmt,
SWS_BILINEAR, NULL, NULL, NULL);
if (!sws_ctx) {
av_log(log_ctx, AV_LOG_ERROR,
"Impossible to create scale context for the conversion "
"fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n",
av_get_pix_fmt_name(src_pix_fmt), src_w, src_h,
av_get_pix_fmt_name(dst_pix_fmt), dst_w, dst_h);
ret = AVERROR(EINVAL);
goto end;
}

if ((ret = av_image_alloc(dst_data, dst_linesize, dst_w, dst_h, dst_pix_fmt, 16)) < 0)
goto end;
ret = 0;
sws_scale(sws_ctx, src_data, src_linesize, 0, src_h, dst_data, dst_linesize);

end:
sws_freeContext(sws_ctx);
return ret;
}
38 changes: 38 additions & 0 deletions libavfilter/lswsutils.h
@@ -0,0 +1,38 @@
/*
* 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
* Miscellaneous utilities which make use of the libswscale library
*/

#ifndef AVFILTER_LSWSUTILS_H
#define AVFILTER_LSWSUTILS_H

#include "libswscale/swscale.h"

/**
* Scale image using libswscale.
*/
int ff_scale_image(uint8_t *dst_data[4], int dst_linesize[4],
int dst_w, int dst_h, enum PixelFormat dst_pix_fmt,
uint8_t *const src_data[4], int src_linesize[4],
int src_w, int src_h, enum PixelFormat src_pix_fmt,
void *log_ctx);

#endif /* AVFILTER_LSWSUTILS_H */
4 changes: 2 additions & 2 deletions libavfilter/version.h
Expand Up @@ -29,8 +29,8 @@
#include "libavutil/avutil.h"

#define LIBAVFILTER_VERSION_MAJOR 2
#define LIBAVFILTER_VERSION_MINOR 66
#define LIBAVFILTER_VERSION_MICRO 101
#define LIBAVFILTER_VERSION_MINOR 67
#define LIBAVFILTER_VERSION_MICRO 100

#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
LIBAVFILTER_VERSION_MINOR, \
Expand Down

0 comments on commit 2f83681

Please sign in to comment.