2
* Copyright (C) 2006 Mark Nauwelaerts <mnauw@users.sourceforge.net>
5
* Copyright (C) 2002 Jindrich Makovicka <makovick@gmail.com>
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1307 USA
23
* SECTION:element-delogo
27
* Suppresses a TV station logo by a simple interpolation of the surrounding
28
* pixels. Just set a rectangle covering the logo and watch it disappear
29
* (and sometimes something even uglier appear - your mileage may vary).
32
* If <link linkend="GstDelogo--border">border</link> is set to a negative
33
* value, a green border is drawn to simplify finding the right location
36
* <title>History</title>
40
* mplayer delogo filter [Jindrich Makovicka]
43
* Also available in avidemux (MPlayer delogo)
56
#include "plugin-mencoder.h"
61
#define GST_TYPE_DELOGO \
62
(gst_delogo_get_type())
63
#define GST_DELOGO(obj) \
64
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DELOGO,GstDelogo))
65
#define GST_DELOGO_CLASS(klass) \
66
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DELOGO,GstDelogoClass))
67
#define GST_IS_DELOGO(obj) \
68
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DELOGO))
69
#define GST_IS_DELOGO_CLASS(klass) \
70
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DELOGO))
73
typedef struct _GstDelogo GstDelogo;
74
typedef struct _GstDelogoClass GstDelogoClass;
78
GstVideoFilter videofilter;
82
/* properties; external view */
83
guint logo_x, logo_y, logo_w, logo_h;
86
/* properties; processed */
87
guint xoff, yoff, lw, lh;
92
struct _GstDelogoClass
94
GstVideoFilterClass parent_class;
97
GST_DEBUG_CATEGORY_STATIC (delogo_debug);
98
#define GST_CAT_DEFAULT delogo_debug
101
/* signals and args */
119
#define DEFAULT_LOGO_X 0
120
#define DEFAULT_LOGO_Y 0
121
#define DEFAULT_LOGO_W 10
122
#define DEFAULT_LOGO_H 10
123
#define DEFAULT_BORDER 0
126
static GstElementDetails delogo_details =
127
GST_ELEMENT_DETAILS ("Delogo",
128
"Filter/Effect/Video",
129
"Simple tv station logo remover",
130
"Mark Nauwelaerts <mnauw@users.sourceforge.net>,\n"
131
"Jindrich Makovicka");
133
static GstStaticPadTemplate gst_delogo_src_template =
134
GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SRC_NAME,
137
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ IYUV, I420, YV12 }"))
140
static GstStaticPadTemplate gst_delogo_sink_template =
141
GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SINK_NAME,
144
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ IYUV, I420, YV12 }"))
147
static gboolean gst_delogo_set_caps (GstBaseTransform * btrans,
148
GstCaps * incaps, GstCaps * outcaps);
149
static gboolean gst_delogo_get_unit_size (GstBaseTransform * btrans,
150
GstCaps * caps, guint * size);
151
static GstFlowReturn gst_delogo_transform (GstBaseTransform * btrans,
152
GstBuffer * in, GstBuffer * out);
153
static gboolean gst_delogo_start (GstBaseTransform * btrans);
154
static gboolean gst_delogo_stop (GstBaseTransform * btrans);
156
static void gst_delogo_set_property (GObject * object, guint prop_id,
157
const GValue * value, GParamSpec * pspec);
158
static void gst_delogo_get_property (GObject * object, guint prop_id,
159
GValue * value, GParamSpec * pspec);
161
GST_BOILERPLATE (GstDelogo, gst_delogo, GstVideoFilter, GST_TYPE_VIDEO_FILTER);
163
GST_VIDEO_FILTER_SET_CAPS_BOILERPLATE (GstDelogo, gst_delogo);
165
GST_VIDEO_FILTER_GET_UNIT_SIZE_BOILERPLATE (gst_delogo);
168
gst_delogo_base_init (gpointer g_class)
170
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
172
gst_element_class_set_details (element_class, &delogo_details);
174
gst_element_class_add_pad_template (element_class,
175
gst_static_pad_template_get (&gst_delogo_sink_template));
176
gst_element_class_add_pad_template (element_class,
177
gst_static_pad_template_get (&gst_delogo_src_template));
181
gst_delogo_class_init (GstDelogoClass * g_class)
183
GObjectClass *gobject_class;
184
GstBaseTransformClass *trans_class;
186
gobject_class = G_OBJECT_CLASS (g_class);
187
trans_class = GST_BASE_TRANSFORM_CLASS (g_class);
189
GST_DEBUG_CATEGORY_INIT (delogo_debug, "delogo", 0, "delogo");
191
gobject_class->set_property = gst_delogo_set_property;
192
gobject_class->get_property = gst_delogo_get_property;
194
g_object_class_install_property (gobject_class, PROP_LOGO_X,
195
g_param_spec_uint ("logo-x", "Logo X",
196
"X-coordinate of logo top left corner",
197
0, G_MAXUINT, DEFAULT_LOGO_X,
198
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
200
g_object_class_install_property (gobject_class, PROP_LOGO_Y,
201
g_param_spec_uint ("logo-y", "Logo Y",
202
"Y-coordinate of logo top left corner",
203
0, G_MAXUINT, DEFAULT_LOGO_Y,
204
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
206
g_object_class_install_property (gobject_class, PROP_LOGO_W,
207
g_param_spec_uint ("logo-w", "Logo Width",
209
0, G_MAXUINT, DEFAULT_LOGO_W,
210
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
212
g_object_class_install_property (gobject_class, PROP_LOGO_H,
213
g_param_spec_uint ("logo-h", "Logo Width",
215
0, G_MAXUINT, DEFAULT_LOGO_H,
216
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
218
g_object_class_install_property (gobject_class, PROP_BORDER,
219
g_param_spec_int ("border", "Border",
220
"Thickness of fuzzy edge of rectangle (<0 = draw border)",
221
-1, G_MAXINT, DEFAULT_BORDER,
222
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
224
trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_delogo_set_caps);
225
trans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_delogo_get_unit_size);
226
trans_class->transform = GST_DEBUG_FUNCPTR (gst_delogo_transform);
227
trans_class->start = GST_DEBUG_FUNCPTR (gst_delogo_start);
228
trans_class->stop = GST_DEBUG_FUNCPTR (gst_delogo_stop);
232
gst_delogo_init (GstDelogo * filter, GstDelogoClass * g_class)
234
filter->logo_x = DEFAULT_LOGO_X;
235
filter->logo_y = DEFAULT_LOGO_Y;
236
filter->logo_w = DEFAULT_LOGO_W;
237
filter->logo_h = DEFAULT_LOGO_H;
238
filter->border = DEFAULT_BORDER;
242
gst_delogo_delogo(guint8 * dst, guint8 * src, gint dstStride, gint srcStride,
243
gint width, gint height, gint logo_x, gint logo_y, gint logo_w, gint logo_h,
244
gint band, gint show, gint direct)
250
guint8 *topleft, *botleft, *topright;
251
gint xclipl, xclipr, yclipt, yclipb;
252
gint logo_x1, logo_x2, logo_y1, logo_y2;
254
xclipl = MAX (-logo_x, 0);
255
xclipr = MAX (logo_x + logo_w - width, 0);
256
yclipt = MAX (-logo_y, 0);
257
yclipb = MAX (logo_y + logo_h - height, 0);
259
logo_x1 = logo_x + xclipl;
260
logo_x2 = logo_x + logo_w - xclipr;
261
logo_y1 = logo_y + yclipt;
262
logo_y2 = logo_y + logo_h - yclipb;
264
topleft = src + logo_y1 * srcStride + logo_x1;
265
topright = src + logo_y1 * srcStride + logo_x2 - 1;
266
botleft = src + (logo_y2 - 1) * srcStride + logo_x1;
269
oil_memcpy (dst, src, width * height);
271
dst += (logo_y1 + 1) * dstStride;
272
src += (logo_y1 + 1) * srcStride;
274
for (y = logo_y1 + 1; y < logo_y2 - 1; y++) {
275
for (x = logo_x1 + 1, xdst = dst + logo_x1 + 1, xsrc = src + logo_x1 + 1;
276
x < logo_x2 - 1; x++, xdst++, xsrc++) {
277
interp = ((topleft[srcStride * (y - logo_y - yclipt)]
278
+ topleft[srcStride *(y - logo_y-1 - yclipt)]
279
+ topleft[srcStride *(y - logo_y+1 - yclipt)])
280
* (logo_w - (x - logo_x)) / logo_w
281
+ (topright[srcStride *(y - logo_y - yclipt)]
282
+ topright[srcStride *(y - logo_y -1 - yclipt)]
283
+ topright[srcStride *(y - logo_y +1 - yclipt)])
284
* (x - logo_x) / logo_w
285
+ (topleft[x -logo_x - xclipl]
286
+ topleft[x - logo_x - 1 - xclipl]
287
+ topleft[x - logo_x + 1 - xclipl])
288
* (logo_h - (y - logo_y)) / logo_h
289
+ (botleft[x - logo_x -xclipl]
290
+ botleft[x - logo_x - 1 - xclipl]
291
+ botleft[x - logo_x + 1- xclipl])
292
* (y - logo_y) / logo_h
294
/* interp = (topleft[srcStride*(y-logo_y)]*(logo_w-(x-logo_x))/logo_w
295
+ topright[srcStride*(y-logo_y)]*(x-logo_x)/logo_w
296
+ topleft[x-logo_x]*(logo_h-(y-logo_y))/logo_h
297
+ botleft[x-logo_x]*(y-logo_y)/logo_h
299
if (y >= logo_y + band && y < logo_y + logo_h - band &&
300
x >= logo_x+band && x < logo_x + logo_w - band) {
304
if (x < logo_x + band)
305
dist = MAX (dist, logo_x - x + band);
306
else if (x >= logo_x + logo_w-band)
307
dist = MAX (dist, x -(logo_x + logo_w - 1 - band));
308
if (y < logo_y + band)
309
dist = MAX (dist, logo_y - y + band);
310
else if (y >= logo_y + logo_h - band)
311
dist = MAX (dist, y - (logo_y + logo_h - 1 - band));
312
*xdst = (*xsrc * dist + interp * (band - dist)) / band;
314
if (show && (dist == band - 1))
325
gst_delogo_set_props (GstDelogo * filter)
328
filter->band = filter->border;
330
if (filter->band < 0) {
335
filter->lw = filter->logo_w + filter->band * 2;
336
filter->lh = filter->logo_h + filter->band * 2;
337
filter->xoff = filter->logo_x - filter->band;
338
filter->yoff = filter->logo_y - filter->band;
342
gst_delogo_transform (GstBaseTransform * btrans, GstBuffer * in,
347
guint width, height, stride;
349
gst_object_sync_values (G_OBJECT (btrans), GST_BUFFER_TIMESTAMP (in));
351
filter = GST_DELOGO (btrans);
353
width = filter->width;
354
height = filter->height;
357
src = (guint8 *) GST_BUFFER_DATA (in);
358
dest = (guint8 *) GST_BUFFER_DATA (out);
359
stride = GST_VIDEO_I420_Y_ROWSTRIDE (width);
361
gst_delogo_delogo (dest, src, stride, stride, stride, height,
362
filter->xoff, filter->yoff, filter->lw, filter->lh,
363
filter->band, filter->show, FALSE);
366
src += GST_VIDEO_I420_U_OFFSET (width, height);
367
dest += GST_VIDEO_I420_U_OFFSET (width, height);
368
stride = GST_VIDEO_I420_U_ROWSTRIDE (width);
370
gst_delogo_delogo (dest, src, stride, stride, stride, height / 2,
371
filter->xoff / 2, filter->yoff / 2, filter->lw / 2, filter->lh / 2,
372
filter->band / 2, filter->show, FALSE);
374
src = (guint8 *) GST_BUFFER_DATA (in) + GST_VIDEO_I420_V_OFFSET (width, height);
375
dest = (guint8 *) GST_BUFFER_DATA (out) + GST_VIDEO_I420_V_OFFSET (width, height);
377
gst_delogo_delogo (dest, src, stride, stride, stride, height / 2,
378
filter->xoff / 2, filter->yoff / 2, filter->lw / 2, filter->lh / 2,
379
filter->band / 2, filter->show, FALSE);
386
gst_delogo_start (GstBaseTransform * btrans)
392
gst_delogo_stop (GstBaseTransform * btrans)
398
gst_delogo_set_property (GObject * object, guint prop_id,
399
const GValue * value, GParamSpec * pspec)
403
g_return_if_fail (GST_IS_DELOGO (object));
404
src = GST_DELOGO (object);
408
src->logo_x = g_value_get_uint (value);
411
src->logo_y = g_value_get_uint (value);
414
src->logo_w = g_value_get_uint (value);
417
src->logo_h = g_value_get_uint (value);
420
src->border = g_value_get_int (value);
423
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
427
gst_delogo_set_props (src);
431
gst_delogo_get_property (GObject * object, guint prop_id, GValue * value,
436
g_return_if_fail (GST_IS_DELOGO (object));
437
src = GST_DELOGO (object);
441
g_value_set_uint (value, src->logo_x);
444
g_value_set_uint (value, src->logo_y);
447
g_value_set_uint (value, src->logo_w);
450
g_value_set_uint (value, src->logo_h);
453
g_value_set_int (value, src->border);
456
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);