~ubuntu-branches/ubuntu/hardy/avidemux/hardy

« back to all changes in this revision

Viewing changes to avidemux/ADM_video/ADM_vidMcDeint.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Matvey Kozhev
  • Date: 2007-12-18 13:53:04 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20071218135304-cdqec2lg2bglyz15
Tags: 1:2.4~preview3-0.0ubuntu1
* Upload to Ubuntu. (LP: #163287, LP: #126572)
* debian/changelog: re-added Ubuntu releases.
* debian/control:
  - Require debhelper >= 5.0.51 (for dh_icons) and imagemagick.
  - Build-depend on libsdl1.2-dev instead of libsdl-dev.
  - Build against newer libx264-dev. (LP: #138854)
  - Removed libamrnb-dev, not in Ubuntu yet.
* debian/rules:
  - Install all icon sizes, using convert (upstream installs none).
  - Added missing calls to dh_installmenu, dh_installman, dh_icons and
    dh_desktop.
* debian/menu, debian/avidemux-qt.menu:
  - Corrected package and executable names.
* debian/avidemux-common.install: Install icons.
* debian/avidemux.common.manpages: Install man/avidemux.1.
* debian/links, debian/avidemux-cli.links, debian/avidemux-gtk.links:
  - Link manpages to avidemux.1.gz.
* debian/install, debian/avidemux-qt.install, debian/avidemux-gtk.desktop,
  debian/avidemux-qt.desktop: Install desktop files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//
2
 
//
3
 
// Port to avidemux2 by mean
4
 
// Original filter by M Niedermayer
5
 
// See below
6
 
/*
7
 
    Copyright (C) 2006 Michael Niedermayer <michaelni@gmx.at>
8
 
 
9
 
    This program is free software; you can redistribute it and/or modify
10
 
    it under the terms of the GNU General Public License as published by
11
 
    the Free Software Foundation; either version 2 of the License, or
12
 
    (at your option) any later version.
13
 
 
14
 
    This program is distributed in the hope that it will be useful,
15
 
    but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 
    GNU General Public License for more details.
18
 
 
19
 
    You should have received a copy of the GNU General Public License
20
 
    along with this program; if not, write to the Free Software
21
 
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
 
*/
23
 
 
24
 
#include <stdio.h>
25
 
#include <stdlib.h>
26
 
#include <string.h>
27
 
#include <ADM_assert.h>
28
 
#include "ADM_lavcodec.h"
29
 
 
30
 
#include "config.h"
31
 
#include "fourcc.h"
32
 
#include "avio.hxx"
33
 
#include "config.h"
34
 
#include "avi_vars.h"
35
 
 
36
 
 
37
 
 
38
 
#include "ADM_toolkit/toolkit.hxx"
39
 
#include "ADM_editor/ADM_edit.hxx"
40
 
#include "ADM_video/ADM_genvideo.hxx"
41
 
 
42
 
#include "ADM_filter/video_filters.h"
43
 
#include "ADM_video/ADM_cache.h"
44
 
 
45
 
#include "ADM_video/ADM_vidMcDeint_param.h"
46
 
 
47
 
static FILTER_PARAM mcDeintParam={3,{"mode","qp","initial_parity"}};
48
 
 
49
 
struct vf_priv_s {
50
 
    int mode;
51
 
    int qp;
52
 
    int parity;
53
 
#if 0
54
 
    int temp_stride[3];
55
 
    uint8_t *src[3];
56
 
    int16_t *temp[3];
57
 
#endif
58
 
    int outbuf_size;
59
 
    uint8_t *outbuf;
60
 
    AVCodecContext *avctx_enc;
61
 
    AVFrame *frame;
62
 
    AVFrame *frame_dec;
63
 
};
64
 
 
65
 
 
66
 
class  AVDMVideoMCDeint:public AVDMGenericVideoStream
67
 
 {
68
 
 
69
 
 protected:
70
 
                MCDEINT_PARAM *_param;
71
 
                VideoCache      *vidCache;
72
 
                uint8_t         init();
73
 
                uint8_t         cleanup();
74
 
                vf_priv_s       priv;
75
 
 public:
76
 
    virtual char          *printConf(void) ;
77
 
                  AVDMVideoMCDeint(  AVDMGenericVideoStream *in,CONFcouple *setup);
78
 
                 ~AVDMVideoMCDeint();
79
 
 virtual uint8_t getFrameNumberNoAlloc(uint32_t frame, uint32_t *len,
80
 
                            ADMImage *data,uint32_t *flags);
81
 
 
82
 
  virtual uint8_t configure( AVDMGenericVideoStream *instream);
83
 
  virtual uint8_t getCoupledConf( CONFcouple **couples);
84
 
 }     ;
85
 
 
86
 
SCRIPT_CREATE(mcdeint_script,AVDMVideoMCDeint,mcDeintParam);
87
 
BUILD_CREATE(mcdeint_create,AVDMVideoMCDeint);
88
 
 
89
 
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);
90
 
uint8_t DIA_mcDeint(MCDEINT_PARAM *param);
91
 
 
92
 
 
93
 
char *AVDMVideoMCDeint::printConf( void )
94
 
{
95
 
static char buf[50];
96
 
 
97
 
        sprintf((char *)buf," MC deinterlacer : Mode %d, qp %d, parity %d ",_param->mode,_param->qp,_param->initial_parity);
98
 
        return buf;
99
 
}
100
 
uint8_t AVDMVideoMCDeint::configure(AVDMGenericVideoStream * instream)
101
 
{
102
 
    if( DIA_mcDeint(_param))
103
 
    {
104
 
      cleanup();
105
 
      init();
106
 
      return 1;
107
 
    }
108
 
    return 0;
109
 
}
110
 
uint8_t AVDMVideoMCDeint::getCoupledConf( CONFcouple **couples)
111
 
{
112
 
 
113
 
                        ADM_assert(_param);
114
 
                        *couples=new CONFcouple(3);
115
 
 
116
 
#define CSET(x)  (*couples)->setCouple((char *)#x,(_param->x))
117
 
                CSET(mode);
118
 
                CSET(qp);
119
 
                CSET(initial_parity);
120
 
                return 1;
121
 
 
122
 
}
123
 
 
124
 
//_______________________________________________________________
125
 
AVDMVideoMCDeint::AVDMVideoMCDeint(AVDMGenericVideoStream *in,CONFcouple *couples)
126
 
{
127
 
 
128
 
        _in=in;
129
 
        memcpy(&_info,_in->getInfo(),sizeof(_info));
130
 
        _param=NEW(MCDEINT_PARAM);
131
 
        vidCache=new VideoCache(4,_in);
132
 
        if(couples)
133
 
        {
134
 
                GET(mode);
135
 
                GET(qp);
136
 
                GET(initial_parity);
137
 
        }
138
 
        else
139
 
        {
140
 
                _param->mode=0;
141
 
                _param->qp=1;
142
 
                _param->initial_parity=0;
143
 
                
144
 
        }
145
 
        _info.encoding=1;
146
 
        init();
147
 
}
148
 
 
149
 
 
150
 
 
151
 
// ___ destructor_____________
152
 
AVDMVideoMCDeint::~AVDMVideoMCDeint()
153
 
{
154
 
      cleanup();
155
 
      delete  vidCache;
156
 
      delete _param;
157
 
      _param=NULL;
158
 
      vidCache=NULL;
159
 
}
160
 
uint8_t AVDMVideoMCDeint::getFrameNumberNoAlloc(uint32_t frame,
161
 
                                uint32_t *len,
162
 
                                ADMImage *data,
163
 
                                uint32_t *flags)
164
 
{
165
 
                        if(frame>=_info.nb_frames) 
166
 
                        {
167
 
                                printf("MPdelogo : Filter : out of bound!\n");
168
 
                                return 0;
169
 
                        }
170
 
        
171
 
                        ADM_assert(_param);
172
 
 
173
 
ADMImage *curImage;
174
 
char txt[256];
175
 
                        curImage=vidCache->getImage(frame);
176
 
                        if(!curImage)
177
 
                        {
178
 
                                printf("MCDeint : error getting frame\n");
179
 
                                return 0;
180
 
                        }
181
 
              
182
 
                      // Prepare to call filter...
183
 
                  uint8_t *dplanes[3],*splanes[3];
184
 
                  int dstride[3],sstride[3];
185
 
 
186
 
                  dstride[0]=sstride[0]=_info.width;
187
 
                  dstride[2]=sstride[2]=dstride[1]=sstride[1]=_info.width>>1;
188
 
 
189
 
                  splanes[0]=YPLANE(curImage);
190
 
                  splanes[1]=UPLANE(curImage);
191
 
                  splanes[2]=VPLANE(curImage);
192
 
 
193
 
                  dplanes[0]=YPLANE(data);
194
 
                  dplanes[1]=UPLANE(data);
195
 
                  dplanes[2]=VPLANE(data);
196
 
 
197
 
 
198
 
                  filter(&priv, dplanes, splanes, dstride, sstride, _info.width, _info.height);
199
 
                  vidCache->unlockAll();
200
 
        return 1;
201
 
}
202
 
uint8_t AVDMVideoMCDeint::init( void )
203
 
{
204
 
  memset(&priv,0,sizeof(priv));
205
 
  int i;
206
 
  
207
 
  AVCodec *enc= avcodec_find_encoder(CODEC_ID_SNOW);
208
 
  ADM_assert(enc);
209
 
 
210
 
        for(i=0; i<3; i++)
211
 
        {
212
 
            AVCodecContext *avctx_enc;
213
 
            avctx_enc=     priv.avctx_enc= avcodec_alloc_context();
214
 
            avctx_enc->width = _info.width;
215
 
            avctx_enc->height = _info.height;
216
 
            avctx_enc->time_base= (AVRational){1,25};  // meaningless
217
 
            avctx_enc->gop_size = 300;
218
 
            avctx_enc->max_b_frames= 0;
219
 
            avctx_enc->pix_fmt = PIX_FMT_YUV420P;
220
 
            avctx_enc->flags = CODEC_FLAG_QSCALE | CODEC_FLAG_LOW_DELAY;
221
 
            avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
222
 
            avctx_enc->global_quality= 1;
223
 
            avctx_enc->flags2= CODEC_FLAG2_MEMC_ONLY;
224
 
            avctx_enc->me_cmp=
225
 
            avctx_enc->me_sub_cmp= FF_CMP_SAD; //SSE;
226
 
            avctx_enc->mb_cmp= FF_CMP_SSE;
227
 
 
228
 
            switch(_param->mode)
229
 
            {
230
 
            case 3:
231
 
                avctx_enc->refs= 3;
232
 
            case 2:
233
 
                avctx_enc->me_method= ME_ITER;
234
 
            case 1:
235
 
                avctx_enc->flags |= CODEC_FLAG_4MV;
236
 
                avctx_enc->dia_size=2;
237
 
//                avctx_enc->mb_decision = MB_DECISSION_RD;
238
 
            case 0:
239
 
                avctx_enc->flags |= CODEC_FLAG_QPEL;
240
 
            }
241
 
 
242
 
            avcodec_open(avctx_enc, enc);
243
 
 
244
 
        }
245
 
        priv.frame= avcodec_alloc_frame();
246
 
 
247
 
        priv.outbuf_size= _info.width*_info.height*10;
248
 
        priv.outbuf= (uint8_t *)ADM_alloc(priv.outbuf_size);
249
 
        priv.parity=_param->initial_parity;
250
 
  return 1;
251
 
}
252
 
uint8_t AVDMVideoMCDeint::cleanup( void )
253
 
{
254
 
  //
255
 
   avcodec_close(priv.avctx_enc);
256
 
   av_free(priv.avctx_enc);
257
 
   ADM_dezalloc(priv.outbuf);
258
 
   memset(&priv,0,sizeof(priv));
259
 
  return 1;
260
 
}
261
 
 
262
 
 
263
 
/*
264
 
Known Issues:
265
 
* The motion estimation is somewhat at the mercy of the input, if the input
266
 
  frames are created purely based on spatial interpolation then for example
267
 
  a thin black line or another random and not interpolateable pattern
268
 
  will cause problems
269
 
  Note: completly ignoring the "unavailable" lines during motion estimation 
270
 
  didnt look any better, so the most obvious solution would be to improve
271
 
  tfields or penalize problematic motion vectors ...
272
 
 
273
 
* If non iterative ME is used then snow currently ignores the OBMC window
274
 
  and as a result sometimes creates artifacts
275
 
 
276
 
* only past frames are used, we should ideally use future frames too, something
277
 
  like filtering the whole movie in forward and then backward direction seems 
278
 
  like a interresting idea but the current filter framework is FAR from
279
 
  supporting such things
280
 
 
281
 
* combining the motion compensated image with the input image also isnt
282
 
  as trivial as it seems, simple blindly taking even lines from one and
283
 
  odd ones from the other doesnt work at all as ME/MC sometimes simple
284
 
  has nothing in the previous frames which matches the current, the current
285
 
  algo has been found by trial and error and almost certainly can be
286
 
  improved ...
287
 
*/
288
 
 
289
 
 
290
 
 
291
 
#define MIN(a,b) ((a) > (b) ? (b) : (a))
292
 
#define MAX(a,b) ((a) < (b) ? (b) : (a))
293
 
#define ABS(a) ((a) > 0 ? (a) : (-(a)))
294
 
 
295
 
//===========================================================================//
296
 
 
297
 
 
298
 
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){
299
 
    int x, y, i;
300
 
    int out_size;
301
 
 
302
 
    for(i=0; i<3; i++){
303
 
        p->frame->data[i]= src[i];
304
 
        p->frame->linesize[i]= src_stride[i];
305
 
    }
306
 
 
307
 
    p->avctx_enc->me_cmp=
308
 
    p->avctx_enc->me_sub_cmp= FF_CMP_SAD /*| (p->parity ? FF_CMP_ODD : FF_CMP_EVEN)*/;
309
 
    p->frame->quality= p->qp*FF_QP2LAMBDA;
310
 
    out_size = avcodec_encode_video(p->avctx_enc, p->outbuf, p->outbuf_size, p->frame);
311
 
    p->frame_dec = p->avctx_enc->coded_frame;
312
 
 
313
 
    for(i=0; i<3; i++){
314
 
        int is_chroma= !!i;
315
 
        int w= width >>is_chroma;
316
 
        int h= height>>is_chroma;
317
 
        int fils= p->frame_dec->linesize[i];
318
 
        int srcs= src_stride[i];
319
 
 
320
 
        for(y=0; y<h; y++){
321
 
            if((y ^ p->parity) & 1){
322
 
                for(x=0; x<w; x++){
323
 
                    if((x-2)+(y-1)*w>=0 && (x+2)+(y+1)*w<w*h){ //FIXME either alloc larger images or optimize this
324
 
                        uint8_t *filp= &p->frame_dec->data[i][x + y*fils];
325
 
                        uint8_t *srcp= &src[i][x + y*srcs];
326
 
                        int diff0= filp[-fils] - srcp[-srcs];
327
 
                        int diff1= filp[+fils] - srcp[+srcs];
328
 
                        int spatial_score= ABS(srcp[-srcs-1] - srcp[+srcs-1])
329
 
                                          +ABS(srcp[-srcs  ] - srcp[+srcs  ])
330
 
                                          +ABS(srcp[-srcs+1] - srcp[+srcs+1]) - 1;
331
 
                        int temp= filp[0];
332
 
 
333
 
#define CHECK(j)\
334
 
    {   int score= ABS(srcp[-srcs-1+j] - srcp[+srcs-1-j])\
335
 
                 + ABS(srcp[-srcs  +j] - srcp[+srcs  -j])\
336
 
                 + ABS(srcp[-srcs+1+j] - srcp[+srcs+1-j]);\
337
 
        if(score < spatial_score){\
338
 
            spatial_score= score;\
339
 
            diff0= filp[-fils+j] - srcp[-srcs+j];\
340
 
            diff1= filp[+fils-j] - srcp[+srcs-j];
341
 
 
342
 
                        CHECK(-1) CHECK(-2) }} }}
343
 
                        CHECK( 1) CHECK( 2) }} }}
344
 
#if 0
345
 
                        if((diff0 ^ diff1) > 0){
346
 
                            int mindiff= ABS(diff0) > ABS(diff1) ? diff1 : diff0;
347
 
                            temp-= mindiff;
348
 
                        }
349
 
#elif 1
350
 
                        if(diff0 + diff1 > 0)
351
 
                            temp-= (diff0 + diff1 - ABS( ABS(diff0) - ABS(diff1) )/2)/2;
352
 
                        else
353
 
                            temp-= (diff0 + diff1 + ABS( ABS(diff0) - ABS(diff1) )/2)/2;
354
 
#else
355
 
                        temp-= (diff0 + diff1)/2;
356
 
#endif
357
 
#if 1
358
 
                        filp[0]=
359
 
                        dst[i][x + y*dst_stride[i]]= temp > 255U ? ~(temp>>31) : temp;
360
 
#else
361
 
                        dst[i][x + y*dst_stride[i]]= filp[0];
362
 
                        filp[0]= temp > 255U ? ~(temp>>31) : temp;
363
 
#endif
364
 
                    }else
365
 
                        dst[i][x + y*dst_stride[i]]= p->frame_dec->data[i][x + y*fils];
366
 
                }
367
 
            }
368
 
        }
369
 
        for(y=0; y<h; y++){
370
 
            if(!((y ^ p->parity) & 1)){
371
 
                for(x=0; x<w; x++){
372
 
#if 1
373
 
                    p->frame_dec->data[i][x + y*fils]=
374
 
                    dst[i][x + y*dst_stride[i]]= src[i][x + y*srcs];
375
 
#else
376
 
                    dst[i][x + y*dst_stride[i]]= p->frame_dec->data[i][x + y*fils];
377
 
                    p->frame_dec->data[i][x + y*fils]= src[i][x + y*srcs];
378
 
#endif
379
 
                }
380
 
            }
381
 
        }
382
 
    }
383
 
    p->parity ^= 1;
384
 
 
385
 
}
386
 
#ifdef titititititi_II
387
 
static int config(struct vf_instance_s* vf,
388
 
        int width, int height, int d_width, int d_height,
389
 
        unsigned int flags, unsigned int outfmt){
390
 
        int i;
391
 
        AVCodec *enc= avcodec_find_encoder(CODEC_ID_SNOW);
392
 
 
393
 
        for(i=0; i<3; i++){
394
 
            AVCodecContext *avctx_enc;
395
 
#if 0
396
 
            int is_chroma= !!i;
397
 
            int w= ((width  + 31) & (~31))>>is_chroma;
398
 
            int h= ((height + 31) & (~31))>>is_chroma;
399
 
 
400
 
            vf->priv->temp_stride[i]= w;
401
 
            vf->priv->temp[i]= malloc(vf->priv->temp_stride[i]*h*sizeof(int16_t));
402
 
            vf->priv->src [i]= malloc(vf->priv->temp_stride[i]*h*sizeof(uint8_t));
403
 
#endif
404
 
            avctx_enc=
405
 
            vf->priv->avctx_enc= avcodec_alloc_context();
406
 
            avctx_enc->width = width;
407
 
            avctx_enc->height = height;
408
 
            avctx_enc->time_base= (AVRational){1,25};  // meaningless
409
 
            avctx_enc->gop_size = 300;
410
 
            avctx_enc->max_b_frames= 0;
411
 
            avctx_enc->pix_fmt = PIX_FMT_YUV420P;
412
 
            avctx_enc->flags = CODEC_FLAG_QSCALE | CODEC_FLAG_LOW_DELAY;
413
 
            avctx_enc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
414
 
            avctx_enc->global_quality= 1;
415
 
            avctx_enc->flags2= CODEC_FLAG2_MEMC_ONLY;
416
 
            avctx_enc->me_cmp=
417
 
            avctx_enc->me_sub_cmp= FF_CMP_SAD; //SSE;
418
 
            avctx_enc->mb_cmp= FF_CMP_SSE;
419
 
 
420
 
            switch(vf->priv->mode){
421
 
            case 3:
422
 
                avctx_enc->refs= 3;
423
 
            case 2:
424
 
                avctx_enc->me_method= ME_ITER;
425
 
            case 1:
426
 
                avctx_enc->flags |= CODEC_FLAG_4MV;
427
 
                avctx_enc->dia_size=2;
428
 
//                avctx_enc->mb_decision = MB_DECISSION_RD;
429
 
            case 0:
430
 
                avctx_enc->flags |= CODEC_FLAG_QPEL;
431
 
            }
432
 
 
433
 
            avcodec_open(avctx_enc, enc);
434
 
 
435
 
        }
436
 
        vf->priv->frame= avcodec_alloc_frame();
437
 
 
438
 
        vf->priv->outbuf_size= width*height*10;
439
 
        vf->priv->outbuf= malloc(vf->priv->outbuf_size);
440
 
 
441
 
        return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
442
 
}
443
 
 
444
 
static void get_image(struct vf_instance_s* vf, mp_image_t *mpi){
445
 
    if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
446
 
return; //caused problems, dunno why
447
 
    // ok, we can do pp in-place (or pp disabled):
448
 
    vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
449
 
        mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height);
450
 
    mpi->planes[0]=vf->dmpi->planes[0];
451
 
    mpi->stride[0]=vf->dmpi->stride[0];
452
 
    mpi->width=vf->dmpi->width;
453
 
    if(mpi->flags&MP_IMGFLAG_PLANAR){
454
 
        mpi->planes[1]=vf->dmpi->planes[1];
455
 
        mpi->planes[2]=vf->dmpi->planes[2];
456
 
        mpi->stride[1]=vf->dmpi->stride[1];
457
 
        mpi->stride[2]=vf->dmpi->stride[2];
458
 
    }
459
 
    mpi->flags|=MP_IMGFLAG_DIRECT;
460
 
}
461
 
 
462
 
static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){
463
 
    mp_image_t *dmpi;
464
 
 
465
 
    if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
466
 
        // no DR, so get a new image! hope we'll get DR buffer:
467
 
        dmpi=vf_get_image(vf->next,mpi->imgfmt,
468
 
            MP_IMGTYPE_TEMP,
469
 
            MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
470
 
            mpi->width,mpi->height);
471
 
        vf_clone_mpi_attributes(dmpi, mpi);
472
 
    }else{
473
 
        dmpi=vf->dmpi;
474
 
    }
475
 
 
476
 
    filter(vf->priv, dmpi->planes, mpi->planes, dmpi->stride, mpi->stride, mpi->w, mpi->h);
477
 
 
478
 
    return vf_next_put_image(vf,dmpi, pts);
479
 
}
480
 
 
481
 
static void uninit(struct vf_instance_s* vf){
482
 
    if(!vf->priv) return;
483
 
 
484
 
#if 0
485
 
    for(i=0; i<3; i++){
486
 
        if(vf->priv->temp[i]) free(vf->priv->temp[i]);
487
 
        vf->priv->temp[i]= NULL;
488
 
        if(vf->priv->src[i]) free(vf->priv->src[i]);
489
 
        vf->priv->src[i]= NULL;
490
 
    }
491
 
#endif
492
 
    av_freep(&vf->priv->avctx_enc);
493
 
 
494
 
    free(vf->priv->outbuf);
495
 
    free(vf->priv);
496
 
    vf->priv=NULL;
497
 
}
498
 
 
499
 
#endif
500
 
//EOF