~ubuntu-branches/ubuntu/saucy/gst-libav1.0/saucy-proposed

« back to all changes in this revision

Viewing changes to gst-libs/ext/libav/libpostproc/postprocess.c

  • Committer: Package Import Robot
  • Author(s): Sebastian Dröge
  • Date: 2013-07-30 09:00:15 UTC
  • mfrom: (1.1.16) (7.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20130730090015-sc1ou2yssu7q5w4e
Tags: 1.1.3-1
* New upstream development snapshot:
  + debian/control:
    - Build depend on GStreamer and gst-plugins-base >= 1.1.3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2001-2003 Michael Niedermayer (michaelni@gmx.at)
3
 
 *
4
 
 * AltiVec optimizations (C) 2004 Romain Dolbeau <romain@dolbeau.org>
5
 
 *
6
 
 * This file is part of Libav.
7
 
 *
8
 
 * Libav is free software; you can redistribute it and/or modify
9
 
 * it under the terms of the GNU General Public License as published by
10
 
 * the Free Software Foundation; either version 2 of the License, or
11
 
 * (at your option) any later version.
12
 
 *
13
 
 * Libav is distributed in the hope that it will be useful,
14
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
 * GNU General Public License for more details.
17
 
 *
18
 
 * You should have received a copy of the GNU General Public License
19
 
 * along with Libav; if not, write to the Free Software
20
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 
 */
22
 
 
23
 
/**
24
 
 * @file
25
 
 * postprocessing.
26
 
 */
27
 
 
28
 
/*
29
 
                        C       MMX     MMX2    3DNow   AltiVec
30
 
isVertDC                Ec      Ec                      Ec
31
 
isVertMinMaxOk          Ec      Ec                      Ec
32
 
doVertLowPass           E               e       e       Ec
33
 
doVertDefFilter         Ec      Ec      e       e       Ec
34
 
isHorizDC               Ec      Ec                      Ec
35
 
isHorizMinMaxOk         a       E                       Ec
36
 
doHorizLowPass          E               e       e       Ec
37
 
doHorizDefFilter        Ec      Ec      e       e       Ec
38
 
do_a_deblock            Ec      E       Ec      E
39
 
deRing                  E               e       e*      Ecp
40
 
Vertical RKAlgo1        E               a       a
41
 
Horizontal RKAlgo1                      a       a
42
 
Vertical X1#            a               E       E
43
 
Horizontal X1#          a               E       E
44
 
LinIpolDeinterlace      e               E       E*
45
 
CubicIpolDeinterlace    a               e       e*
46
 
LinBlendDeinterlace     e               E       E*
47
 
MedianDeinterlace#      E       Ec      Ec
48
 
TempDeNoiser#           E               e       e       Ec
49
 
 
50
 
* I do not have a 3DNow! CPU -> it is untested, but no one said it does not work so it seems to work
51
 
# more or less selfinvented filters so the exactness is not too meaningful
52
 
E = Exact implementation
53
 
e = almost exact implementation (slightly different rounding,...)
54
 
a = alternative / approximate impl
55
 
c = checked against the other implementations (-vo md5)
56
 
p = partially optimized, still some work to do
57
 
*/
58
 
 
59
 
/*
60
 
TODO:
61
 
reduce the time wasted on the mem transfer
62
 
unroll stuff if instructions depend too much on the prior one
63
 
move YScale thing to the end instead of fixing QP
64
 
write a faster and higher quality deblocking filter :)
65
 
make the mainloop more flexible (variable number of blocks at once
66
 
        (the if/else stuff per block is slowing things down)
67
 
compare the quality & speed of all filters
68
 
split this huge file
69
 
optimize c versions
70
 
try to unroll inner for(x=0 ... loop to avoid these damn if(x ... checks
71
 
...
72
 
*/
73
 
 
74
 
//Changelog: use git log
75
 
 
76
 
#include "config.h"
77
 
#include "libavutil/avutil.h"
78
 
#include <inttypes.h>
79
 
#include <stdio.h>
80
 
#include <stdlib.h>
81
 
#include <string.h>
82
 
//#undef HAVE_MMX2
83
 
//#define HAVE_AMD3DNOW
84
 
//#undef HAVE_MMX
85
 
//#undef ARCH_X86
86
 
//#define DEBUG_BRIGHTNESS
87
 
#include "postprocess.h"
88
 
#include "postprocess_internal.h"
89
 
#include "libavutil/avstring.h"
90
 
 
91
 
unsigned postproc_version(void)
92
 
{
93
 
    return LIBPOSTPROC_VERSION_INT;
94
 
}
95
 
 
96
 
const char *postproc_configuration(void)
97
 
{
98
 
    return LIBAV_CONFIGURATION;
99
 
}
100
 
 
101
 
const char *postproc_license(void)
102
 
{
103
 
#define LICENSE_PREFIX "libpostproc license: "
104
 
    return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1;
105
 
}
106
 
 
107
 
#if HAVE_ALTIVEC_H
108
 
#include <altivec.h>
109
 
#endif
110
 
 
111
 
#define GET_MODE_BUFFER_SIZE 500
112
 
#define OPTIONS_ARRAY_SIZE 10
113
 
#define BLOCK_SIZE 8
114
 
#define TEMP_STRIDE 8
115
 
//#define NUM_BLOCKS_AT_ONCE 16 //not used yet
116
 
 
117
 
#if ARCH_X86
118
 
DECLARE_ASM_CONST(8, uint64_t, w05)= 0x0005000500050005LL;
119
 
DECLARE_ASM_CONST(8, uint64_t, w04)= 0x0004000400040004LL;
120
 
DECLARE_ASM_CONST(8, uint64_t, w20)= 0x0020002000200020LL;
121
 
DECLARE_ASM_CONST(8, uint64_t, b00)= 0x0000000000000000LL;
122
 
DECLARE_ASM_CONST(8, uint64_t, b01)= 0x0101010101010101LL;
123
 
DECLARE_ASM_CONST(8, uint64_t, b02)= 0x0202020202020202LL;
124
 
DECLARE_ASM_CONST(8, uint64_t, b08)= 0x0808080808080808LL;
125
 
DECLARE_ASM_CONST(8, uint64_t, b80)= 0x8080808080808080LL;
126
 
#endif
127
 
 
128
 
DECLARE_ASM_CONST(8, int, deringThreshold)= 20;
129
 
 
130
 
 
131
 
static struct PPFilter filters[]=
132
 
{
133
 
    {"hb", "hdeblock",              1, 1, 3, H_DEBLOCK},
134
 
    {"vb", "vdeblock",              1, 2, 4, V_DEBLOCK},
135
 
/*  {"hr", "rkhdeblock",            1, 1, 3, H_RK1_FILTER},
136
 
    {"vr", "rkvdeblock",            1, 2, 4, V_RK1_FILTER},*/
137
 
    {"h1", "x1hdeblock",            1, 1, 3, H_X1_FILTER},
138
 
    {"v1", "x1vdeblock",            1, 2, 4, V_X1_FILTER},
139
 
    {"ha", "ahdeblock",             1, 1, 3, H_A_DEBLOCK},
140
 
    {"va", "avdeblock",             1, 2, 4, V_A_DEBLOCK},
141
 
    {"dr", "dering",                1, 5, 6, DERING},
142
 
    {"al", "autolevels",            0, 1, 2, LEVEL_FIX},
143
 
    {"lb", "linblenddeint",         1, 1, 4, LINEAR_BLEND_DEINT_FILTER},
144
 
    {"li", "linipoldeint",          1, 1, 4, LINEAR_IPOL_DEINT_FILTER},
145
 
    {"ci", "cubicipoldeint",        1, 1, 4, CUBIC_IPOL_DEINT_FILTER},
146
 
    {"md", "mediandeint",           1, 1, 4, MEDIAN_DEINT_FILTER},
147
 
    {"fd", "ffmpegdeint",           1, 1, 4, FFMPEG_DEINT_FILTER},
148
 
    {"l5", "lowpass5",              1, 1, 4, LOWPASS5_DEINT_FILTER},
149
 
    {"tn", "tmpnoise",              1, 7, 8, TEMP_NOISE_FILTER},
150
 
    {"fq", "forcequant",            1, 0, 0, FORCE_QUANT},
151
 
    {NULL, NULL,0,0,0,0} //End Marker
152
 
};
153
 
 
154
 
static const char *replaceTable[]=
155
 
{
156
 
    "default",      "hb:a,vb:a,dr:a",
157
 
    "de",           "hb:a,vb:a,dr:a",
158
 
    "fast",         "h1:a,v1:a,dr:a",
159
 
    "fa",           "h1:a,v1:a,dr:a",
160
 
    "ac",           "ha:a:128:7,va:a,dr:a",
161
 
    NULL //End Marker
162
 
};
163
 
 
164
 
 
165
 
#if ARCH_X86
166
 
static inline void prefetchnta(void *p)
167
 
{
168
 
    __asm__ volatile(   "prefetchnta (%0)\n\t"
169
 
        : : "r" (p)
170
 
    );
171
 
}
172
 
 
173
 
static inline void prefetcht0(void *p)
174
 
{
175
 
    __asm__ volatile(   "prefetcht0 (%0)\n\t"
176
 
        : : "r" (p)
177
 
    );
178
 
}
179
 
 
180
 
static inline void prefetcht1(void *p)
181
 
{
182
 
    __asm__ volatile(   "prefetcht1 (%0)\n\t"
183
 
        : : "r" (p)
184
 
    );
185
 
}
186
 
 
187
 
static inline void prefetcht2(void *p)
188
 
{
189
 
    __asm__ volatile(   "prefetcht2 (%0)\n\t"
190
 
        : : "r" (p)
191
 
    );
192
 
}
193
 
#endif
194
 
 
195
 
/* The horizontal functions exist only in C because the MMX
196
 
 * code is faster with vertical filters and transposing. */
197
 
 
198
 
/**
199
 
 * Check if the given 8x8 Block is mostly "flat"
200
 
 */
201
 
static inline int isHorizDC_C(uint8_t src[], int stride, PPContext *c)
202
 
{
203
 
    int numEq= 0;
204
 
    int y;
205
 
    const int dcOffset= ((c->nonBQP*c->ppMode.baseDcDiff)>>8) + 1;
206
 
    const int dcThreshold= dcOffset*2 + 1;
207
 
 
208
 
    for(y=0; y<BLOCK_SIZE; y++){
209
 
        if(((unsigned)(src[0] - src[1] + dcOffset)) < dcThreshold) numEq++;
210
 
        if(((unsigned)(src[1] - src[2] + dcOffset)) < dcThreshold) numEq++;
211
 
        if(((unsigned)(src[2] - src[3] + dcOffset)) < dcThreshold) numEq++;
212
 
        if(((unsigned)(src[3] - src[4] + dcOffset)) < dcThreshold) numEq++;
213
 
        if(((unsigned)(src[4] - src[5] + dcOffset)) < dcThreshold) numEq++;
214
 
        if(((unsigned)(src[5] - src[6] + dcOffset)) < dcThreshold) numEq++;
215
 
        if(((unsigned)(src[6] - src[7] + dcOffset)) < dcThreshold) numEq++;
216
 
        src+= stride;
217
 
    }
218
 
    return numEq > c->ppMode.flatnessThreshold;
219
 
}
220
 
 
221
 
/**
222
 
 * Check if the middle 8x8 Block in the given 8x16 block is flat
223
 
 */
224
 
static inline int isVertDC_C(uint8_t src[], int stride, PPContext *c)
225
 
{
226
 
    int numEq= 0;
227
 
    int y;
228
 
    const int dcOffset= ((c->nonBQP*c->ppMode.baseDcDiff)>>8) + 1;
229
 
    const int dcThreshold= dcOffset*2 + 1;
230
 
 
231
 
    src+= stride*4; // src points to begin of the 8x8 Block
232
 
    for(y=0; y<BLOCK_SIZE-1; y++){
233
 
        if(((unsigned)(src[0] - src[0+stride] + dcOffset)) < dcThreshold) numEq++;
234
 
        if(((unsigned)(src[1] - src[1+stride] + dcOffset)) < dcThreshold) numEq++;
235
 
        if(((unsigned)(src[2] - src[2+stride] + dcOffset)) < dcThreshold) numEq++;
236
 
        if(((unsigned)(src[3] - src[3+stride] + dcOffset)) < dcThreshold) numEq++;
237
 
        if(((unsigned)(src[4] - src[4+stride] + dcOffset)) < dcThreshold) numEq++;
238
 
        if(((unsigned)(src[5] - src[5+stride] + dcOffset)) < dcThreshold) numEq++;
239
 
        if(((unsigned)(src[6] - src[6+stride] + dcOffset)) < dcThreshold) numEq++;
240
 
        if(((unsigned)(src[7] - src[7+stride] + dcOffset)) < dcThreshold) numEq++;
241
 
        src+= stride;
242
 
    }
243
 
    return numEq > c->ppMode.flatnessThreshold;
244
 
}
245
 
 
246
 
static inline int isHorizMinMaxOk_C(uint8_t src[], int stride, int QP)
247
 
{
248
 
    int i;
249
 
    for(i=0; i<2; i++){
250
 
        if((unsigned)(src[0] - src[5] + 2*QP) > 4*QP) return 0;
251
 
        src += stride;
252
 
        if((unsigned)(src[2] - src[7] + 2*QP) > 4*QP) return 0;
253
 
        src += stride;
254
 
        if((unsigned)(src[4] - src[1] + 2*QP) > 4*QP) return 0;
255
 
        src += stride;
256
 
        if((unsigned)(src[6] - src[3] + 2*QP) > 4*QP) return 0;
257
 
        src += stride;
258
 
    }
259
 
    return 1;
260
 
}
261
 
 
262
 
static inline int isVertMinMaxOk_C(uint8_t src[], int stride, int QP)
263
 
{
264
 
    int x;
265
 
    src+= stride*4;
266
 
    for(x=0; x<BLOCK_SIZE; x+=4){
267
 
        if((unsigned)(src[  x + 0*stride] - src[  x + 5*stride] + 2*QP) > 4*QP) return 0;
268
 
        if((unsigned)(src[1+x + 2*stride] - src[1+x + 7*stride] + 2*QP) > 4*QP) return 0;
269
 
        if((unsigned)(src[2+x + 4*stride] - src[2+x + 1*stride] + 2*QP) > 4*QP) return 0;
270
 
        if((unsigned)(src[3+x + 6*stride] - src[3+x + 3*stride] + 2*QP) > 4*QP) return 0;
271
 
    }
272
 
    return 1;
273
 
}
274
 
 
275
 
static inline int horizClassify_C(uint8_t src[], int stride, PPContext *c)
276
 
{
277
 
    if( isHorizDC_C(src, stride, c) ){
278
 
        if( isHorizMinMaxOk_C(src, stride, c->QP) )
279
 
            return 1;
280
 
        else
281
 
            return 0;
282
 
    }else{
283
 
        return 2;
284
 
    }
285
 
}
286
 
 
287
 
static inline int vertClassify_C(uint8_t src[], int stride, PPContext *c)
288
 
{
289
 
    if( isVertDC_C(src, stride, c) ){
290
 
        if( isVertMinMaxOk_C(src, stride, c->QP) )
291
 
            return 1;
292
 
        else
293
 
            return 0;
294
 
    }else{
295
 
        return 2;
296
 
    }
297
 
}
298
 
 
299
 
static inline void doHorizDefFilter_C(uint8_t dst[], int stride, PPContext *c)
300
 
{
301
 
    int y;
302
 
    for(y=0; y<BLOCK_SIZE; y++){
303
 
        const int middleEnergy= 5*(dst[4] - dst[3]) + 2*(dst[2] - dst[5]);
304
 
 
305
 
        if(FFABS(middleEnergy) < 8*c->QP){
306
 
            const int q=(dst[3] - dst[4])/2;
307
 
            const int leftEnergy=  5*(dst[2] - dst[1]) + 2*(dst[0] - dst[3]);
308
 
            const int rightEnergy= 5*(dst[6] - dst[5]) + 2*(dst[4] - dst[7]);
309
 
 
310
 
            int d= FFABS(middleEnergy) - FFMIN( FFABS(leftEnergy), FFABS(rightEnergy) );
311
 
            d= FFMAX(d, 0);
312
 
 
313
 
            d= (5*d + 32) >> 6;
314
 
            d*= FFSIGN(-middleEnergy);
315
 
 
316
 
            if(q>0)
317
 
            {
318
 
                d= d<0 ? 0 : d;
319
 
                d= d>q ? q : d;
320
 
            }
321
 
            else
322
 
            {
323
 
                d= d>0 ? 0 : d;
324
 
                d= d<q ? q : d;
325
 
            }
326
 
 
327
 
            dst[3]-= d;
328
 
            dst[4]+= d;
329
 
        }
330
 
        dst+= stride;
331
 
    }
332
 
}
333
 
 
334
 
/**
335
 
 * Do a horizontal low pass filter on the 10x8 block (dst points to middle 8x8 Block)
336
 
 * using the 9-Tap Filter (1,1,2,2,4,2,2,1,1)/16 (C version)
337
 
 */
338
 
static inline void doHorizLowPass_C(uint8_t dst[], int stride, PPContext *c)
339
 
{
340
 
    int y;
341
 
    for(y=0; y<BLOCK_SIZE; y++){
342
 
        const int first= FFABS(dst[-1] - dst[0]) < c->QP ? dst[-1] : dst[0];
343
 
        const int last= FFABS(dst[8] - dst[7]) < c->QP ? dst[8] : dst[7];
344
 
 
345
 
        int sums[10];
346
 
        sums[0] = 4*first + dst[0] + dst[1] + dst[2] + 4;
347
 
        sums[1] = sums[0] - first  + dst[3];
348
 
        sums[2] = sums[1] - first  + dst[4];
349
 
        sums[3] = sums[2] - first  + dst[5];
350
 
        sums[4] = sums[3] - first  + dst[6];
351
 
        sums[5] = sums[4] - dst[0] + dst[7];
352
 
        sums[6] = sums[5] - dst[1] + last;
353
 
        sums[7] = sums[6] - dst[2] + last;
354
 
        sums[8] = sums[7] - dst[3] + last;
355
 
        sums[9] = sums[8] - dst[4] + last;
356
 
 
357
 
        dst[0]= (sums[0] + sums[2] + 2*dst[0])>>4;
358
 
        dst[1]= (sums[1] + sums[3] + 2*dst[1])>>4;
359
 
        dst[2]= (sums[2] + sums[4] + 2*dst[2])>>4;
360
 
        dst[3]= (sums[3] + sums[5] + 2*dst[3])>>4;
361
 
        dst[4]= (sums[4] + sums[6] + 2*dst[4])>>4;
362
 
        dst[5]= (sums[5] + sums[7] + 2*dst[5])>>4;
363
 
        dst[6]= (sums[6] + sums[8] + 2*dst[6])>>4;
364
 
        dst[7]= (sums[7] + sums[9] + 2*dst[7])>>4;
365
 
 
366
 
        dst+= stride;
367
 
    }
368
 
}
369
 
 
370
 
/**
371
 
 * Experimental Filter 1 (Horizontal)
372
 
 * will not damage linear gradients
373
 
 * Flat blocks should look like they were passed through the (1,1,2,2,4,2,2,1,1) 9-Tap filter
374
 
 * can only smooth blocks at the expected locations (it cannot smooth them if they did move)
375
 
 * MMX2 version does correct clipping C version does not
376
 
 * not identical with the vertical one
377
 
 */
378
 
static inline void horizX1Filter(uint8_t *src, int stride, int QP)
379
 
{
380
 
    int y;
381
 
    static uint64_t *lut= NULL;
382
 
    if(lut==NULL)
383
 
    {
384
 
        int i;
385
 
        lut = av_malloc(256*8);
386
 
        for(i=0; i<256; i++)
387
 
        {
388
 
            int v= i < 128 ? 2*i : 2*(i-256);
389
 
/*
390
 
//Simulate 112242211 9-Tap filter
391
 
            uint64_t a= (v/16)  & 0xFF;
392
 
            uint64_t b= (v/8)   & 0xFF;
393
 
            uint64_t c= (v/4)   & 0xFF;
394
 
            uint64_t d= (3*v/8) & 0xFF;
395
 
*/
396
 
//Simulate piecewise linear interpolation
397
 
            uint64_t a= (v/16)   & 0xFF;
398
 
            uint64_t b= (v*3/16) & 0xFF;
399
 
            uint64_t c= (v*5/16) & 0xFF;
400
 
            uint64_t d= (7*v/16) & 0xFF;
401
 
            uint64_t A= (0x100 - a)&0xFF;
402
 
            uint64_t B= (0x100 - b)&0xFF;
403
 
            uint64_t C= (0x100 - c)&0xFF;
404
 
            uint64_t D= (0x100 - c)&0xFF;
405
 
 
406
 
            lut[i]   = (a<<56) | (b<<48) | (c<<40) | (d<<32) |
407
 
                       (D<<24) | (C<<16) | (B<<8)  | (A);
408
 
            //lut[i] = (v<<32) | (v<<24);
409
 
        }
410
 
    }
411
 
 
412
 
    for(y=0; y<BLOCK_SIZE; y++){
413
 
        int a= src[1] - src[2];
414
 
        int b= src[3] - src[4];
415
 
        int c= src[5] - src[6];
416
 
 
417
 
        int d= FFMAX(FFABS(b) - (FFABS(a) + FFABS(c))/2, 0);
418
 
 
419
 
        if(d < QP){
420
 
            int v = d * FFSIGN(-b);
421
 
 
422
 
            src[1] +=v/8;
423
 
            src[2] +=v/4;
424
 
            src[3] +=3*v/8;
425
 
            src[4] -=3*v/8;
426
 
            src[5] -=v/4;
427
 
            src[6] -=v/8;
428
 
        }
429
 
        src+=stride;
430
 
    }
431
 
}
432
 
 
433
 
/**
434
 
 * accurate deblock filter
435
 
 */
436
 
static av_always_inline void do_a_deblock_C(uint8_t *src, int step, int stride, PPContext *c){
437
 
    int y;
438
 
    const int QP= c->QP;
439
 
    const int dcOffset= ((c->nonBQP*c->ppMode.baseDcDiff)>>8) + 1;
440
 
    const int dcThreshold= dcOffset*2 + 1;
441
 
//START_TIMER
442
 
    src+= step*4; // src points to begin of the 8x8 Block
443
 
    for(y=0; y<8; y++){
444
 
        int numEq= 0;
445
 
 
446
 
        if(((unsigned)(src[-1*step] - src[0*step] + dcOffset)) < dcThreshold) numEq++;
447
 
        if(((unsigned)(src[ 0*step] - src[1*step] + dcOffset)) < dcThreshold) numEq++;
448
 
        if(((unsigned)(src[ 1*step] - src[2*step] + dcOffset)) < dcThreshold) numEq++;
449
 
        if(((unsigned)(src[ 2*step] - src[3*step] + dcOffset)) < dcThreshold) numEq++;
450
 
        if(((unsigned)(src[ 3*step] - src[4*step] + dcOffset)) < dcThreshold) numEq++;
451
 
        if(((unsigned)(src[ 4*step] - src[5*step] + dcOffset)) < dcThreshold) numEq++;
452
 
        if(((unsigned)(src[ 5*step] - src[6*step] + dcOffset)) < dcThreshold) numEq++;
453
 
        if(((unsigned)(src[ 6*step] - src[7*step] + dcOffset)) < dcThreshold) numEq++;
454
 
        if(((unsigned)(src[ 7*step] - src[8*step] + dcOffset)) < dcThreshold) numEq++;
455
 
        if(numEq > c->ppMode.flatnessThreshold){
456
 
            int min, max, x;
457
 
 
458
 
            if(src[0] > src[step]){
459
 
                max= src[0];
460
 
                min= src[step];
461
 
            }else{
462
 
                max= src[step];
463
 
                min= src[0];
464
 
            }
465
 
            for(x=2; x<8; x+=2){
466
 
                if(src[x*step] > src[(x+1)*step]){
467
 
                        if(src[x    *step] > max) max= src[ x   *step];
468
 
                        if(src[(x+1)*step] < min) min= src[(x+1)*step];
469
 
                }else{
470
 
                        if(src[(x+1)*step] > max) max= src[(x+1)*step];
471
 
                        if(src[ x   *step] < min) min= src[ x   *step];
472
 
                }
473
 
            }
474
 
            if(max-min < 2*QP){
475
 
                const int first= FFABS(src[-1*step] - src[0]) < QP ? src[-1*step] : src[0];
476
 
                const int last= FFABS(src[8*step] - src[7*step]) < QP ? src[8*step] : src[7*step];
477
 
 
478
 
                int sums[10];
479
 
                sums[0] = 4*first + src[0*step] + src[1*step] + src[2*step] + 4;
480
 
                sums[1] = sums[0] - first       + src[3*step];
481
 
                sums[2] = sums[1] - first       + src[4*step];
482
 
                sums[3] = sums[2] - first       + src[5*step];
483
 
                sums[4] = sums[3] - first       + src[6*step];
484
 
                sums[5] = sums[4] - src[0*step] + src[7*step];
485
 
                sums[6] = sums[5] - src[1*step] + last;
486
 
                sums[7] = sums[6] - src[2*step] + last;
487
 
                sums[8] = sums[7] - src[3*step] + last;
488
 
                sums[9] = sums[8] - src[4*step] + last;
489
 
 
490
 
                src[0*step]= (sums[0] + sums[2] + 2*src[0*step])>>4;
491
 
                src[1*step]= (sums[1] + sums[3] + 2*src[1*step])>>4;
492
 
                src[2*step]= (sums[2] + sums[4] + 2*src[2*step])>>4;
493
 
                src[3*step]= (sums[3] + sums[5] + 2*src[3*step])>>4;
494
 
                src[4*step]= (sums[4] + sums[6] + 2*src[4*step])>>4;
495
 
                src[5*step]= (sums[5] + sums[7] + 2*src[5*step])>>4;
496
 
                src[6*step]= (sums[6] + sums[8] + 2*src[6*step])>>4;
497
 
                src[7*step]= (sums[7] + sums[9] + 2*src[7*step])>>4;
498
 
            }
499
 
        }else{
500
 
            const int middleEnergy= 5*(src[4*step] - src[3*step]) + 2*(src[2*step] - src[5*step]);
501
 
 
502
 
            if(FFABS(middleEnergy) < 8*QP){
503
 
                const int q=(src[3*step] - src[4*step])/2;
504
 
                const int leftEnergy=  5*(src[2*step] - src[1*step]) + 2*(src[0*step] - src[3*step]);
505
 
                const int rightEnergy= 5*(src[6*step] - src[5*step]) + 2*(src[4*step] - src[7*step]);
506
 
 
507
 
                int d= FFABS(middleEnergy) - FFMIN( FFABS(leftEnergy), FFABS(rightEnergy) );
508
 
                d= FFMAX(d, 0);
509
 
 
510
 
                d= (5*d + 32) >> 6;
511
 
                d*= FFSIGN(-middleEnergy);
512
 
 
513
 
                if(q>0){
514
 
                    d= d<0 ? 0 : d;
515
 
                    d= d>q ? q : d;
516
 
                }else{
517
 
                    d= d>0 ? 0 : d;
518
 
                    d= d<q ? q : d;
519
 
                }
520
 
 
521
 
                src[3*step]-= d;
522
 
                src[4*step]+= d;
523
 
            }
524
 
        }
525
 
 
526
 
        src += stride;
527
 
    }
528
 
/*if(step==16){
529
 
    STOP_TIMER("step16")
530
 
}else{
531
 
    STOP_TIMER("stepX")
532
 
}*/
533
 
}
534
 
 
535
 
//Note: we have C, MMX, MMX2, 3DNOW version there is no 3DNOW+MMX2 one
536
 
//Plain C versions
537
 
#if !(HAVE_MMX || HAVE_ALTIVEC) || CONFIG_RUNTIME_CPUDETECT
538
 
#define COMPILE_C
539
 
#endif
540
 
 
541
 
#if HAVE_ALTIVEC
542
 
#define COMPILE_ALTIVEC
543
 
#endif //HAVE_ALTIVEC
544
 
 
545
 
#if ARCH_X86
546
 
 
547
 
#if (HAVE_MMX && !HAVE_AMD3DNOW && !HAVE_MMX2) || CONFIG_RUNTIME_CPUDETECT
548
 
#define COMPILE_MMX
549
 
#endif
550
 
 
551
 
#if HAVE_MMX2 || CONFIG_RUNTIME_CPUDETECT
552
 
#define COMPILE_MMX2
553
 
#endif
554
 
 
555
 
#if (HAVE_AMD3DNOW && !HAVE_MMX2) || CONFIG_RUNTIME_CPUDETECT
556
 
#define COMPILE_3DNOW
557
 
#endif
558
 
#endif /* ARCH_X86 */
559
 
 
560
 
#undef HAVE_MMX
561
 
#define HAVE_MMX 0
562
 
#undef HAVE_MMX2
563
 
#define HAVE_MMX2 0
564
 
#undef HAVE_AMD3DNOW
565
 
#define HAVE_AMD3DNOW 0
566
 
#undef HAVE_ALTIVEC
567
 
#define HAVE_ALTIVEC 0
568
 
 
569
 
#ifdef COMPILE_C
570
 
#define RENAME(a) a ## _C
571
 
#include "postprocess_template.c"
572
 
#endif
573
 
 
574
 
#ifdef COMPILE_ALTIVEC
575
 
#undef RENAME
576
 
#undef HAVE_ALTIVEC
577
 
#define HAVE_ALTIVEC 1
578
 
#define RENAME(a) a ## _altivec
579
 
#include "postprocess_altivec_template.c"
580
 
#include "postprocess_template.c"
581
 
#endif
582
 
 
583
 
//MMX versions
584
 
#ifdef COMPILE_MMX
585
 
#undef RENAME
586
 
#undef HAVE_MMX
587
 
#define HAVE_MMX 1
588
 
#define RENAME(a) a ## _MMX
589
 
#include "postprocess_template.c"
590
 
#endif
591
 
 
592
 
//MMX2 versions
593
 
#ifdef COMPILE_MMX2
594
 
#undef RENAME
595
 
#undef HAVE_MMX
596
 
#undef HAVE_MMX2
597
 
#define HAVE_MMX 1
598
 
#define HAVE_MMX2 1
599
 
#define RENAME(a) a ## _MMX2
600
 
#include "postprocess_template.c"
601
 
#endif
602
 
 
603
 
//3DNOW versions
604
 
#ifdef COMPILE_3DNOW
605
 
#undef RENAME
606
 
#undef HAVE_MMX
607
 
#undef HAVE_MMX2
608
 
#undef HAVE_AMD3DNOW
609
 
#define HAVE_MMX 1
610
 
#define HAVE_MMX2 0
611
 
#define HAVE_AMD3DNOW 1
612
 
#define RENAME(a) a ## _3DNow
613
 
#include "postprocess_template.c"
614
 
#endif
615
 
 
616
 
// minor note: the HAVE_xyz is messed up after that line so do not use it.
617
 
 
618
 
static inline void postProcess(const uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height,
619
 
        const QP_STORE_T QPs[], int QPStride, int isColor, pp_mode *vm, pp_context *vc)
620
 
{
621
 
    PPContext *c= (PPContext *)vc;
622
 
    PPMode *ppMode= (PPMode *)vm;
623
 
    c->ppMode= *ppMode; //FIXME
624
 
 
625
 
    // Using ifs here as they are faster than function pointers although the
626
 
    // difference would not be measurable here but it is much better because
627
 
    // someone might exchange the CPU whithout restarting MPlayer ;)
628
 
#if CONFIG_RUNTIME_CPUDETECT
629
 
#if ARCH_X86
630
 
    // ordered per speed fastest first
631
 
    if(c->cpuCaps & PP_CPU_CAPS_MMX2)
632
 
        postProcess_MMX2(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
633
 
    else if(c->cpuCaps & PP_CPU_CAPS_3DNOW)
634
 
        postProcess_3DNow(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
635
 
    else if(c->cpuCaps & PP_CPU_CAPS_MMX)
636
 
        postProcess_MMX(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
637
 
    else
638
 
        postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
639
 
#else
640
 
#if HAVE_ALTIVEC
641
 
    if(c->cpuCaps & PP_CPU_CAPS_ALTIVEC)
642
 
            postProcess_altivec(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
643
 
    else
644
 
#endif
645
 
            postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
646
 
#endif
647
 
#else /* CONFIG_RUNTIME_CPUDETECT */
648
 
#if   HAVE_MMX2
649
 
            postProcess_MMX2(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
650
 
#elif HAVE_AMD3DNOW
651
 
            postProcess_3DNow(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
652
 
#elif HAVE_MMX
653
 
            postProcess_MMX(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
654
 
#elif HAVE_ALTIVEC
655
 
            postProcess_altivec(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
656
 
#else
657
 
            postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
658
 
#endif
659
 
#endif /* !CONFIG_RUNTIME_CPUDETECT */
660
 
}
661
 
 
662
 
//static void postProcess(uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height,
663
 
//        QP_STORE_T QPs[], int QPStride, int isColor, struct PPMode *ppMode);
664
 
 
665
 
/* -pp Command line Help
666
 
*/
667
 
const char pp_help[] =
668
 
"Available postprocessing filters:\n"
669
 
"Filters                        Options\n"
670
 
"short  long name       short   long option     Description\n"
671
 
"*      *               a       autoq           CPU power dependent enabler\n"
672
 
"                       c       chrom           chrominance filtering enabled\n"
673
 
"                       y       nochrom         chrominance filtering disabled\n"
674
 
"                       n       noluma          luma filtering disabled\n"
675
 
"hb     hdeblock        (2 threshold)           horizontal deblocking filter\n"
676
 
"       1. difference factor: default=32, higher -> more deblocking\n"
677
 
"       2. flatness threshold: default=39, lower -> more deblocking\n"
678
 
"                       the h & v deblocking filters share these\n"
679
 
"                       so you can't set different thresholds for h / v\n"
680
 
"vb     vdeblock        (2 threshold)           vertical deblocking filter\n"
681
 
"ha     hadeblock       (2 threshold)           horizontal deblocking filter\n"
682
 
"va     vadeblock       (2 threshold)           vertical deblocking filter\n"
683
 
"h1     x1hdeblock                              experimental h deblock filter 1\n"
684
 
"v1     x1vdeblock                              experimental v deblock filter 1\n"
685
 
"dr     dering                                  deringing filter\n"
686
 
"al     autolevels                              automatic brightness / contrast\n"
687
 
"                       f        fullyrange     stretch luminance to (0..255)\n"
688
 
"lb     linblenddeint                           linear blend deinterlacer\n"
689
 
"li     linipoldeint                            linear interpolating deinterlace\n"
690
 
"ci     cubicipoldeint                          cubic interpolating deinterlacer\n"
691
 
"md     mediandeint                             median deinterlacer\n"
692
 
"fd     ffmpegdeint                             ffmpeg deinterlacer\n"
693
 
"l5     lowpass5                                FIR lowpass deinterlacer\n"
694
 
"de     default                                 hb:a,vb:a,dr:a\n"
695
 
"fa     fast                                    h1:a,v1:a,dr:a\n"
696
 
"ac                                             ha:a:128:7,va:a,dr:a\n"
697
 
"tn     tmpnoise        (3 threshold)           temporal noise reducer\n"
698
 
"                     1. <= 2. <= 3.            larger -> stronger filtering\n"
699
 
"fq     forceQuant      <quantizer>             force quantizer\n"
700
 
"Usage:\n"
701
 
"<filterName>[:<option>[:<option>...]][[,|/][-]<filterName>[:<option>...]]...\n"
702
 
"long form example:\n"
703
 
"vdeblock:autoq/hdeblock:autoq/linblenddeint    default,-vdeblock\n"
704
 
"short form example:\n"
705
 
"vb:a/hb:a/lb                                   de,-vb\n"
706
 
"more examples:\n"
707
 
"tn:64:128:256\n"
708
 
"\n"
709
 
;
710
 
 
711
 
pp_mode *pp_get_mode_by_name_and_quality(const char *name, int quality)
712
 
{
713
 
    char temp[GET_MODE_BUFFER_SIZE];
714
 
    char *p= temp;
715
 
    static const char filterDelimiters[] = ",/";
716
 
    static const char optionDelimiters[] = ":";
717
 
    struct PPMode *ppMode;
718
 
    char *filterToken;
719
 
 
720
 
    ppMode= av_malloc(sizeof(PPMode));
721
 
 
722
 
    ppMode->lumMode= 0;
723
 
    ppMode->chromMode= 0;
724
 
    ppMode->maxTmpNoise[0]= 700;
725
 
    ppMode->maxTmpNoise[1]= 1500;
726
 
    ppMode->maxTmpNoise[2]= 3000;
727
 
    ppMode->maxAllowedY= 234;
728
 
    ppMode->minAllowedY= 16;
729
 
    ppMode->baseDcDiff= 256/8;
730
 
    ppMode->flatnessThreshold= 56-16-1;
731
 
    ppMode->maxClippedThreshold= 0.01;
732
 
    ppMode->error=0;
733
 
 
734
 
    memset(temp, 0, GET_MODE_BUFFER_SIZE);
735
 
    av_strlcpy(temp, name, GET_MODE_BUFFER_SIZE - 1);
736
 
 
737
 
    av_log(NULL, AV_LOG_DEBUG, "pp: %s\n", name);
738
 
 
739
 
    for(;;){
740
 
        char *filterName;
741
 
        int q= 1000000; //PP_QUALITY_MAX;
742
 
        int chrom=-1;
743
 
        int luma=-1;
744
 
        char *option;
745
 
        char *options[OPTIONS_ARRAY_SIZE];
746
 
        int i;
747
 
        int filterNameOk=0;
748
 
        int numOfUnknownOptions=0;
749
 
        int enable=1; //does the user want us to enabled or disabled the filter
750
 
 
751
 
        filterToken= strtok(p, filterDelimiters);
752
 
        if(filterToken == NULL) break;
753
 
        p+= strlen(filterToken) + 1; // p points to next filterToken
754
 
        filterName= strtok(filterToken, optionDelimiters);
755
 
        av_log(NULL, AV_LOG_DEBUG, "pp: %s::%s\n", filterToken, filterName);
756
 
 
757
 
        if(*filterName == '-'){
758
 
            enable=0;
759
 
            filterName++;
760
 
        }
761
 
 
762
 
        for(;;){ //for all options
763
 
            option= strtok(NULL, optionDelimiters);
764
 
            if(option == NULL) break;
765
 
 
766
 
            av_log(NULL, AV_LOG_DEBUG, "pp: option: %s\n", option);
767
 
            if(!strcmp("autoq", option) || !strcmp("a", option)) q= quality;
768
 
            else if(!strcmp("nochrom", option) || !strcmp("y", option)) chrom=0;
769
 
            else if(!strcmp("chrom", option) || !strcmp("c", option)) chrom=1;
770
 
            else if(!strcmp("noluma", option) || !strcmp("n", option)) luma=0;
771
 
            else{
772
 
                options[numOfUnknownOptions] = option;
773
 
                numOfUnknownOptions++;
774
 
            }
775
 
            if(numOfUnknownOptions >= OPTIONS_ARRAY_SIZE-1) break;
776
 
        }
777
 
        options[numOfUnknownOptions] = NULL;
778
 
 
779
 
        /* replace stuff from the replace Table */
780
 
        for(i=0; replaceTable[2*i]!=NULL; i++){
781
 
            if(!strcmp(replaceTable[2*i], filterName)){
782
 
                int newlen= strlen(replaceTable[2*i + 1]);
783
 
                int plen;
784
 
                int spaceLeft;
785
 
 
786
 
                if(p==NULL) p= temp, *p=0;      //last filter
787
 
                else p--, *p=',';               //not last filter
788
 
 
789
 
                plen= strlen(p);
790
 
                spaceLeft= p - temp + plen;
791
 
                if(spaceLeft + newlen  >= GET_MODE_BUFFER_SIZE - 1){
792
 
                    ppMode->error++;
793
 
                    break;
794
 
                }
795
 
                memmove(p + newlen, p, plen+1);
796
 
                memcpy(p, replaceTable[2*i + 1], newlen);
797
 
                filterNameOk=1;
798
 
            }
799
 
        }
800
 
 
801
 
        for(i=0; filters[i].shortName!=NULL; i++){
802
 
            if(   !strcmp(filters[i].longName, filterName)
803
 
               || !strcmp(filters[i].shortName, filterName)){
804
 
                ppMode->lumMode &= ~filters[i].mask;
805
 
                ppMode->chromMode &= ~filters[i].mask;
806
 
 
807
 
                filterNameOk=1;
808
 
                if(!enable) break; // user wants to disable it
809
 
 
810
 
                if(q >= filters[i].minLumQuality && luma)
811
 
                    ppMode->lumMode|= filters[i].mask;
812
 
                if(chrom==1 || (chrom==-1 && filters[i].chromDefault))
813
 
                    if(q >= filters[i].minChromQuality)
814
 
                            ppMode->chromMode|= filters[i].mask;
815
 
 
816
 
                if(filters[i].mask == LEVEL_FIX){
817
 
                    int o;
818
 
                    ppMode->minAllowedY= 16;
819
 
                    ppMode->maxAllowedY= 234;
820
 
                    for(o=0; options[o]!=NULL; o++){
821
 
                        if(  !strcmp(options[o],"fullyrange")
822
 
                           ||!strcmp(options[o],"f")){
823
 
                            ppMode->minAllowedY= 0;
824
 
                            ppMode->maxAllowedY= 255;
825
 
                            numOfUnknownOptions--;
826
 
                        }
827
 
                    }
828
 
                }
829
 
                else if(filters[i].mask == TEMP_NOISE_FILTER)
830
 
                {
831
 
                    int o;
832
 
                    int numOfNoises=0;
833
 
 
834
 
                    for(o=0; options[o]!=NULL; o++){
835
 
                        char *tail;
836
 
                        ppMode->maxTmpNoise[numOfNoises]=
837
 
                            strtol(options[o], &tail, 0);
838
 
                        if(tail!=options[o]){
839
 
                            numOfNoises++;
840
 
                            numOfUnknownOptions--;
841
 
                            if(numOfNoises >= 3) break;
842
 
                        }
843
 
                    }
844
 
                }
845
 
                else if(filters[i].mask == V_DEBLOCK   || filters[i].mask == H_DEBLOCK
846
 
                     || filters[i].mask == V_A_DEBLOCK || filters[i].mask == H_A_DEBLOCK){
847
 
                    int o;
848
 
 
849
 
                    for(o=0; options[o]!=NULL && o<2; o++){
850
 
                        char *tail;
851
 
                        int val= strtol(options[o], &tail, 0);
852
 
                        if(tail==options[o]) break;
853
 
 
854
 
                        numOfUnknownOptions--;
855
 
                        if(o==0) ppMode->baseDcDiff= val;
856
 
                        else ppMode->flatnessThreshold= val;
857
 
                    }
858
 
                }
859
 
                else if(filters[i].mask == FORCE_QUANT){
860
 
                    int o;
861
 
                    ppMode->forcedQuant= 15;
862
 
 
863
 
                    for(o=0; options[o]!=NULL && o<1; o++){
864
 
                        char *tail;
865
 
                        int val= strtol(options[o], &tail, 0);
866
 
                        if(tail==options[o]) break;
867
 
 
868
 
                        numOfUnknownOptions--;
869
 
                        ppMode->forcedQuant= val;
870
 
                    }
871
 
                }
872
 
            }
873
 
        }
874
 
        if(!filterNameOk) ppMode->error++;
875
 
        ppMode->error += numOfUnknownOptions;
876
 
    }
877
 
 
878
 
    av_log(NULL, AV_LOG_DEBUG, "pp: lumMode=%X, chromMode=%X\n", ppMode->lumMode, ppMode->chromMode);
879
 
    if(ppMode->error){
880
 
        av_log(NULL, AV_LOG_ERROR, "%d errors in postprocess string \"%s\"\n", ppMode->error, name);
881
 
        av_free(ppMode);
882
 
        return NULL;
883
 
    }
884
 
    return ppMode;
885
 
}
886
 
 
887
 
void pp_free_mode(pp_mode *mode){
888
 
    av_free(mode);
889
 
}
890
 
 
891
 
static void reallocAlign(void **p, int alignment, int size){
892
 
    av_free(*p);
893
 
    *p= av_mallocz(size);
894
 
}
895
 
 
896
 
static void reallocBuffers(PPContext *c, int width, int height, int stride, int qpStride){
897
 
    int mbWidth = (width+15)>>4;
898
 
    int mbHeight= (height+15)>>4;
899
 
    int i;
900
 
 
901
 
    c->stride= stride;
902
 
    c->qpStride= qpStride;
903
 
 
904
 
    reallocAlign((void **)&c->tempDst, 8, stride*24);
905
 
    reallocAlign((void **)&c->tempSrc, 8, stride*24);
906
 
    reallocAlign((void **)&c->tempBlocks, 8, 2*16*8);
907
 
    reallocAlign((void **)&c->yHistogram, 8, 256*sizeof(uint64_t));
908
 
    for(i=0; i<256; i++)
909
 
            c->yHistogram[i]= width*height/64*15/256;
910
 
 
911
 
    for(i=0; i<3; i++){
912
 
        //Note: The +17*1024 is just there so I do not have to worry about r/w over the end.
913
 
        reallocAlign((void **)&c->tempBlurred[i], 8, stride*mbHeight*16 + 17*1024);
914
 
        reallocAlign((void **)&c->tempBlurredPast[i], 8, 256*((height+7)&(~7))/2 + 17*1024);//FIXME size
915
 
    }
916
 
 
917
 
    reallocAlign((void **)&c->deintTemp, 8, 2*width+32);
918
 
    reallocAlign((void **)&c->nonBQPTable, 8, qpStride*mbHeight*sizeof(QP_STORE_T));
919
 
    reallocAlign((void **)&c->stdQPTable, 8, qpStride*mbHeight*sizeof(QP_STORE_T));
920
 
    reallocAlign((void **)&c->forcedQPTable, 8, mbWidth*sizeof(QP_STORE_T));
921
 
}
922
 
 
923
 
static const char * context_to_name(void * ptr) {
924
 
    return "postproc";
925
 
}
926
 
 
927
 
static const AVClass av_codec_context_class = { "Postproc", context_to_name, NULL };
928
 
 
929
 
pp_context *pp_get_context(int width, int height, int cpuCaps){
930
 
    PPContext *c= av_malloc(sizeof(PPContext));
931
 
    int stride= FFALIGN(width, 16);  //assumed / will realloc if needed
932
 
    int qpStride= (width+15)/16 + 2; //assumed / will realloc if needed
933
 
 
934
 
    memset(c, 0, sizeof(PPContext));
935
 
    c->av_class = &av_codec_context_class;
936
 
    c->cpuCaps= cpuCaps;
937
 
    if(cpuCaps&PP_FORMAT){
938
 
        c->hChromaSubSample= cpuCaps&0x3;
939
 
        c->vChromaSubSample= (cpuCaps>>4)&0x3;
940
 
    }else{
941
 
        c->hChromaSubSample= 1;
942
 
        c->vChromaSubSample= 1;
943
 
    }
944
 
 
945
 
    reallocBuffers(c, width, height, stride, qpStride);
946
 
 
947
 
    c->frameNum=-1;
948
 
 
949
 
    return c;
950
 
}
951
 
 
952
 
void pp_free_context(void *vc){
953
 
    PPContext *c = (PPContext*)vc;
954
 
    int i;
955
 
 
956
 
    for(i=0; i<3; i++) av_free(c->tempBlurred[i]);
957
 
    for(i=0; i<3; i++) av_free(c->tempBlurredPast[i]);
958
 
 
959
 
    av_free(c->tempBlocks);
960
 
    av_free(c->yHistogram);
961
 
    av_free(c->tempDst);
962
 
    av_free(c->tempSrc);
963
 
    av_free(c->deintTemp);
964
 
    av_free(c->stdQPTable);
965
 
    av_free(c->nonBQPTable);
966
 
    av_free(c->forcedQPTable);
967
 
 
968
 
    memset(c, 0, sizeof(PPContext));
969
 
 
970
 
    av_free(c);
971
 
}
972
 
 
973
 
void  pp_postprocess(const uint8_t * src[3], const int srcStride[3],
974
 
                     uint8_t * dst[3], const int dstStride[3],
975
 
                     int width, int height,
976
 
                     const QP_STORE_T *QP_store,  int QPStride,
977
 
                     pp_mode *vm,  void *vc, int pict_type)
978
 
{
979
 
    int mbWidth = (width+15)>>4;
980
 
    int mbHeight= (height+15)>>4;
981
 
    PPMode *mode = (PPMode*)vm;
982
 
    PPContext *c = (PPContext*)vc;
983
 
    int minStride= FFMAX(FFABS(srcStride[0]), FFABS(dstStride[0]));
984
 
    int absQPStride = FFABS(QPStride);
985
 
 
986
 
    // c->stride and c->QPStride are always positive
987
 
    if(c->stride < minStride || c->qpStride < absQPStride)
988
 
        reallocBuffers(c, width, height,
989
 
                       FFMAX(minStride, c->stride),
990
 
                       FFMAX(c->qpStride, absQPStride));
991
 
 
992
 
    if(QP_store==NULL || (mode->lumMode & FORCE_QUANT)){
993
 
        int i;
994
 
        QP_store= c->forcedQPTable;
995
 
        absQPStride = QPStride = 0;
996
 
        if(mode->lumMode & FORCE_QUANT)
997
 
            for(i=0; i<mbWidth; i++) c->forcedQPTable[i]= mode->forcedQuant;
998
 
        else
999
 
            for(i=0; i<mbWidth; i++) c->forcedQPTable[i]= 1;
1000
 
    }
1001
 
 
1002
 
    if(pict_type & PP_PICT_TYPE_QP2){
1003
 
        int i;
1004
 
        const int count= mbHeight * absQPStride;
1005
 
        for(i=0; i<(count>>2); i++){
1006
 
            ((uint32_t*)c->stdQPTable)[i] = (((const uint32_t*)QP_store)[i]>>1) & 0x7F7F7F7F;
1007
 
        }
1008
 
        for(i<<=2; i<count; i++){
1009
 
            c->stdQPTable[i] = QP_store[i]>>1;
1010
 
        }
1011
 
        QP_store= c->stdQPTable;
1012
 
        QPStride= absQPStride;
1013
 
    }
1014
 
 
1015
 
    if(0){
1016
 
        int x,y;
1017
 
        for(y=0; y<mbHeight; y++){
1018
 
            for(x=0; x<mbWidth; x++){
1019
 
                av_log(c, AV_LOG_INFO, "%2d ", QP_store[x + y*QPStride]);
1020
 
            }
1021
 
            av_log(c, AV_LOG_INFO, "\n");
1022
 
        }
1023
 
        av_log(c, AV_LOG_INFO, "\n");
1024
 
    }
1025
 
 
1026
 
    if((pict_type&7)!=3){
1027
 
        if (QPStride >= 0){
1028
 
            int i;
1029
 
            const int count= mbHeight * QPStride;
1030
 
            for(i=0; i<(count>>2); i++){
1031
 
                ((uint32_t*)c->nonBQPTable)[i] = ((const uint32_t*)QP_store)[i] & 0x3F3F3F3F;
1032
 
            }
1033
 
            for(i<<=2; i<count; i++){
1034
 
                c->nonBQPTable[i] = QP_store[i] & 0x3F;
1035
 
            }
1036
 
        } else {
1037
 
            int i,j;
1038
 
            for(i=0; i<mbHeight; i++) {
1039
 
                for(j=0; j<absQPStride; j++) {
1040
 
                    c->nonBQPTable[i*absQPStride+j] = QP_store[i*QPStride+j] & 0x3F;
1041
 
                }
1042
 
            }
1043
 
        }
1044
 
    }
1045
 
 
1046
 
    av_log(c, AV_LOG_DEBUG, "using npp filters 0x%X/0x%X\n",
1047
 
           mode->lumMode, mode->chromMode);
1048
 
 
1049
 
    postProcess(src[0], srcStride[0], dst[0], dstStride[0],
1050
 
                width, height, QP_store, QPStride, 0, mode, c);
1051
 
 
1052
 
    width  = (width )>>c->hChromaSubSample;
1053
 
    height = (height)>>c->vChromaSubSample;
1054
 
 
1055
 
    if(mode->chromMode){
1056
 
        postProcess(src[1], srcStride[1], dst[1], dstStride[1],
1057
 
                    width, height, QP_store, QPStride, 1, mode, c);
1058
 
        postProcess(src[2], srcStride[2], dst[2], dstStride[2],
1059
 
                    width, height, QP_store, QPStride, 2, mode, c);
1060
 
    }
1061
 
    else if(srcStride[1] == dstStride[1] && srcStride[2] == dstStride[2]){
1062
 
        linecpy(dst[1], src[1], height, srcStride[1]);
1063
 
        linecpy(dst[2], src[2], height, srcStride[2]);
1064
 
    }else{
1065
 
        int y;
1066
 
        for(y=0; y<height; y++){
1067
 
            memcpy(&(dst[1][y*dstStride[1]]), &(src[1][y*srcStride[1]]), width);
1068
 
            memcpy(&(dst[2][y*dstStride[2]]), &(src[2][y*srcStride[2]]), width);
1069
 
        }
1070
 
    }
1071
 
}