Statistics
| Branch: | Revision:

ffmpeg / libavfilter / libmpcodecs / vf_delogo.c @ e4852fb3

History | View | Annotate | Download (8.68 KB)

1
/*
2
 * Copyright (C) 2002 Jindrich Makovicka <makovick@gmail.com>
3
 *
4
 * This file is part of MPlayer.
5
 *
6
 * MPlayer is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * MPlayer is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along
17
 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
 */
20

    
21
/* A very simple tv station logo remover */
22

    
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <inttypes.h>
27
#include <math.h>
28

    
29
#include "mp_msg.h"
30
#include "cpudetect.h"
31
#include "img_format.h"
32
#include "mp_image.h"
33
#include "vf.h"
34
#include "libvo/fastmemcpy.h"
35

    
36
#include "m_option.h"
37
#include "m_struct.h"
38

    
39
//===========================================================================//
40

    
41
static struct vf_priv_s {
42
    unsigned int outfmt;
43
    int xoff, yoff, lw, lh, band, show;
44
} const vf_priv_dflt = {
45
    0,
46
    0, 0, 0, 0, 0, 0
47
};
48

    
49
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
50
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
51

    
52
static void delogo(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int width, int height,
53
                   int logo_x, int logo_y, int logo_w, int logo_h, int band, int show, int direct) {
54
    int y, x;
55
    int interp, dist;
56
    uint8_t *xdst, *xsrc;
57

    
58
    uint8_t *topleft, *botleft, *topright;
59
    int xclipl, xclipr, yclipt, yclipb;
60
    int logo_x1, logo_x2, logo_y1, logo_y2;
61

    
62
    xclipl = MAX(-logo_x, 0);
63
    xclipr = MAX(logo_x+logo_w-width, 0);
64
    yclipt = MAX(-logo_y, 0);
65
    yclipb = MAX(logo_y+logo_h-height, 0);
66

    
67
    logo_x1 = logo_x + xclipl;
68
    logo_x2 = logo_x + logo_w - xclipr;
69
    logo_y1 = logo_y + yclipt;
70
    logo_y2 = logo_y + logo_h - yclipb;
71

    
72
    topleft = src+logo_y1*srcStride+logo_x1;
73
    topright = src+logo_y1*srcStride+logo_x2-1;
74
    botleft = src+(logo_y2-1)*srcStride+logo_x1;
75

    
76
    if (!direct) memcpy_pic(dst, src, width, height, dstStride, srcStride);
77

    
78
    dst += (logo_y1+1)*dstStride;
79
    src += (logo_y1+1)*srcStride;
80

    
81
    for(y = logo_y1+1; y < logo_y2-1; y++)
82
    {
83
        for (x = logo_x1+1, xdst = dst+logo_x1+1, xsrc = src+logo_x1+1; x < logo_x2-1; x++, xdst++, xsrc++) {
84
            interp = ((topleft[srcStride*(y-logo_y-yclipt)]
85
                       + topleft[srcStride*(y-logo_y-1-yclipt)]
86
                       + topleft[srcStride*(y-logo_y+1-yclipt)])*(logo_w-(x-logo_x))/logo_w
87
                      + (topright[srcStride*(y-logo_y-yclipt)]
88
                         + topright[srcStride*(y-logo_y-1-yclipt)]
89
                         + topright[srcStride*(y-logo_y+1-yclipt)])*(x-logo_x)/logo_w
90
                      + (topleft[x-logo_x-xclipl]
91
                         + topleft[x-logo_x-1-xclipl]
92
                         + topleft[x-logo_x+1-xclipl])*(logo_h-(y-logo_y))/logo_h
93
                      + (botleft[x-logo_x-xclipl]
94
                         + botleft[x-logo_x-1-xclipl]
95
                         + botleft[x-logo_x+1-xclipl])*(y-logo_y)/logo_h
96
                )/6;
97
/*                interp = (topleft[srcStride*(y-logo_y)]*(logo_w-(x-logo_x))/logo_w
98
                          + topright[srcStride*(y-logo_y)]*(x-logo_x)/logo_w
99
                          + topleft[x-logo_x]*(logo_h-(y-logo_y))/logo_h
100
                          + botleft[x-logo_x]*(y-logo_y)/logo_h
101
                          )/2;*/
102
            if (y >= logo_y+band && y < logo_y+logo_h-band && x >= logo_x+band && x < logo_x+logo_w-band) {
103
                    *xdst = interp;
104
            } else {
105
                dist = 0;
106
                if (x < logo_x+band) dist = MAX(dist, logo_x-x+band);
107
                else if (x >= logo_x+logo_w-band) dist = MAX(dist, x-(logo_x+logo_w-1-band));
108
                if (y < logo_y+band) dist = MAX(dist, logo_y-y+band);
109
                else if (y >= logo_y+logo_h-band) dist = MAX(dist, y-(logo_y+logo_h-1-band));
110
                *xdst = (*xsrc*dist + interp*(band-dist))/band;
111
                if (show && (dist == band-1)) *xdst = 0;
112
            }
113
        }
114

    
115
        dst+= dstStride;
116
        src+= srcStride;
117
    }
118
}
119

    
120
static int config(struct vf_instance *vf,
121
                  int width, int height, int d_width, int d_height,
122
                  unsigned int flags, unsigned int outfmt){
123

    
124
    return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
125
}
126

    
127

    
128
static void get_image(struct vf_instance *vf, mp_image_t *mpi){
129
    if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
130
    if(mpi->imgfmt!=vf->priv->outfmt) return; // colorspace differ
131
    // ok, we can do pp in-place (or pp disabled):
132
    vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
133
                          mpi->type, mpi->flags, mpi->w, mpi->h);
134
    mpi->planes[0]=vf->dmpi->planes[0];
135
    mpi->stride[0]=vf->dmpi->stride[0];
136
    mpi->width=vf->dmpi->width;
137
    if(mpi->flags&MP_IMGFLAG_PLANAR){
138
        mpi->planes[1]=vf->dmpi->planes[1];
139
        mpi->planes[2]=vf->dmpi->planes[2];
140
        mpi->stride[1]=vf->dmpi->stride[1];
141
        mpi->stride[2]=vf->dmpi->stride[2];
142
    }
143
    mpi->flags|=MP_IMGFLAG_DIRECT;
144
}
145

    
146
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
147
    mp_image_t *dmpi;
148

    
149
    if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
150
        // no DR, so get a new image! hope we'll get DR buffer:
151
        vf->dmpi=vf_get_image(vf->next,vf->priv->outfmt,
152
                              MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
153
                              mpi->w,mpi->h);
154
    }
155
    dmpi= vf->dmpi;
156

    
157
    delogo(dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h,
158
           vf->priv->xoff, vf->priv->yoff, vf->priv->lw, vf->priv->lh, vf->priv->band, vf->priv->show,
159
           mpi->flags&MP_IMGFLAG_DIRECT);
160
    delogo(dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w/2, mpi->h/2,
161
           vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show,
162
           mpi->flags&MP_IMGFLAG_DIRECT);
163
    delogo(dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w/2, mpi->h/2,
164
           vf->priv->xoff/2, vf->priv->yoff/2, vf->priv->lw/2, vf->priv->lh/2, vf->priv->band/2, vf->priv->show,
165
           mpi->flags&MP_IMGFLAG_DIRECT);
166

    
167
    vf_clone_mpi_attributes(dmpi, mpi);
168

    
169
    return vf_next_put_image(vf,dmpi, pts);
170
}
171

    
172
static void uninit(struct vf_instance *vf){
173
    if(!vf->priv) return;
174

    
175
    free(vf->priv);
176
    vf->priv=NULL;
177
}
178

    
179
//===========================================================================//
180

    
181
static int query_format(struct vf_instance *vf, unsigned int fmt){
182
    switch(fmt)
183
    {
184
    case IMGFMT_YV12:
185
    case IMGFMT_I420:
186
    case IMGFMT_IYUV:
187
        return vf_next_query_format(vf,vf->priv->outfmt);
188
    }
189
    return 0;
190
}
191

    
192
static const unsigned int fmt_list[]={
193
    IMGFMT_YV12,
194
    IMGFMT_I420,
195
    IMGFMT_IYUV,
196
    0
197
};
198

    
199
static int vf_open(vf_instance_t *vf, char *args){
200
    vf->config=config;
201
    vf->put_image=put_image;
202
    vf->get_image=get_image;
203
    vf->query_format=query_format;
204
    vf->uninit=uninit;
205

    
206
    mp_msg(MSGT_VFILTER, MSGL_V, "delogo: %d x %d, %d x %d, band = %d\n",
207
           vf->priv->xoff, vf->priv->yoff,
208
           vf->priv->lw, vf->priv->lh,
209
           vf->priv->band);
210

    
211
    vf->priv->show = 0;
212

    
213
    if (vf->priv->band < 0) {
214
        vf->priv->band = 4;
215
        vf->priv->show = 1;
216
    }
217

    
218

    
219
    vf->priv->lw += vf->priv->band*2;
220
    vf->priv->lh += vf->priv->band*2;
221
    vf->priv->xoff -= vf->priv->band;
222
    vf->priv->yoff -= vf->priv->band;
223

    
224
    // check csp:
225
    vf->priv->outfmt=vf_match_csp(&vf->next,fmt_list,IMGFMT_YV12);
226
    if(!vf->priv->outfmt)
227
    {
228
        uninit(vf);
229
        return 0; // no csp match :(
230
    }
231

    
232
    return 1;
233
}
234

    
235
#define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f)
236
static const m_option_t vf_opts_fields[] = {
237
    { "x", ST_OFF(xoff), CONF_TYPE_INT, 0, 0, 0, NULL },
238
    { "y", ST_OFF(yoff), CONF_TYPE_INT, 0, 0, 0, NULL },
239
    { "w", ST_OFF(lw), CONF_TYPE_INT, 0, 0, 0, NULL },
240
    { "h", ST_OFF(lh), CONF_TYPE_INT, 0, 0, 0, NULL },
241
    { "t", ST_OFF(band), CONF_TYPE_INT, 0, 0, 0, NULL },
242
    { "band", ST_OFF(band), CONF_TYPE_INT, 0, 0, 0, NULL }, // alias
243
    { NULL, NULL, 0, 0, 0, 0, NULL }
244
};
245

    
246
static const m_struct_t vf_opts = {
247
    "delogo",
248
    sizeof(struct vf_priv_s),
249
    &vf_priv_dflt,
250
    vf_opts_fields
251
};
252

    
253
const vf_info_t vf_info_delogo = {
254
    "simple logo remover",
255
    "delogo",
256
    "Jindrich Makovicka, Alex Beregszaszi",
257
    "",
258
    vf_open,
259
    &vf_opts
260
};
261

    
262
//===========================================================================//