• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavfilter/libmpcodecs/vf_mcdeint.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
00003  *
00004  * This file is part of MPlayer.
00005  *
00006  * MPlayer is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * MPlayer is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
00018  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00019  */
00020 
00021 
00022 /*
00023 Known Issues:
00024 * The motion estimation is somewhat at the mercy of the input, if the input
00025   frames are created purely based on spatial interpolation then for example
00026   a thin black line or another random and not interpolateable pattern
00027   will cause problems
00028   Note: completly ignoring the "unavailable" lines during motion estimation
00029   didnt look any better, so the most obvious solution would be to improve
00030   tfields or penalize problematic motion vectors ...
00031 
00032 * If non iterative ME is used then snow currently ignores the OBMC window
00033   and as a result sometimes creates artifacts
00034 
00035 * only past frames are used, we should ideally use future frames too, something
00036   like filtering the whole movie in forward and then backward direction seems
00037   like a interresting idea but the current filter framework is FAR from
00038   supporting such things
00039 
00040 * combining the motion compensated image with the input image also isnt
00041   as trivial as it seems, simple blindly taking even lines from one and
00042   odd ones from the other doesnt work at all as ME/MC sometimes simple
00043   has nothing in the previous frames which matches the current, the current
00044   algo has been found by trial and error and almost certainly can be
00045   improved ...
00046 */
00047 
00048 #include <stdio.h>
00049 #include <stdlib.h>
00050 #include <string.h>
00051 #include <inttypes.h>
00052 #include <math.h>
00053 
00054 #include "mp_msg.h"
00055 #include "cpudetect.h"
00056 
00057 #include "libavutil/internal.h"
00058 #include "libavutil/intreadwrite.h"
00059 #include "libavcodec/avcodec.h"
00060 #include "libavcodec/dsputil.h"
00061 
00062 #undef fprintf
00063 #undef free
00064 #undef malloc
00065 
00066 #include "img_format.h"
00067 #include "mp_image.h"
00068 #include "vf.h"
00069 #include "vd_ffmpeg.h"
00070 
00071 #define MIN(a,b) ((a) > (b) ? (b) : (a))
00072 #define MAX(a,b) ((a) < (b) ? (b) : (a))
00073 #define ABS(a) ((a) > 0 ? (a) : (-(a)))
00074 
00075 //===========================================================================//
00076 
00077 struct vf_priv_s {
00078     int mode;
00079     int qp;
00080     int parity;
00081 #if 0
00082     int temp_stride[3];
00083     uint8_t *src[3];
00084     int16_t *temp[3];
00085 #endif
00086     int outbuf_size;
00087     uint8_t *outbuf;
00088     AVCodecContext *avctx_enc;
00089     AVFrame *frame;
00090     AVFrame *frame_dec;
00091 };
00092 
00093 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){
00094     int x, y, i;
00095     int out_size;
00096 
00097     for(i=0; i<3; i++){
00098         p->frame->data[i]= src[i];
00099         p->frame->linesize[i]= src_stride[i];
00100     }
00101 
00102     p->avctx_enc->me_cmp=
00103     p->avctx_enc->me_sub_cmp= FF_CMP_SAD /*| (p->parity ? FF_CMP_ODD : FF_CMP_EVEN)*/;
00104     p->frame->quality= p->qp*FF_QP2LAMBDA;
00105     out_size = avcodec_encode_video(p->avctx_enc, p->outbuf, p->outbuf_size, p->frame);
00106     p->frame_dec = p->avctx_enc->coded_frame;
00107 
00108     for(i=0; i<3; i++){
00109         int is_chroma= !!i;
00110         int w= width >>is_chroma;
00111         int h= height>>is_chroma;
00112         int fils= p->frame_dec->linesize[i];
00113         int srcs= src_stride[i];
00114 
00115         for(y=0; y<h; y++){
00116             if((y ^ p->parity) & 1){
00117                 for(x=0; x<w; x++){
00118                     if((x-2)+(y-1)*w>=0 && (x+2)+(y+1)*w<w*h){ //FIXME either alloc larger images or optimize this
00119                         uint8_t *filp= &p->frame_dec->data[i][x + y*fils];
00120                         uint8_t *srcp= &src[i][x + y*srcs];
00121                         int diff0= filp[-fils] - srcp[-srcs];
00122                         int diff1= filp[+fils] - srcp[+srcs];
00123                         int spatial_score= ABS(srcp[-srcs-1] - srcp[+srcs-1])
00124                                           +ABS(srcp[-srcs  ] - srcp[+srcs  ])
00125                                           +ABS(srcp[-srcs+1] - srcp[+srcs+1]) - 1;
00126                         int temp= filp[0];
00127 
00128 #define CHECK(j)\
00129     {   int score= ABS(srcp[-srcs-1+j] - srcp[+srcs-1-j])\
00130                  + ABS(srcp[-srcs  +j] - srcp[+srcs  -j])\
00131                  + ABS(srcp[-srcs+1+j] - srcp[+srcs+1-j]);\
00132         if(score < spatial_score){\
00133             spatial_score= score;\
00134             diff0= filp[-fils+j] - srcp[-srcs+j];\
00135             diff1= filp[+fils-j] - srcp[+srcs-j];
00136 
00137                         CHECK(-1) CHECK(-2) }} }}
00138                         CHECK( 1) CHECK( 2) }} }}
00139 #if 0
00140                         if((diff0 ^ diff1) > 0){
00141                             int mindiff= ABS(diff0) > ABS(diff1) ? diff1 : diff0;
00142                             temp-= mindiff;
00143                         }
00144 #elif 1
00145                         if(diff0 + diff1 > 0)
00146                             temp-= (diff0 + diff1 - ABS( ABS(diff0) - ABS(diff1) )/2)/2;
00147                         else
00148                             temp-= (diff0 + diff1 + ABS( ABS(diff0) - ABS(diff1) )/2)/2;
00149 #else
00150                         temp-= (diff0 + diff1)/2;
00151 #endif
00152 #if 1
00153                         filp[0]=
00154                         dst[i][x + y*dst_stride[i]]= temp > 255U ? ~(temp>>31) : temp;
00155 #else
00156                         dst[i][x + y*dst_stride[i]]= filp[0];
00157                         filp[0]= temp > 255U ? ~(temp>>31) : temp;
00158 #endif
00159                     }else
00160                         dst[i][x + y*dst_stride[i]]= p->frame_dec->data[i][x + y*fils];
00161                 }
00162             }
00163         }
00164         for(y=0; y<h; y++){
00165             if(!((y ^ p->parity) & 1)){
00166                 for(x=0; x<w; x++){
00167 #if 1
00168                     p->frame_dec->data[i][x + y*fils]=
00169                     dst[i][x + y*dst_stride[i]]= src[i][x + y*srcs];
00170 #else
00171                     dst[i][x + y*dst_stride[i]]= p->frame_dec->data[i][x + y*fils];
00172                     p->frame_dec->data[i][x + y*fils]= src[i][x + y*srcs];
00173 #endif
00174                 }
00175             }
00176         }
00177     }
00178     p->parity ^= 1;
00179 
00180 }
00181 
00182 static int config(struct vf_instance *vf,
00183         int width, int height, int d_width, int d_height,
00184         unsigned int flags, unsigned int outfmt){
00185         int i;
00186         AVCodec *enc= avcodec_find_encoder(CODEC_ID_SNOW);
00187 
00188         for(i=0; i<3; i++){
00189             AVCodecContext *avctx_enc;
00190 #if 0
00191             int is_chroma= !!i;
00192             int w= ((width  + 31) & (~31))>>is_chroma;
00193             int h= ((height + 31) & (~31))>>is_chroma;
00194 
00195             vf->priv->temp_stride[i]= w;
00196             vf->priv->temp[i]= malloc(vf->priv->temp_stride[i]*h*sizeof(int16_t));
00197             vf->priv->src [i]= malloc(vf->priv->temp_stride[i]*h*sizeof(uint8_t));
00198 #endif
00199             avctx_enc=
00200             vf->priv->avctx_enc= avcodec_alloc_context();
00201             avctx_enc->width = width;
00202             avctx_enc->height = height;
00203             avctx_enc->time_base= (AVRational){1,25};  // meaningless
00204             avctx_enc->gop_size = 300;
00205             avctx_enc->max_b_frames= 0;
00206             avctx_enc->pix_fmt = PIX_FMT_YUV420P;
00207             avctx_enc->flags = CODEC_FLAG_QSCALE | CODEC_FLAG_LOW_DELAY;
00208             avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
00209             avctx_enc->global_quality= 1;
00210             avctx_enc->flags2= CODEC_FLAG2_MEMC_ONLY;
00211             avctx_enc->me_cmp=
00212             avctx_enc->me_sub_cmp= FF_CMP_SAD; //SSE;
00213             avctx_enc->mb_cmp= FF_CMP_SSE;
00214 
00215             switch(vf->priv->mode){
00216             case 3:
00217                 avctx_enc->refs= 3;
00218             case 2:
00219                 avctx_enc->me_method= ME_ITER;
00220             case 1:
00221                 avctx_enc->flags |= CODEC_FLAG_4MV;
00222                 avctx_enc->dia_size=2;
00223 //                avctx_enc->mb_decision = MB_DECISION_RD;
00224             case 0:
00225                 avctx_enc->flags |= CODEC_FLAG_QPEL;
00226             }
00227 
00228             avcodec_open(avctx_enc, enc);
00229 
00230         }
00231         vf->priv->frame= avcodec_alloc_frame();
00232 
00233         vf->priv->outbuf_size= width*height*10;
00234         vf->priv->outbuf= malloc(vf->priv->outbuf_size);
00235 
00236         return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
00237 }
00238 
00239 static void get_image(struct vf_instance *vf, mp_image_t *mpi){
00240     if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
00241 return; //caused problems, dunno why
00242     // ok, we can do pp in-place (or pp disabled):
00243     vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
00244         mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height);
00245     mpi->planes[0]=vf->dmpi->planes[0];
00246     mpi->stride[0]=vf->dmpi->stride[0];
00247     mpi->width=vf->dmpi->width;
00248     if(mpi->flags&MP_IMGFLAG_PLANAR){
00249         mpi->planes[1]=vf->dmpi->planes[1];
00250         mpi->planes[2]=vf->dmpi->planes[2];
00251         mpi->stride[1]=vf->dmpi->stride[1];
00252         mpi->stride[2]=vf->dmpi->stride[2];
00253     }
00254     mpi->flags|=MP_IMGFLAG_DIRECT;
00255 }
00256 
00257 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
00258     mp_image_t *dmpi;
00259 
00260     if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
00261         // no DR, so get a new image! hope we'll get DR buffer:
00262         dmpi=vf_get_image(vf->next,mpi->imgfmt,
00263             MP_IMGTYPE_TEMP,
00264             MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
00265             mpi->width,mpi->height);
00266         vf_clone_mpi_attributes(dmpi, mpi);
00267     }else{
00268         dmpi=vf->dmpi;
00269     }
00270 
00271     filter(vf->priv, dmpi->planes, mpi->planes, dmpi->stride, mpi->stride, mpi->w, mpi->h);
00272 
00273     return vf_next_put_image(vf,dmpi, pts);
00274 }
00275 
00276 static void uninit(struct vf_instance *vf){
00277     if(!vf->priv) return;
00278 
00279 #if 0
00280     for(i=0; i<3; i++){
00281         free(vf->priv->temp[i]);
00282         vf->priv->temp[i]= NULL;
00283         free(vf->priv->src[i]);
00284         vf->priv->src[i]= NULL;
00285     }
00286 #endif
00287     if (vf->priv->avctx_enc) {
00288     avcodec_close(vf->priv->avctx_enc);
00289     av_freep(&vf->priv->avctx_enc);
00290     }
00291 
00292     free(vf->priv->outbuf);
00293     free(vf->priv);
00294     vf->priv=NULL;
00295 }
00296 
00297 //===========================================================================//
00298 static int query_format(struct vf_instance *vf, unsigned int fmt){
00299     switch(fmt){
00300         case IMGFMT_YV12:
00301         case IMGFMT_I420:
00302         case IMGFMT_IYUV:
00303         case IMGFMT_Y800:
00304         case IMGFMT_Y8:
00305             return vf_next_query_format(vf,fmt);
00306     }
00307     return 0;
00308 }
00309 
00310 static int vf_open(vf_instance_t *vf, char *args){
00311 
00312     vf->config=config;
00313     vf->put_image=put_image;
00314     vf->get_image=get_image;
00315     vf->query_format=query_format;
00316     vf->uninit=uninit;
00317     vf->priv=malloc(sizeof(struct vf_priv_s));
00318     memset(vf->priv, 0, sizeof(struct vf_priv_s));
00319 
00320     init_avcodec();
00321 
00322     vf->priv->mode=0;
00323     vf->priv->parity= -1;
00324     vf->priv->qp=1;
00325 
00326     if (args) sscanf(args, "%d:%d:%d", &vf->priv->mode, &vf->priv->parity, &vf->priv->qp);
00327 
00328     return 1;
00329 }
00330 
00331 const vf_info_t vf_info_mcdeint = {
00332     "motion compensating deinterlacer",
00333     "mcdeint",
00334     "Michael Niedermayer",
00335     "",
00336     vf_open,
00337     NULL
00338 };

Generated on Fri Feb 22 2013 07:24:30 for FFmpeg by  doxygen 1.7.1