Mercurial > mplayer.hg
annotate libmpcodecs/vf_mcdeint.c @ 24970:938e685a263c
ack, can't believe i wrote this crap with void pointer arithmetic
gimme some cola!!!
since the code was disabled and tests had shown it was slower,
i'm just removing it rather than fixing it.
author | rfelker |
---|---|
date | Fri, 09 Nov 2007 12:51:43 +0000 |
parents | f8d4f8eff72b |
children | 1e25755bc0c4 |
rev | line source |
---|---|
18590 | 1 /* |
2 Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at> | |
3 | |
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. | |
8 | |
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. | |
13 | |
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 | |
17 */ | |
18 | |
18592 | 19 |
20 /* | |
21 Known Issues: | |
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 | |
25 will cause problems | |
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 ... | |
29 | |
30 * If non iterative ME is used then snow currently ignores the OBMC window | |
31 and as a result sometimes creates artifacts | |
32 | |
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 | |
37 | |
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 | |
43 improved ... | |
44 */ | |
45 | |
18590 | 46 #include <stdio.h> |
47 #include <stdlib.h> | |
48 #include <string.h> | |
49 #include <inttypes.h> | |
50 #include <math.h> | |
51 | |
52 #include "config.h" | |
53 | |
54 #include "mp_msg.h" | |
55 #include "cpudetect.h" | |
56 | |
57 #include "libavcodec/avcodec.h" | |
58 #include "libavcodec/dsputil.h" | |
59 | |
60 #ifdef HAVE_MALLOC_H | |
61 #include <malloc.h> | |
62 #endif | |
63 | |
64 #include "img_format.h" | |
65 #include "mp_image.h" | |
66 #include "vf.h" | |
67 | |
68 #define MIN(a,b) ((a) > (b) ? (b) : (a)) | |
69 #define MAX(a,b) ((a) < (b) ? (b) : (a)) | |
70 #define ABS(a) ((a) > 0 ? (a) : (-(a))) | |
71 | |
72 //===========================================================================// | |
73 | |
74 struct vf_priv_s { | |
75 int mode; | |
76 int qp; | |
77 int parity; | |
78 #if 0 | |
79 int temp_stride[3]; | |
80 uint8_t *src[3]; | |
81 int16_t *temp[3]; | |
82 #endif | |
83 int outbuf_size; | |
84 uint8_t *outbuf; | |
85 AVCodecContext *avctx_enc; | |
86 AVFrame *frame; | |
87 AVFrame *frame_dec; | |
88 }; | |
89 | |
90 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){ | |
18657 | 91 int x, y, i; |
18590 | 92 int out_size; |
93 | |
94 for(i=0; i<3; i++){ | |
95 p->frame->data[i]= src[i]; | |
96 p->frame->linesize[i]= src_stride[i]; | |
97 } | |
98 | |
99 p->avctx_enc->me_cmp= | |
100 p->avctx_enc->me_sub_cmp= FF_CMP_SAD /*| (p->parity ? FF_CMP_ODD : FF_CMP_EVEN)*/; | |
101 p->frame->quality= p->qp*FF_QP2LAMBDA; | |
102 out_size = avcodec_encode_video(p->avctx_enc, p->outbuf, p->outbuf_size, p->frame); | |
103 p->frame_dec = p->avctx_enc->coded_frame; | |
104 | |
105 for(i=0; i<3; i++){ | |
106 int is_chroma= !!i; | |
107 int w= width >>is_chroma; | |
108 int h= height>>is_chroma; | |
109 int fils= p->frame_dec->linesize[i]; | |
110 int srcs= src_stride[i]; | |
111 | |
112 for(y=0; y<h; y++){ | |
113 if((y ^ p->parity) & 1){ | |
114 for(x=0; x<w; x++){ | |
18648
7cc939d4a9e2
filter left & right edges too (yeah the code is lame i know...)
michael
parents:
18647
diff
changeset
|
115 if((x-2)+(y-1)*w>=0 && (x+2)+(y+1)*w<w*h){ //FIXME either alloc larger images or optimize this |
18590 | 116 uint8_t *filp= &p->frame_dec->data[i][x + y*fils]; |
117 uint8_t *srcp= &src[i][x + y*srcs]; | |
18647 | 118 int diff0= filp[-fils] - srcp[-srcs]; |
119 int diff1= filp[+fils] - srcp[+srcs]; | |
18657 | 120 int spatial_score= ABS(srcp[-srcs-1] - srcp[+srcs-1]) |
121 +ABS(srcp[-srcs ] - srcp[+srcs ]) | |
122 +ABS(srcp[-srcs+1] - srcp[+srcs+1]) - 1; | |
18590 | 123 int temp= filp[0]; |
18647 | 124 |
18657 | 125 #define CHECK(j)\ |
126 { int score= ABS(srcp[-srcs-1+j] - srcp[+srcs-1-j])\ | |
127 + ABS(srcp[-srcs +j] - srcp[+srcs -j])\ | |
128 + ABS(srcp[-srcs+1+j] - srcp[+srcs+1-j]);\ | |
129 if(score < spatial_score){\ | |
130 spatial_score= score;\ | |
131 diff0= filp[-fils+j] - srcp[-srcs+j];\ | |
132 diff1= filp[+fils-j] - srcp[+srcs-j]; | |
133 | |
134 CHECK(-1) CHECK(-2) }} }} | |
135 CHECK( 1) CHECK( 2) }} }} | |
18590 | 136 #if 0 |
137 if((diff0 ^ diff1) > 0){ | |
138 int mindiff= ABS(diff0) > ABS(diff1) ? diff1 : diff0; | |
18647 | 139 temp-= mindiff; |
18590 | 140 } |
141 #elif 1 | |
142 if(diff0 + diff1 > 0) | |
18647 | 143 temp-= (diff0 + diff1 - ABS( ABS(diff0) - ABS(diff1) )/2)/2; |
18590 | 144 else |
18647 | 145 temp-= (diff0 + diff1 + ABS( ABS(diff0) - ABS(diff1) )/2)/2; |
18590 | 146 #else |
18647 | 147 temp-= (diff0 + diff1)/2; |
18590 | 148 #endif |
149 #if 1 | |
150 filp[0]= | |
151 dst[i][x + y*dst_stride[i]]= temp > 255U ? ~(temp>>31) : temp; | |
152 #else | |
153 dst[i][x + y*dst_stride[i]]= filp[0]; | |
154 filp[0]= temp > 255U ? ~(temp>>31) : temp; | |
155 #endif | |
156 }else | |
157 dst[i][x + y*dst_stride[i]]= p->frame_dec->data[i][x + y*fils]; | |
158 } | |
159 } | |
160 } | |
161 for(y=0; y<h; y++){ | |
162 if(!((y ^ p->parity) & 1)){ | |
163 for(x=0; x<w; x++){ | |
164 #if 1 | |
165 p->frame_dec->data[i][x + y*fils]= | |
166 dst[i][x + y*dst_stride[i]]= src[i][x + y*srcs]; | |
167 #else | |
168 dst[i][x + y*dst_stride[i]]= p->frame_dec->data[i][x + y*fils]; | |
169 p->frame_dec->data[i][x + y*fils]= src[i][x + y*srcs]; | |
170 #endif | |
171 } | |
172 } | |
173 } | |
174 } | |
175 p->parity ^= 1; | |
176 | |
177 } | |
178 | |
179 static int config(struct vf_instance_s* vf, | |
180 int width, int height, int d_width, int d_height, | |
181 unsigned int flags, unsigned int outfmt){ | |
182 int i; | |
183 AVCodec *enc= avcodec_find_encoder(CODEC_ID_SNOW); | |
184 | |
185 for(i=0; i<3; i++){ | |
186 AVCodecContext *avctx_enc; | |
187 #if 0 | |
188 int is_chroma= !!i; | |
189 int w= ((width + 31) & (~31))>>is_chroma; | |
190 int h= ((height + 31) & (~31))>>is_chroma; | |
191 | |
192 vf->priv->temp_stride[i]= w; | |
193 vf->priv->temp[i]= malloc(vf->priv->temp_stride[i]*h*sizeof(int16_t)); | |
194 vf->priv->src [i]= malloc(vf->priv->temp_stride[i]*h*sizeof(uint8_t)); | |
195 #endif | |
196 avctx_enc= | |
197 vf->priv->avctx_enc= avcodec_alloc_context(); | |
198 avctx_enc->width = width; | |
199 avctx_enc->height = height; | |
200 avctx_enc->time_base= (AVRational){1,25}; // meaningless | |
201 avctx_enc->gop_size = 300; | |
202 avctx_enc->max_b_frames= 0; | |
203 avctx_enc->pix_fmt = PIX_FMT_YUV420P; | |
204 avctx_enc->flags = CODEC_FLAG_QSCALE | CODEC_FLAG_LOW_DELAY; | |
205 avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; | |
206 avctx_enc->global_quality= 1; | |
207 avctx_enc->flags2= CODEC_FLAG2_MEMC_ONLY; | |
208 avctx_enc->me_cmp= | |
209 avctx_enc->me_sub_cmp= FF_CMP_SAD; //SSE; | |
210 avctx_enc->mb_cmp= FF_CMP_SSE; | |
211 | |
212 switch(vf->priv->mode){ | |
213 case 3: | |
214 avctx_enc->refs= 3; | |
215 case 2: | |
216 avctx_enc->me_method= ME_ITER; | |
217 case 1: | |
218 avctx_enc->flags |= CODEC_FLAG_4MV; | |
219 avctx_enc->dia_size=2; | |
22283
bc9e95184521
cosmetics: Fix some common typos, sepErate --> sepArate, deciSSion --> deciSion.
diego
parents:
18821
diff
changeset
|
220 // avctx_enc->mb_decision = MB_DECISION_RD; |
18590 | 221 case 0: |
222 avctx_enc->flags |= CODEC_FLAG_QPEL; | |
223 } | |
224 | |
225 avcodec_open(avctx_enc, enc); | |
226 | |
227 } | |
228 vf->priv->frame= avcodec_alloc_frame(); | |
229 | |
230 vf->priv->outbuf_size= width*height*10; | |
231 vf->priv->outbuf= malloc(vf->priv->outbuf_size); | |
232 | |
233 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); | |
234 } | |
235 | |
236 static void get_image(struct vf_instance_s* vf, mp_image_t *mpi){ | |
237 if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change | |
238 return; //caused problems, dunno why | |
239 // ok, we can do pp in-place (or pp disabled): | |
240 vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, | |
241 mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height); | |
242 mpi->planes[0]=vf->dmpi->planes[0]; | |
243 mpi->stride[0]=vf->dmpi->stride[0]; | |
244 mpi->width=vf->dmpi->width; | |
245 if(mpi->flags&MP_IMGFLAG_PLANAR){ | |
246 mpi->planes[1]=vf->dmpi->planes[1]; | |
247 mpi->planes[2]=vf->dmpi->planes[2]; | |
248 mpi->stride[1]=vf->dmpi->stride[1]; | |
249 mpi->stride[2]=vf->dmpi->stride[2]; | |
250 } | |
251 mpi->flags|=MP_IMGFLAG_DIRECT; | |
252 } | |
253 | |
254 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){ | |
255 mp_image_t *dmpi; | |
256 | |
257 if(!(mpi->flags&MP_IMGFLAG_DIRECT)){ | |
258 // no DR, so get a new image! hope we'll get DR buffer: | |
259 dmpi=vf_get_image(vf->next,mpi->imgfmt, | |
260 MP_IMGTYPE_TEMP, | |
261 MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE, | |
262 mpi->width,mpi->height); | |
263 vf_clone_mpi_attributes(dmpi, mpi); | |
264 }else{ | |
265 dmpi=vf->dmpi; | |
266 } | |
267 | |
268 filter(vf->priv, dmpi->planes, mpi->planes, dmpi->stride, mpi->stride, mpi->w, mpi->h); | |
269 | |
270 return vf_next_put_image(vf,dmpi, pts); | |
271 } | |
272 | |
273 static void uninit(struct vf_instance_s* vf){ | |
274 if(!vf->priv) return; | |
275 | |
276 #if 0 | |
277 for(i=0; i<3; i++){ | |
278 if(vf->priv->temp[i]) free(vf->priv->temp[i]); | |
279 vf->priv->temp[i]= NULL; | |
280 if(vf->priv->src[i]) free(vf->priv->src[i]); | |
281 vf->priv->src[i]= NULL; | |
282 } | |
283 #endif | |
18821 | 284 if (vf->priv->avctx_enc) { |
18752 | 285 avcodec_close(vf->priv->avctx_enc); |
18590 | 286 av_freep(&vf->priv->avctx_enc); |
18821 | 287 } |
18590 | 288 |
289 free(vf->priv->outbuf); | |
290 free(vf->priv); | |
291 vf->priv=NULL; | |
292 } | |
293 | |
294 //===========================================================================// | |
295 static int query_format(struct vf_instance_s* vf, unsigned int fmt){ | |
296 switch(fmt){ | |
297 case IMGFMT_YV12: | |
298 case IMGFMT_I420: | |
299 case IMGFMT_IYUV: | |
300 case IMGFMT_Y800: | |
301 case IMGFMT_Y8: | |
302 return vf_next_query_format(vf,fmt); | |
303 } | |
304 return 0; | |
305 } | |
306 | |
307 static int open(vf_instance_t *vf, char* args){ | |
308 | |
309 vf->config=config; | |
310 vf->put_image=put_image; | |
311 vf->get_image=get_image; | |
312 vf->query_format=query_format; | |
313 vf->uninit=uninit; | |
314 vf->priv=malloc(sizeof(struct vf_priv_s)); | |
315 memset(vf->priv, 0, sizeof(struct vf_priv_s)); | |
316 | |
317 avcodec_init(); | |
318 avcodec_register_all(); | |
319 | |
320 vf->priv->mode=0; | |
321 vf->priv->parity= -1; | |
322 vf->priv->qp=1; | |
323 | |
324 if (args) sscanf(args, "%d:%d:%d", &vf->priv->mode, &vf->priv->parity, &vf->priv->qp); | |
325 | |
326 return 1; | |
327 } | |
328 | |
329 vf_info_t vf_info_mcdeint = { | |
330 "motion compensating deinterlacer", | |
331 "mcdeint", | |
332 "Michael Niedermayer", | |
333 "", | |
334 open, | |
335 NULL | |
336 }; |