Statistics
| Branch: | Revision:

ffmpeg / libavfilter / libmpcodecs / vf_mcdeint.c @ e4852fb3

History | View | Annotate | Download (10.9 KB)

1
/*
2
 * Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
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

    
22
/*
23
Known Issues:
24
* The motion estimation is somewhat at the mercy of the input, if the input
25
  frames are created purely based on spatial interpolation then for example
26
  a thin black line or another random and not interpolateable pattern
27
  will cause problems
28
  Note: completly ignoring the "unavailable" lines during motion estimation
29
  didnt look any better, so the most obvious solution would be to improve
30
  tfields or penalize problematic motion vectors ...
31

32
* If non iterative ME is used then snow currently ignores the OBMC window
33
  and as a result sometimes creates artifacts
34

35
* only past frames are used, we should ideally use future frames too, something
36
  like filtering the whole movie in forward and then backward direction seems
37
  like a interresting idea but the current filter framework is FAR from
38
  supporting such things
39

40
* combining the motion compensated image with the input image also isnt
41
  as trivial as it seems, simple blindly taking even lines from one and
42
  odd ones from the other doesnt work at all as ME/MC sometimes simple
43
  has nothing in the previous frames which matches the current, the current
44
  algo has been found by trial and error and almost certainly can be
45
  improved ...
46
*/
47

    
48
#include <stdio.h>
49
#include <stdlib.h>
50
#include <string.h>
51
#include <inttypes.h>
52
#include <math.h>
53

    
54
#include "mp_msg.h"
55
#include "cpudetect.h"
56

    
57
#include "libavutil/internal.h"
58
#include "libavutil/intreadwrite.h"
59
#include "libavcodec/avcodec.h"
60
#include "libavcodec/dsputil.h"
61

    
62
#undef fprintf
63
#undef free
64
#undef malloc
65

    
66
#include "img_format.h"
67
#include "mp_image.h"
68
#include "vf.h"
69
#include "vd_ffmpeg.h"
70

    
71
#define MIN(a,b) ((a) > (b) ? (b) : (a))
72
#define MAX(a,b) ((a) < (b) ? (b) : (a))
73
#define ABS(a) ((a) > 0 ? (a) : (-(a)))
74

    
75
//===========================================================================//
76

    
77
struct vf_priv_s {
78
    int mode;
79
    int qp;
80
    int parity;
81
#if 0
82
    int temp_stride[3];
83
    uint8_t *src[3];
84
    int16_t *temp[3];
85
#endif
86
    int outbuf_size;
87
    uint8_t *outbuf;
88
    AVCodecContext *avctx_enc;
89
    AVFrame *frame;
90
    AVFrame *frame_dec;
91
};
92

    
93
static void filter(struct vf_priv_s *p, uint8_t *dst[3], uint8_t *src[3], int dst_stride[3], int src_stride[3], int width, int height){
94
    int x, y, i;
95
    int out_size;
96

    
97
    for(i=0; i<3; i++){
98
        p->frame->data[i]= src[i];
99
        p->frame->linesize[i]= src_stride[i];
100
    }
101

    
102
    p->avctx_enc->me_cmp=
103
    p->avctx_enc->me_sub_cmp= FF_CMP_SAD /*| (p->parity ? FF_CMP_ODD : FF_CMP_EVEN)*/;
104
    p->frame->quality= p->qp*FF_QP2LAMBDA;
105
    out_size = avcodec_encode_video(p->avctx_enc, p->outbuf, p->outbuf_size, p->frame);
106
    p->frame_dec = p->avctx_enc->coded_frame;
107

    
108
    for(i=0; i<3; i++){
109
        int is_chroma= !!i;
110
        int w= width >>is_chroma;
111
        int h= height>>is_chroma;
112
        int fils= p->frame_dec->linesize[i];
113
        int srcs= src_stride[i];
114

    
115
        for(y=0; y<h; y++){
116
            if((y ^ p->parity) & 1){
117
                for(x=0; x<w; x++){
118
                    if((x-2)+(y-1)*w>=0 && (x+2)+(y+1)*w<w*h){ //FIXME either alloc larger images or optimize this
119
                        uint8_t *filp= &p->frame_dec->data[i][x + y*fils];
120
                        uint8_t *srcp= &src[i][x + y*srcs];
121
                        int diff0= filp[-fils] - srcp[-srcs];
122
                        int diff1= filp[+fils] - srcp[+srcs];
123
                        int spatial_score= ABS(srcp[-srcs-1] - srcp[+srcs-1])
124
                                          +ABS(srcp[-srcs  ] - srcp[+srcs  ])
125
                                          +ABS(srcp[-srcs+1] - srcp[+srcs+1]) - 1;
126
                        int temp= filp[0];
127

    
128
#define CHECK(j)\
129
    {   int score= ABS(srcp[-srcs-1+j] - srcp[+srcs-1-j])\
130
                 + ABS(srcp[-srcs  +j] - srcp[+srcs  -j])\
131
                 + ABS(srcp[-srcs+1+j] - srcp[+srcs+1-j]);\
132
        if(score < spatial_score){\
133
            spatial_score= score;\
134
            diff0= filp[-fils+j] - srcp[-srcs+j];\
135
            diff1= filp[+fils-j] - srcp[+srcs-j];
136

    
137
                        CHECK(-1) CHECK(-2) }} }}
138
                        CHECK( 1) CHECK( 2) }} }}
139
#if 0
140
                        if((diff0 ^ diff1) > 0){
141
                            int mindiff= ABS(diff0) > ABS(diff1) ? diff1 : diff0;
142
                            temp-= mindiff;
143
                        }
144
#elif 1
145
                        if(diff0 + diff1 > 0)
146
                            temp-= (diff0 + diff1 - ABS( ABS(diff0) - ABS(diff1) )/2)/2;
147
                        else
148
                            temp-= (diff0 + diff1 + ABS( ABS(diff0) - ABS(diff1) )/2)/2;
149
#else
150
                        temp-= (diff0 + diff1)/2;
151
#endif
152
#if 1
153
                        filp[0]=
154
                        dst[i][x + y*dst_stride[i]]= temp > 255U ? ~(temp>>31) : temp;
155
#else
156
                        dst[i][x + y*dst_stride[i]]= filp[0];
157
                        filp[0]= temp > 255U ? ~(temp>>31) : temp;
158
#endif
159
                    }else
160
                        dst[i][x + y*dst_stride[i]]= p->frame_dec->data[i][x + y*fils];
161
                }
162
            }
163
        }
164
        for(y=0; y<h; y++){
165
            if(!((y ^ p->parity) & 1)){
166
                for(x=0; x<w; x++){
167
#if 1
168
                    p->frame_dec->data[i][x + y*fils]=
169
                    dst[i][x + y*dst_stride[i]]= src[i][x + y*srcs];
170
#else
171
                    dst[i][x + y*dst_stride[i]]= p->frame_dec->data[i][x + y*fils];
172
                    p->frame_dec->data[i][x + y*fils]= src[i][x + y*srcs];
173
#endif
174
                }
175
            }
176
        }
177
    }
178
    p->parity ^= 1;
179

    
180
}
181

    
182
static int config(struct vf_instance *vf,
183
        int width, int height, int d_width, int d_height,
184
        unsigned int flags, unsigned int outfmt){
185
        int i;
186
        AVCodec *enc= avcodec_find_encoder(CODEC_ID_SNOW);
187

    
188
        for(i=0; i<3; i++){
189
            AVCodecContext *avctx_enc;
190
#if 0
191
            int is_chroma= !!i;
192
            int w= ((width  + 31) & (~31))>>is_chroma;
193
            int h= ((height + 31) & (~31))>>is_chroma;
194

195
            vf->priv->temp_stride[i]= w;
196
            vf->priv->temp[i]= malloc(vf->priv->temp_stride[i]*h*sizeof(int16_t));
197
            vf->priv->src [i]= malloc(vf->priv->temp_stride[i]*h*sizeof(uint8_t));
198
#endif
199
            avctx_enc=
200
            vf->priv->avctx_enc= avcodec_alloc_context();
201
            avctx_enc->width = width;
202
            avctx_enc->height = height;
203
            avctx_enc->time_base= (AVRational){1,25};  // meaningless
204
            avctx_enc->gop_size = 300;
205
            avctx_enc->max_b_frames= 0;
206
            avctx_enc->pix_fmt = PIX_FMT_YUV420P;
207
            avctx_enc->flags = CODEC_FLAG_QSCALE | CODEC_FLAG_LOW_DELAY;
208
            avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
209
            avctx_enc->global_quality= 1;
210
            avctx_enc->flags2= CODEC_FLAG2_MEMC_ONLY;
211
            avctx_enc->me_cmp=
212
            avctx_enc->me_sub_cmp= FF_CMP_SAD; //SSE;
213
            avctx_enc->mb_cmp= FF_CMP_SSE;
214

    
215
            switch(vf->priv->mode){
216
            case 3:
217
                avctx_enc->refs= 3;
218
            case 2:
219
                avctx_enc->me_method= ME_ITER;
220
            case 1:
221
                avctx_enc->flags |= CODEC_FLAG_4MV;
222
                avctx_enc->dia_size=2;
223
//                avctx_enc->mb_decision = MB_DECISION_RD;
224
            case 0:
225
                avctx_enc->flags |= CODEC_FLAG_QPEL;
226
            }
227

    
228
            avcodec_open(avctx_enc, enc);
229

    
230
        }
231
        vf->priv->frame= avcodec_alloc_frame();
232

    
233
        vf->priv->outbuf_size= width*height*10;
234
        vf->priv->outbuf= malloc(vf->priv->outbuf_size);
235

    
236
        return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
237
}
238

    
239
static void get_image(struct vf_instance *vf, mp_image_t *mpi){
240
    if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
241
return; //caused problems, dunno why
242
    // ok, we can do pp in-place (or pp disabled):
243
    vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
244
        mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height);
245
    mpi->planes[0]=vf->dmpi->planes[0];
246
    mpi->stride[0]=vf->dmpi->stride[0];
247
    mpi->width=vf->dmpi->width;
248
    if(mpi->flags&MP_IMGFLAG_PLANAR){
249
        mpi->planes[1]=vf->dmpi->planes[1];
250
        mpi->planes[2]=vf->dmpi->planes[2];
251
        mpi->stride[1]=vf->dmpi->stride[1];
252
        mpi->stride[2]=vf->dmpi->stride[2];
253
    }
254
    mpi->flags|=MP_IMGFLAG_DIRECT;
255
}
256

    
257
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
258
    mp_image_t *dmpi;
259

    
260
    if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
261
        // no DR, so get a new image! hope we'll get DR buffer:
262
        dmpi=vf_get_image(vf->next,mpi->imgfmt,
263
            MP_IMGTYPE_TEMP,
264
            MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
265
            mpi->width,mpi->height);
266
        vf_clone_mpi_attributes(dmpi, mpi);
267
    }else{
268
        dmpi=vf->dmpi;
269
    }
270

    
271
    filter(vf->priv, dmpi->planes, mpi->planes, dmpi->stride, mpi->stride, mpi->w, mpi->h);
272

    
273
    return vf_next_put_image(vf,dmpi, pts);
274
}
275

    
276
static void uninit(struct vf_instance *vf){
277
    if(!vf->priv) return;
278

    
279
#if 0
280
    for(i=0; i<3; i++){
281
        free(vf->priv->temp[i]);
282
        vf->priv->temp[i]= NULL;
283
        free(vf->priv->src[i]);
284
        vf->priv->src[i]= NULL;
285
    }
286
#endif
287
    if (vf->priv->avctx_enc) {
288
    avcodec_close(vf->priv->avctx_enc);
289
    av_freep(&vf->priv->avctx_enc);
290
    }
291

    
292
    free(vf->priv->outbuf);
293
    free(vf->priv);
294
    vf->priv=NULL;
295
}
296

    
297
//===========================================================================//
298
static int query_format(struct vf_instance *vf, unsigned int fmt){
299
    switch(fmt){
300
        case IMGFMT_YV12:
301
        case IMGFMT_I420:
302
        case IMGFMT_IYUV:
303
        case IMGFMT_Y800:
304
        case IMGFMT_Y8:
305
            return vf_next_query_format(vf,fmt);
306
    }
307
    return 0;
308
}
309

    
310
static int vf_open(vf_instance_t *vf, char *args){
311

    
312
    vf->config=config;
313
    vf->put_image=put_image;
314
    vf->get_image=get_image;
315
    vf->query_format=query_format;
316
    vf->uninit=uninit;
317
    vf->priv=malloc(sizeof(struct vf_priv_s));
318
    memset(vf->priv, 0, sizeof(struct vf_priv_s));
319

    
320
    init_avcodec();
321

    
322
    vf->priv->mode=0;
323
    vf->priv->parity= -1;
324
    vf->priv->qp=1;
325

    
326
    if (args) sscanf(args, "%d:%d:%d", &vf->priv->mode, &vf->priv->parity, &vf->priv->qp);
327

    
328
    return 1;
329
}
330

    
331
const vf_info_t vf_info_mcdeint = {
332
    "motion compensating deinterlacer",
333
    "mcdeint",
334
    "Michael Niedermayer",
335
    "",
336
    vf_open,
337
    NULL
338
};