2
Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 2 of the License, or
7
(at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
* The motion estimation is somewhat at the mercy of the input, if the input
23
frames are created purely based on spatial interpolation then for example
24
a thin black line or another random and not interpolateable pattern
26
Note: completly ignoring the "unavailable" lines during motion estimation
27
didnt look any better, so the most obvious solution would be to improve
28
tfields or penalize problematic motion vectors ...
30
* If non iterative ME is used then snow currently ignores the OBMC window
31
and as a result sometimes creates artifacts
33
* only past frames are used, we should ideally use future frames too, something
34
like filtering the whole movie in forward and then backward direction seems
35
like a interresting idea but the current filter framework is FAR from
36
supporting such things
38
* combining the motion compensated image with the input image also isnt
39
as trivial as it seems, simple blindly taking even lines from one and
40
odd ones from the other doesnt work at all as ME/MC sometimes simple
41
has nothing in the previous frames which matches the current, the current
42
algo has been found by trial and error and almost certainly can be
55
#include "cpudetect.h"
57
#include "libavcodec/avcodec.h"
58
#include "libavcodec/dsputil.h"
64
#include "img_format.h"
67
#include "libvo/fastmemcpy.h"
69
#define MIN(a,b) ((a) > (b) ? (b) : (a))
70
#define MAX(a,b) ((a) < (b) ? (b) : (a))
71
#define ABS(a) ((a) > 0 ? (a) : (-(a)))
73
//===========================================================================//
86
AVCodecContext *avctx_enc;
91
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){
96
p->frame->data[i]= src[i];
97
p->frame->linesize[i]= src_stride[i];
100
p->avctx_enc->me_cmp=
101
p->avctx_enc->me_sub_cmp= FF_CMP_SAD /*| (p->parity ? FF_CMP_ODD : FF_CMP_EVEN)*/;
102
p->frame->quality= p->qp*FF_QP2LAMBDA;
103
out_size = avcodec_encode_video(p->avctx_enc, p->outbuf, p->outbuf_size, p->frame);
104
p->frame_dec = p->avctx_enc->coded_frame;
108
int w= width >>is_chroma;
109
int h= height>>is_chroma;
110
int fils= p->frame_dec->linesize[i];
111
int srcs= src_stride[i];
114
if((y ^ p->parity) & 1){
116
if((x-2)+(y-1)*w>=0 && (x+2)+(y+1)*w<w*h){ //FIXME either alloc larger images or optimize this
117
uint8_t *filp= &p->frame_dec->data[i][x + y*fils];
118
uint8_t *srcp= &src[i][x + y*srcs];
119
int diff0= filp[-fils] - srcp[-srcs];
120
int diff1= filp[+fils] - srcp[+srcs];
121
int spatial_score= ABS(srcp[-srcs-1] - srcp[+srcs-1])
122
+ABS(srcp[-srcs ] - srcp[+srcs ])
123
+ABS(srcp[-srcs+1] - srcp[+srcs+1]) - 1;
127
{ int score= ABS(srcp[-srcs-1+j] - srcp[+srcs-1-j])\
128
+ ABS(srcp[-srcs +j] - srcp[+srcs -j])\
129
+ ABS(srcp[-srcs+1+j] - srcp[+srcs+1-j]);\
130
if(score < spatial_score){\
131
spatial_score= score;\
132
diff0= filp[-fils+j] - srcp[-srcs+j];\
133
diff1= filp[+fils-j] - srcp[+srcs-j];
135
CHECK(-1) CHECK(-2) }} }}
136
CHECK( 1) CHECK( 2) }} }}
138
if((diff0 ^ diff1) > 0){
139
int mindiff= ABS(diff0) > ABS(diff1) ? diff1 : diff0;
143
if(diff0 + diff1 > 0)
144
temp-= (diff0 + diff1 - ABS( ABS(diff0) - ABS(diff1) )/2)/2;
146
temp-= (diff0 + diff1 + ABS( ABS(diff0) - ABS(diff1) )/2)/2;
148
temp-= (diff0 + diff1)/2;
152
dst[i][x + y*dst_stride[i]]= temp > 255U ? ~(temp>>31) : temp;
154
dst[i][x + y*dst_stride[i]]= filp[0];
155
filp[0]= temp > 255U ? ~(temp>>31) : temp;
158
dst[i][x + y*dst_stride[i]]= p->frame_dec->data[i][x + y*fils];
163
if(!((y ^ p->parity) & 1)){
166
p->frame_dec->data[i][x + y*fils]=
167
dst[i][x + y*dst_stride[i]]= src[i][x + y*srcs];
169
dst[i][x + y*dst_stride[i]]= p->frame_dec->data[i][x + y*fils];
170
p->frame_dec->data[i][x + y*fils]= src[i][x + y*srcs];
180
static int config(struct vf_instance_s* vf,
181
int width, int height, int d_width, int d_height,
182
unsigned int flags, unsigned int outfmt){
184
AVCodec *enc= avcodec_find_encoder(CODEC_ID_SNOW);
187
AVCodecContext *avctx_enc;
190
int w= ((width + 31) & (~31))>>is_chroma;
191
int h= ((height + 31) & (~31))>>is_chroma;
193
vf->priv->temp_stride[i]= w;
194
vf->priv->temp[i]= malloc(vf->priv->temp_stride[i]*h*sizeof(int16_t));
195
vf->priv->src [i]= malloc(vf->priv->temp_stride[i]*h*sizeof(uint8_t));
198
vf->priv->avctx_enc= avcodec_alloc_context();
199
avctx_enc->width = width;
200
avctx_enc->height = height;
201
avctx_enc->time_base= (AVRational){1,25}; // meaningless
202
avctx_enc->gop_size = 300;
203
avctx_enc->max_b_frames= 0;
204
avctx_enc->pix_fmt = PIX_FMT_YUV420P;
205
avctx_enc->flags = CODEC_FLAG_QSCALE | CODEC_FLAG_LOW_DELAY;
206
avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
207
avctx_enc->global_quality= 1;
208
avctx_enc->flags2= CODEC_FLAG2_MEMC_ONLY;
210
avctx_enc->me_sub_cmp= FF_CMP_SAD; //SSE;
211
avctx_enc->mb_cmp= FF_CMP_SSE;
213
switch(vf->priv->mode){
217
avctx_enc->me_method= ME_ITER;
219
avctx_enc->flags |= CODEC_FLAG_4MV;
220
avctx_enc->dia_size=2;
221
// avctx_enc->mb_decision = MB_DECISSION_RD;
223
avctx_enc->flags |= CODEC_FLAG_QPEL;
226
avcodec_open(avctx_enc, enc);
229
vf->priv->frame= avcodec_alloc_frame();
231
vf->priv->outbuf_size= width*height*10;
232
vf->priv->outbuf= malloc(vf->priv->outbuf_size);
234
return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
237
static void get_image(struct vf_instance_s* vf, mp_image_t *mpi){
238
if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
239
return; //caused problems, dunno why
240
// ok, we can do pp in-place (or pp disabled):
241
vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
242
mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height);
243
mpi->planes[0]=vf->dmpi->planes[0];
244
mpi->stride[0]=vf->dmpi->stride[0];
245
mpi->width=vf->dmpi->width;
246
if(mpi->flags&MP_IMGFLAG_PLANAR){
247
mpi->planes[1]=vf->dmpi->planes[1];
248
mpi->planes[2]=vf->dmpi->planes[2];
249
mpi->stride[1]=vf->dmpi->stride[1];
250
mpi->stride[2]=vf->dmpi->stride[2];
252
mpi->flags|=MP_IMGFLAG_DIRECT;
255
static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){
258
if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
259
// no DR, so get a new image! hope we'll get DR buffer:
260
dmpi=vf_get_image(vf->next,mpi->imgfmt,
262
MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
263
mpi->width,mpi->height);
264
vf_clone_mpi_attributes(dmpi, mpi);
269
filter(vf->priv, dmpi->planes, mpi->planes, dmpi->stride, mpi->stride, mpi->w, mpi->h);
271
return vf_next_put_image(vf,dmpi, pts);
274
static void uninit(struct vf_instance_s* vf){
275
if(!vf->priv) return;
279
if(vf->priv->temp[i]) free(vf->priv->temp[i]);
280
vf->priv->temp[i]= NULL;
281
if(vf->priv->src[i]) free(vf->priv->src[i]);
282
vf->priv->src[i]= NULL;
285
av_freep(&vf->priv->avctx_enc);
287
free(vf->priv->outbuf);
292
//===========================================================================//
293
static int query_format(struct vf_instance_s* vf, unsigned int fmt){
300
return vf_next_query_format(vf,fmt);
305
static int open(vf_instance_t *vf, char* args){
308
vf->put_image=put_image;
309
vf->get_image=get_image;
310
vf->query_format=query_format;
312
vf->priv=malloc(sizeof(struct vf_priv_s));
313
memset(vf->priv, 0, sizeof(struct vf_priv_s));
316
avcodec_register_all();
319
vf->priv->parity= -1;
322
if (args) sscanf(args, "%d:%d:%d", &vf->priv->mode, &vf->priv->parity, &vf->priv->qp);
327
vf_info_t vf_info_mcdeint = {
328
"motion compensating deinterlacer",
330
"Michael Niedermayer",