~ubuntu-branches/ubuntu/raring/libav/raring-security

« back to all changes in this revision

Viewing changes to .pc/post-0.7.1/0005-postprocess.c-filter-name-needs-to-be-double-0-termi.patch/libpostproc/postprocess.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler
  • Date: 2011-09-28 09:18:34 UTC
  • mfrom: (1.3.7 sid)
  • Revision ID: package-import@ubuntu.com-20110928091834-w415mnuh06h4zpvc
Tags: 4:0.7.1-7ubuntu2
Revert "Convert package to include multiarch support."

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
#if 1
 
250
    for(i=0; i<2; i++){
 
251
        if((unsigned)(src[0] - src[5] + 2*QP) > 4*QP) return 0;
 
252
        src += stride;
 
253
        if((unsigned)(src[2] - src[7] + 2*QP) > 4*QP) return 0;
 
254
        src += stride;
 
255
        if((unsigned)(src[4] - src[1] + 2*QP) > 4*QP) return 0;
 
256
        src += stride;
 
257
        if((unsigned)(src[6] - src[3] + 2*QP) > 4*QP) return 0;
 
258
        src += stride;
 
259
    }
 
260
#else
 
261
    for(i=0; i<8; i++){
 
262
        if((unsigned)(src[0] - src[7] + 2*QP) > 4*QP) return 0;
 
263
        src += stride;
 
264
    }
 
265
#endif
 
266
    return 1;
 
267
}
 
268
 
 
269
static inline int isVertMinMaxOk_C(uint8_t src[], int stride, int QP)
 
270
{
 
271
#if 1
 
272
#if 1
 
273
    int x;
 
274
    src+= stride*4;
 
275
    for(x=0; x<BLOCK_SIZE; x+=4){
 
276
        if((unsigned)(src[  x + 0*stride] - src[  x + 5*stride] + 2*QP) > 4*QP) return 0;
 
277
        if((unsigned)(src[1+x + 2*stride] - src[1+x + 7*stride] + 2*QP) > 4*QP) return 0;
 
278
        if((unsigned)(src[2+x + 4*stride] - src[2+x + 1*stride] + 2*QP) > 4*QP) return 0;
 
279
        if((unsigned)(src[3+x + 6*stride] - src[3+x + 3*stride] + 2*QP) > 4*QP) return 0;
 
280
    }
 
281
#else
 
282
    int x;
 
283
    src+= stride*3;
 
284
    for(x=0; x<BLOCK_SIZE; x++){
 
285
        if((unsigned)(src[x + stride] - src[x + (stride<<3)] + 2*QP) > 4*QP) return 0;
 
286
    }
 
287
#endif
 
288
    return 1;
 
289
#else
 
290
    int x;
 
291
    src+= stride*4;
 
292
    for(x=0; x<BLOCK_SIZE; x++){
 
293
        int min=255;
 
294
        int max=0;
 
295
        int y;
 
296
        for(y=0; y<8; y++){
 
297
            int v= src[x + y*stride];
 
298
            if(v>max) max=v;
 
299
            if(v<min) min=v;
 
300
        }
 
301
        if(max-min > 2*QP) return 0;
 
302
    }
 
303
    return 1;
 
304
#endif
 
305
}
 
306
 
 
307
static inline int horizClassify_C(uint8_t src[], int stride, PPContext *c)
 
308
{
 
309
    if( isHorizDC_C(src, stride, c) ){
 
310
        if( isHorizMinMaxOk_C(src, stride, c->QP) )
 
311
            return 1;
 
312
        else
 
313
            return 0;
 
314
    }else{
 
315
        return 2;
 
316
    }
 
317
}
 
318
 
 
319
static inline int vertClassify_C(uint8_t src[], int stride, PPContext *c)
 
320
{
 
321
    if( isVertDC_C(src, stride, c) ){
 
322
        if( isVertMinMaxOk_C(src, stride, c->QP) )
 
323
            return 1;
 
324
        else
 
325
            return 0;
 
326
    }else{
 
327
        return 2;
 
328
    }
 
329
}
 
330
 
 
331
static inline void doHorizDefFilter_C(uint8_t dst[], int stride, PPContext *c)
 
332
{
 
333
    int y;
 
334
    for(y=0; y<BLOCK_SIZE; y++){
 
335
        const int middleEnergy= 5*(dst[4] - dst[3]) + 2*(dst[2] - dst[5]);
 
336
 
 
337
        if(FFABS(middleEnergy) < 8*c->QP){
 
338
            const int q=(dst[3] - dst[4])/2;
 
339
            const int leftEnergy=  5*(dst[2] - dst[1]) + 2*(dst[0] - dst[3]);
 
340
            const int rightEnergy= 5*(dst[6] - dst[5]) + 2*(dst[4] - dst[7]);
 
341
 
 
342
            int d= FFABS(middleEnergy) - FFMIN( FFABS(leftEnergy), FFABS(rightEnergy) );
 
343
            d= FFMAX(d, 0);
 
344
 
 
345
            d= (5*d + 32) >> 6;
 
346
            d*= FFSIGN(-middleEnergy);
 
347
 
 
348
            if(q>0)
 
349
            {
 
350
                d= d<0 ? 0 : d;
 
351
                d= d>q ? q : d;
 
352
            }
 
353
            else
 
354
            {
 
355
                d= d>0 ? 0 : d;
 
356
                d= d<q ? q : d;
 
357
            }
 
358
 
 
359
            dst[3]-= d;
 
360
            dst[4]+= d;
 
361
        }
 
362
        dst+= stride;
 
363
    }
 
364
}
 
365
 
 
366
/**
 
367
 * Do a horizontal low pass filter on the 10x8 block (dst points to middle 8x8 Block)
 
368
 * using the 9-Tap Filter (1,1,2,2,4,2,2,1,1)/16 (C version)
 
369
 */
 
370
static inline void doHorizLowPass_C(uint8_t dst[], int stride, PPContext *c)
 
371
{
 
372
    int y;
 
373
    for(y=0; y<BLOCK_SIZE; y++){
 
374
        const int first= FFABS(dst[-1] - dst[0]) < c->QP ? dst[-1] : dst[0];
 
375
        const int last= FFABS(dst[8] - dst[7]) < c->QP ? dst[8] : dst[7];
 
376
 
 
377
        int sums[10];
 
378
        sums[0] = 4*first + dst[0] + dst[1] + dst[2] + 4;
 
379
        sums[1] = sums[0] - first  + dst[3];
 
380
        sums[2] = sums[1] - first  + dst[4];
 
381
        sums[3] = sums[2] - first  + dst[5];
 
382
        sums[4] = sums[3] - first  + dst[6];
 
383
        sums[5] = sums[4] - dst[0] + dst[7];
 
384
        sums[6] = sums[5] - dst[1] + last;
 
385
        sums[7] = sums[6] - dst[2] + last;
 
386
        sums[8] = sums[7] - dst[3] + last;
 
387
        sums[9] = sums[8] - dst[4] + last;
 
388
 
 
389
        dst[0]= (sums[0] + sums[2] + 2*dst[0])>>4;
 
390
        dst[1]= (sums[1] + sums[3] + 2*dst[1])>>4;
 
391
        dst[2]= (sums[2] + sums[4] + 2*dst[2])>>4;
 
392
        dst[3]= (sums[3] + sums[5] + 2*dst[3])>>4;
 
393
        dst[4]= (sums[4] + sums[6] + 2*dst[4])>>4;
 
394
        dst[5]= (sums[5] + sums[7] + 2*dst[5])>>4;
 
395
        dst[6]= (sums[6] + sums[8] + 2*dst[6])>>4;
 
396
        dst[7]= (sums[7] + sums[9] + 2*dst[7])>>4;
 
397
 
 
398
        dst+= stride;
 
399
    }
 
400
}
 
401
 
 
402
/**
 
403
 * Experimental Filter 1 (Horizontal)
 
404
 * will not damage linear gradients
 
405
 * Flat blocks should look like they were passed through the (1,1,2,2,4,2,2,1,1) 9-Tap filter
 
406
 * can only smooth blocks at the expected locations (it cannot smooth them if they did move)
 
407
 * MMX2 version does correct clipping C version does not
 
408
 * not identical with the vertical one
 
409
 */
 
410
static inline void horizX1Filter(uint8_t *src, int stride, int QP)
 
411
{
 
412
    int y;
 
413
    static uint64_t *lut= NULL;
 
414
    if(lut==NULL)
 
415
    {
 
416
        int i;
 
417
        lut = av_malloc(256*8);
 
418
        for(i=0; i<256; i++)
 
419
        {
 
420
            int v= i < 128 ? 2*i : 2*(i-256);
 
421
/*
 
422
//Simulate 112242211 9-Tap filter
 
423
            uint64_t a= (v/16)  & 0xFF;
 
424
            uint64_t b= (v/8)   & 0xFF;
 
425
            uint64_t c= (v/4)   & 0xFF;
 
426
            uint64_t d= (3*v/8) & 0xFF;
 
427
*/
 
428
//Simulate piecewise linear interpolation
 
429
            uint64_t a= (v/16)   & 0xFF;
 
430
            uint64_t b= (v*3/16) & 0xFF;
 
431
            uint64_t c= (v*5/16) & 0xFF;
 
432
            uint64_t d= (7*v/16) & 0xFF;
 
433
            uint64_t A= (0x100 - a)&0xFF;
 
434
            uint64_t B= (0x100 - b)&0xFF;
 
435
            uint64_t C= (0x100 - c)&0xFF;
 
436
            uint64_t D= (0x100 - c)&0xFF;
 
437
 
 
438
            lut[i]   = (a<<56) | (b<<48) | (c<<40) | (d<<32) |
 
439
                       (D<<24) | (C<<16) | (B<<8)  | (A);
 
440
            //lut[i] = (v<<32) | (v<<24);
 
441
        }
 
442
    }
 
443
 
 
444
    for(y=0; y<BLOCK_SIZE; y++){
 
445
        int a= src[1] - src[2];
 
446
        int b= src[3] - src[4];
 
447
        int c= src[5] - src[6];
 
448
 
 
449
        int d= FFMAX(FFABS(b) - (FFABS(a) + FFABS(c))/2, 0);
 
450
 
 
451
        if(d < QP){
 
452
            int v = d * FFSIGN(-b);
 
453
 
 
454
            src[1] +=v/8;
 
455
            src[2] +=v/4;
 
456
            src[3] +=3*v/8;
 
457
            src[4] -=3*v/8;
 
458
            src[5] -=v/4;
 
459
            src[6] -=v/8;
 
460
        }
 
461
        src+=stride;
 
462
    }
 
463
}
 
464
 
 
465
/**
 
466
 * accurate deblock filter
 
467
 */
 
468
static av_always_inline void do_a_deblock_C(uint8_t *src, int step, int stride, PPContext *c){
 
469
    int y;
 
470
    const int QP= c->QP;
 
471
    const int dcOffset= ((c->nonBQP*c->ppMode.baseDcDiff)>>8) + 1;
 
472
    const int dcThreshold= dcOffset*2 + 1;
 
473
//START_TIMER
 
474
    src+= step*4; // src points to begin of the 8x8 Block
 
475
    for(y=0; y<8; y++){
 
476
        int numEq= 0;
 
477
 
 
478
        if(((unsigned)(src[-1*step] - src[0*step] + dcOffset)) < dcThreshold) numEq++;
 
479
        if(((unsigned)(src[ 0*step] - src[1*step] + dcOffset)) < dcThreshold) numEq++;
 
480
        if(((unsigned)(src[ 1*step] - src[2*step] + dcOffset)) < dcThreshold) numEq++;
 
481
        if(((unsigned)(src[ 2*step] - src[3*step] + dcOffset)) < dcThreshold) numEq++;
 
482
        if(((unsigned)(src[ 3*step] - src[4*step] + dcOffset)) < dcThreshold) numEq++;
 
483
        if(((unsigned)(src[ 4*step] - src[5*step] + dcOffset)) < dcThreshold) numEq++;
 
484
        if(((unsigned)(src[ 5*step] - src[6*step] + dcOffset)) < dcThreshold) numEq++;
 
485
        if(((unsigned)(src[ 6*step] - src[7*step] + dcOffset)) < dcThreshold) numEq++;
 
486
        if(((unsigned)(src[ 7*step] - src[8*step] + dcOffset)) < dcThreshold) numEq++;
 
487
        if(numEq > c->ppMode.flatnessThreshold){
 
488
            int min, max, x;
 
489
 
 
490
            if(src[0] > src[step]){
 
491
                max= src[0];
 
492
                min= src[step];
 
493
            }else{
 
494
                max= src[step];
 
495
                min= src[0];
 
496
            }
 
497
            for(x=2; x<8; x+=2){
 
498
                if(src[x*step] > src[(x+1)*step]){
 
499
                        if(src[x    *step] > max) max= src[ x   *step];
 
500
                        if(src[(x+1)*step] < min) min= src[(x+1)*step];
 
501
                }else{
 
502
                        if(src[(x+1)*step] > max) max= src[(x+1)*step];
 
503
                        if(src[ x   *step] < min) min= src[ x   *step];
 
504
                }
 
505
            }
 
506
            if(max-min < 2*QP){
 
507
                const int first= FFABS(src[-1*step] - src[0]) < QP ? src[-1*step] : src[0];
 
508
                const int last= FFABS(src[8*step] - src[7*step]) < QP ? src[8*step] : src[7*step];
 
509
 
 
510
                int sums[10];
 
511
                sums[0] = 4*first + src[0*step] + src[1*step] + src[2*step] + 4;
 
512
                sums[1] = sums[0] - first       + src[3*step];
 
513
                sums[2] = sums[1] - first       + src[4*step];
 
514
                sums[3] = sums[2] - first       + src[5*step];
 
515
                sums[4] = sums[3] - first       + src[6*step];
 
516
                sums[5] = sums[4] - src[0*step] + src[7*step];
 
517
                sums[6] = sums[5] - src[1*step] + last;
 
518
                sums[7] = sums[6] - src[2*step] + last;
 
519
                sums[8] = sums[7] - src[3*step] + last;
 
520
                sums[9] = sums[8] - src[4*step] + last;
 
521
 
 
522
                src[0*step]= (sums[0] + sums[2] + 2*src[0*step])>>4;
 
523
                src[1*step]= (sums[1] + sums[3] + 2*src[1*step])>>4;
 
524
                src[2*step]= (sums[2] + sums[4] + 2*src[2*step])>>4;
 
525
                src[3*step]= (sums[3] + sums[5] + 2*src[3*step])>>4;
 
526
                src[4*step]= (sums[4] + sums[6] + 2*src[4*step])>>4;
 
527
                src[5*step]= (sums[5] + sums[7] + 2*src[5*step])>>4;
 
528
                src[6*step]= (sums[6] + sums[8] + 2*src[6*step])>>4;
 
529
                src[7*step]= (sums[7] + sums[9] + 2*src[7*step])>>4;
 
530
            }
 
531
        }else{
 
532
            const int middleEnergy= 5*(src[4*step] - src[3*step]) + 2*(src[2*step] - src[5*step]);
 
533
 
 
534
            if(FFABS(middleEnergy) < 8*QP){
 
535
                const int q=(src[3*step] - src[4*step])/2;
 
536
                const int leftEnergy=  5*(src[2*step] - src[1*step]) + 2*(src[0*step] - src[3*step]);
 
537
                const int rightEnergy= 5*(src[6*step] - src[5*step]) + 2*(src[4*step] - src[7*step]);
 
538
 
 
539
                int d= FFABS(middleEnergy) - FFMIN( FFABS(leftEnergy), FFABS(rightEnergy) );
 
540
                d= FFMAX(d, 0);
 
541
 
 
542
                d= (5*d + 32) >> 6;
 
543
                d*= FFSIGN(-middleEnergy);
 
544
 
 
545
                if(q>0){
 
546
                    d= d<0 ? 0 : d;
 
547
                    d= d>q ? q : d;
 
548
                }else{
 
549
                    d= d>0 ? 0 : d;
 
550
                    d= d<q ? q : d;
 
551
                }
 
552
 
 
553
                src[3*step]-= d;
 
554
                src[4*step]+= d;
 
555
            }
 
556
        }
 
557
 
 
558
        src += stride;
 
559
    }
 
560
/*if(step==16){
 
561
    STOP_TIMER("step16")
 
562
}else{
 
563
    STOP_TIMER("stepX")
 
564
}*/
 
565
}
 
566
 
 
567
//Note: we have C, MMX, MMX2, 3DNOW version there is no 3DNOW+MMX2 one
 
568
//Plain C versions
 
569
#if !(HAVE_MMX || HAVE_ALTIVEC) || CONFIG_RUNTIME_CPUDETECT
 
570
#define COMPILE_C
 
571
#endif
 
572
 
 
573
#if HAVE_ALTIVEC
 
574
#define COMPILE_ALTIVEC
 
575
#endif //HAVE_ALTIVEC
 
576
 
 
577
#if ARCH_X86
 
578
 
 
579
#if (HAVE_MMX && !HAVE_AMD3DNOW && !HAVE_MMX2) || CONFIG_RUNTIME_CPUDETECT
 
580
#define COMPILE_MMX
 
581
#endif
 
582
 
 
583
#if HAVE_MMX2 || CONFIG_RUNTIME_CPUDETECT
 
584
#define COMPILE_MMX2
 
585
#endif
 
586
 
 
587
#if (HAVE_AMD3DNOW && !HAVE_MMX2) || CONFIG_RUNTIME_CPUDETECT
 
588
#define COMPILE_3DNOW
 
589
#endif
 
590
#endif /* ARCH_X86 */
 
591
 
 
592
#undef HAVE_MMX
 
593
#define HAVE_MMX 0
 
594
#undef HAVE_MMX2
 
595
#define HAVE_MMX2 0
 
596
#undef HAVE_AMD3DNOW
 
597
#define HAVE_AMD3DNOW 0
 
598
#undef HAVE_ALTIVEC
 
599
#define HAVE_ALTIVEC 0
 
600
 
 
601
#ifdef COMPILE_C
 
602
#define RENAME(a) a ## _C
 
603
#include "postprocess_template.c"
 
604
#endif
 
605
 
 
606
#ifdef COMPILE_ALTIVEC
 
607
#undef RENAME
 
608
#undef HAVE_ALTIVEC
 
609
#define HAVE_ALTIVEC 1
 
610
#define RENAME(a) a ## _altivec
 
611
#include "postprocess_altivec_template.c"
 
612
#include "postprocess_template.c"
 
613
#endif
 
614
 
 
615
//MMX versions
 
616
#ifdef COMPILE_MMX
 
617
#undef RENAME
 
618
#undef HAVE_MMX
 
619
#define HAVE_MMX 1
 
620
#define RENAME(a) a ## _MMX
 
621
#include "postprocess_template.c"
 
622
#endif
 
623
 
 
624
//MMX2 versions
 
625
#ifdef COMPILE_MMX2
 
626
#undef RENAME
 
627
#undef HAVE_MMX
 
628
#undef HAVE_MMX2
 
629
#define HAVE_MMX 1
 
630
#define HAVE_MMX2 1
 
631
#define RENAME(a) a ## _MMX2
 
632
#include "postprocess_template.c"
 
633
#endif
 
634
 
 
635
//3DNOW versions
 
636
#ifdef COMPILE_3DNOW
 
637
#undef RENAME
 
638
#undef HAVE_MMX
 
639
#undef HAVE_MMX2
 
640
#undef HAVE_AMD3DNOW
 
641
#define HAVE_MMX 1
 
642
#define HAVE_MMX2 0
 
643
#define HAVE_AMD3DNOW 1
 
644
#define RENAME(a) a ## _3DNow
 
645
#include "postprocess_template.c"
 
646
#endif
 
647
 
 
648
// minor note: the HAVE_xyz is messed up after that line so do not use it.
 
649
 
 
650
static inline void postProcess(const uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height,
 
651
        const QP_STORE_T QPs[], int QPStride, int isColor, pp_mode *vm, pp_context *vc)
 
652
{
 
653
    PPContext *c= (PPContext *)vc;
 
654
    PPMode *ppMode= (PPMode *)vm;
 
655
    c->ppMode= *ppMode; //FIXME
 
656
 
 
657
    // Using ifs here as they are faster than function pointers although the
 
658
    // difference would not be measurable here but it is much better because
 
659
    // someone might exchange the CPU whithout restarting MPlayer ;)
 
660
#if CONFIG_RUNTIME_CPUDETECT
 
661
#if ARCH_X86
 
662
    // ordered per speed fastest first
 
663
    if(c->cpuCaps & PP_CPU_CAPS_MMX2)
 
664
        postProcess_MMX2(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
 
665
    else if(c->cpuCaps & PP_CPU_CAPS_3DNOW)
 
666
        postProcess_3DNow(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
 
667
    else if(c->cpuCaps & PP_CPU_CAPS_MMX)
 
668
        postProcess_MMX(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
 
669
    else
 
670
        postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
 
671
#else
 
672
#if HAVE_ALTIVEC
 
673
    if(c->cpuCaps & PP_CPU_CAPS_ALTIVEC)
 
674
            postProcess_altivec(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
 
675
    else
 
676
#endif
 
677
            postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
 
678
#endif
 
679
#else //CONFIG_RUNTIME_CPUDETECT
 
680
#if   HAVE_MMX2
 
681
            postProcess_MMX2(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
 
682
#elif HAVE_AMD3DNOW
 
683
            postProcess_3DNow(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
 
684
#elif HAVE_MMX
 
685
            postProcess_MMX(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
 
686
#elif HAVE_ALTIVEC
 
687
            postProcess_altivec(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
 
688
#else
 
689
            postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c);
 
690
#endif
 
691
#endif //!CONFIG_RUNTIME_CPUDETECT
 
692
}
 
693
 
 
694
//static void postProcess(uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height,
 
695
//        QP_STORE_T QPs[], int QPStride, int isColor, struct PPMode *ppMode);
 
696
 
 
697
/* -pp Command line Help
 
698
*/
 
699
const char pp_help[] =
 
700
"Available postprocessing filters:\n"
 
701
"Filters                        Options\n"
 
702
"short  long name       short   long option     Description\n"
 
703
"*      *               a       autoq           CPU power dependent enabler\n"
 
704
"                       c       chrom           chrominance filtering enabled\n"
 
705
"                       y       nochrom         chrominance filtering disabled\n"
 
706
"                       n       noluma          luma filtering disabled\n"
 
707
"hb     hdeblock        (2 threshold)           horizontal deblocking filter\n"
 
708
"       1. difference factor: default=32, higher -> more deblocking\n"
 
709
"       2. flatness threshold: default=39, lower -> more deblocking\n"
 
710
"                       the h & v deblocking filters share these\n"
 
711
"                       so you can't set different thresholds for h / v\n"
 
712
"vb     vdeblock        (2 threshold)           vertical deblocking filter\n"
 
713
"ha     hadeblock       (2 threshold)           horizontal deblocking filter\n"
 
714
"va     vadeblock       (2 threshold)           vertical deblocking filter\n"
 
715
"h1     x1hdeblock                              experimental h deblock filter 1\n"
 
716
"v1     x1vdeblock                              experimental v deblock filter 1\n"
 
717
"dr     dering                                  deringing filter\n"
 
718
"al     autolevels                              automatic brightness / contrast\n"
 
719
"                       f        fullyrange     stretch luminance to (0..255)\n"
 
720
"lb     linblenddeint                           linear blend deinterlacer\n"
 
721
"li     linipoldeint                            linear interpolating deinterlace\n"
 
722
"ci     cubicipoldeint                          cubic interpolating deinterlacer\n"
 
723
"md     mediandeint                             median deinterlacer\n"
 
724
"fd     ffmpegdeint                             ffmpeg deinterlacer\n"
 
725
"l5     lowpass5                                FIR lowpass deinterlacer\n"
 
726
"de     default                                 hb:a,vb:a,dr:a\n"
 
727
"fa     fast                                    h1:a,v1:a,dr:a\n"
 
728
"ac                                             ha:a:128:7,va:a,dr:a\n"
 
729
"tn     tmpnoise        (3 threshold)           temporal noise reducer\n"
 
730
"                     1. <= 2. <= 3.            larger -> stronger filtering\n"
 
731
"fq     forceQuant      <quantizer>             force quantizer\n"
 
732
"Usage:\n"
 
733
"<filterName>[:<option>[:<option>...]][[,|/][-]<filterName>[:<option>...]]...\n"
 
734
"long form example:\n"
 
735
"vdeblock:autoq/hdeblock:autoq/linblenddeint    default,-vdeblock\n"
 
736
"short form example:\n"
 
737
"vb:a/hb:a/lb                                   de,-vb\n"
 
738
"more examples:\n"
 
739
"tn:64:128:256\n"
 
740
"\n"
 
741
;
 
742
 
 
743
pp_mode *pp_get_mode_by_name_and_quality(const char *name, int quality)
 
744
{
 
745
    char temp[GET_MODE_BUFFER_SIZE];
 
746
    char *p= temp;
 
747
    static const char filterDelimiters[] = ",/";
 
748
    static const char optionDelimiters[] = ":";
 
749
    struct PPMode *ppMode;
 
750
    char *filterToken;
 
751
 
 
752
    ppMode= av_malloc(sizeof(PPMode));
 
753
 
 
754
    ppMode->lumMode= 0;
 
755
    ppMode->chromMode= 0;
 
756
    ppMode->maxTmpNoise[0]= 700;
 
757
    ppMode->maxTmpNoise[1]= 1500;
 
758
    ppMode->maxTmpNoise[2]= 3000;
 
759
    ppMode->maxAllowedY= 234;
 
760
    ppMode->minAllowedY= 16;
 
761
    ppMode->baseDcDiff= 256/8;
 
762
    ppMode->flatnessThreshold= 56-16-1;
 
763
    ppMode->maxClippedThreshold= 0.01;
 
764
    ppMode->error=0;
 
765
 
 
766
    av_strlcpy(temp, name, GET_MODE_BUFFER_SIZE);
 
767
 
 
768
    av_log(NULL, AV_LOG_DEBUG, "pp: %s\n", name);
 
769
 
 
770
    for(;;){
 
771
        char *filterName;
 
772
        int q= 1000000; //PP_QUALITY_MAX;
 
773
        int chrom=-1;
 
774
        int luma=-1;
 
775
        char *option;
 
776
        char *options[OPTIONS_ARRAY_SIZE];
 
777
        int i;
 
778
        int filterNameOk=0;
 
779
        int numOfUnknownOptions=0;
 
780
        int enable=1; //does the user want us to enabled or disabled the filter
 
781
 
 
782
        filterToken= strtok(p, filterDelimiters);
 
783
        if(filterToken == NULL) break;
 
784
        p+= strlen(filterToken) + 1; // p points to next filterToken
 
785
        filterName= strtok(filterToken, optionDelimiters);
 
786
        av_log(NULL, AV_LOG_DEBUG, "pp: %s::%s\n", filterToken, filterName);
 
787
 
 
788
        if(*filterName == '-'){
 
789
            enable=0;
 
790
            filterName++;
 
791
        }
 
792
 
 
793
        for(;;){ //for all options
 
794
            option= strtok(NULL, optionDelimiters);
 
795
            if(option == NULL) break;
 
796
 
 
797
            av_log(NULL, AV_LOG_DEBUG, "pp: option: %s\n", option);
 
798
            if(!strcmp("autoq", option) || !strcmp("a", option)) q= quality;
 
799
            else if(!strcmp("nochrom", option) || !strcmp("y", option)) chrom=0;
 
800
            else if(!strcmp("chrom", option) || !strcmp("c", option)) chrom=1;
 
801
            else if(!strcmp("noluma", option) || !strcmp("n", option)) luma=0;
 
802
            else{
 
803
                options[numOfUnknownOptions] = option;
 
804
                numOfUnknownOptions++;
 
805
            }
 
806
            if(numOfUnknownOptions >= OPTIONS_ARRAY_SIZE-1) break;
 
807
        }
 
808
        options[numOfUnknownOptions] = NULL;
 
809
 
 
810
        /* replace stuff from the replace Table */
 
811
        for(i=0; replaceTable[2*i]!=NULL; i++){
 
812
            if(!strcmp(replaceTable[2*i], filterName)){
 
813
                int newlen= strlen(replaceTable[2*i + 1]);
 
814
                int plen;
 
815
                int spaceLeft;
 
816
 
 
817
                if(p==NULL) p= temp, *p=0;      //last filter
 
818
                else p--, *p=',';               //not last filter
 
819
 
 
820
                plen= strlen(p);
 
821
                spaceLeft= p - temp + plen;
 
822
                if(spaceLeft + newlen  >= GET_MODE_BUFFER_SIZE){
 
823
                    ppMode->error++;
 
824
                    break;
 
825
                }
 
826
                memmove(p + newlen, p, plen+1);
 
827
                memcpy(p, replaceTable[2*i + 1], newlen);
 
828
                filterNameOk=1;
 
829
            }
 
830
        }
 
831
 
 
832
        for(i=0; filters[i].shortName!=NULL; i++){
 
833
            if(   !strcmp(filters[i].longName, filterName)
 
834
               || !strcmp(filters[i].shortName, filterName)){
 
835
                ppMode->lumMode &= ~filters[i].mask;
 
836
                ppMode->chromMode &= ~filters[i].mask;
 
837
 
 
838
                filterNameOk=1;
 
839
                if(!enable) break; // user wants to disable it
 
840
 
 
841
                if(q >= filters[i].minLumQuality && luma)
 
842
                    ppMode->lumMode|= filters[i].mask;
 
843
                if(chrom==1 || (chrom==-1 && filters[i].chromDefault))
 
844
                    if(q >= filters[i].minChromQuality)
 
845
                            ppMode->chromMode|= filters[i].mask;
 
846
 
 
847
                if(filters[i].mask == LEVEL_FIX){
 
848
                    int o;
 
849
                    ppMode->minAllowedY= 16;
 
850
                    ppMode->maxAllowedY= 234;
 
851
                    for(o=0; options[o]!=NULL; o++){
 
852
                        if(  !strcmp(options[o],"fullyrange")
 
853
                           ||!strcmp(options[o],"f")){
 
854
                            ppMode->minAllowedY= 0;
 
855
                            ppMode->maxAllowedY= 255;
 
856
                            numOfUnknownOptions--;
 
857
                        }
 
858
                    }
 
859
                }
 
860
                else if(filters[i].mask == TEMP_NOISE_FILTER)
 
861
                {
 
862
                    int o;
 
863
                    int numOfNoises=0;
 
864
 
 
865
                    for(o=0; options[o]!=NULL; o++){
 
866
                        char *tail;
 
867
                        ppMode->maxTmpNoise[numOfNoises]=
 
868
                            strtol(options[o], &tail, 0);
 
869
                        if(tail!=options[o]){
 
870
                            numOfNoises++;
 
871
                            numOfUnknownOptions--;
 
872
                            if(numOfNoises >= 3) break;
 
873
                        }
 
874
                    }
 
875
                }
 
876
                else if(filters[i].mask == V_DEBLOCK   || filters[i].mask == H_DEBLOCK
 
877
                     || filters[i].mask == V_A_DEBLOCK || filters[i].mask == H_A_DEBLOCK){
 
878
                    int o;
 
879
 
 
880
                    for(o=0; options[o]!=NULL && o<2; o++){
 
881
                        char *tail;
 
882
                        int val= strtol(options[o], &tail, 0);
 
883
                        if(tail==options[o]) break;
 
884
 
 
885
                        numOfUnknownOptions--;
 
886
                        if(o==0) ppMode->baseDcDiff= val;
 
887
                        else ppMode->flatnessThreshold= val;
 
888
                    }
 
889
                }
 
890
                else if(filters[i].mask == FORCE_QUANT){
 
891
                    int o;
 
892
                    ppMode->forcedQuant= 15;
 
893
 
 
894
                    for(o=0; options[o]!=NULL && o<1; o++){
 
895
                        char *tail;
 
896
                        int val= strtol(options[o], &tail, 0);
 
897
                        if(tail==options[o]) break;
 
898
 
 
899
                        numOfUnknownOptions--;
 
900
                        ppMode->forcedQuant= val;
 
901
                    }
 
902
                }
 
903
            }
 
904
        }
 
905
        if(!filterNameOk) ppMode->error++;
 
906
        ppMode->error += numOfUnknownOptions;
 
907
    }
 
908
 
 
909
    av_log(NULL, AV_LOG_DEBUG, "pp: lumMode=%X, chromMode=%X\n", ppMode->lumMode, ppMode->chromMode);
 
910
    if(ppMode->error){
 
911
        av_log(NULL, AV_LOG_ERROR, "%d errors in postprocess string \"%s\"\n", ppMode->error, name);
 
912
        av_free(ppMode);
 
913
        return NULL;
 
914
    }
 
915
    return ppMode;
 
916
}
 
917
 
 
918
void pp_free_mode(pp_mode *mode){
 
919
    av_free(mode);
 
920
}
 
921
 
 
922
static void reallocAlign(void **p, int alignment, int size){
 
923
    av_free(*p);
 
924
    *p= av_mallocz(size);
 
925
}
 
926
 
 
927
static void reallocBuffers(PPContext *c, int width, int height, int stride, int qpStride){
 
928
    int mbWidth = (width+15)>>4;
 
929
    int mbHeight= (height+15)>>4;
 
930
    int i;
 
931
 
 
932
    c->stride= stride;
 
933
    c->qpStride= qpStride;
 
934
 
 
935
    reallocAlign((void **)&c->tempDst, 8, stride*24);
 
936
    reallocAlign((void **)&c->tempSrc, 8, stride*24);
 
937
    reallocAlign((void **)&c->tempBlocks, 8, 2*16*8);
 
938
    reallocAlign((void **)&c->yHistogram, 8, 256*sizeof(uint64_t));
 
939
    for(i=0; i<256; i++)
 
940
            c->yHistogram[i]= width*height/64*15/256;
 
941
 
 
942
    for(i=0; i<3; i++){
 
943
        //Note: The +17*1024 is just there so i do not have to worry about r/w over the end.
 
944
        reallocAlign((void **)&c->tempBlurred[i], 8, stride*mbHeight*16 + 17*1024);
 
945
        reallocAlign((void **)&c->tempBlurredPast[i], 8, 256*((height+7)&(~7))/2 + 17*1024);//FIXME size
 
946
    }
 
947
 
 
948
    reallocAlign((void **)&c->deintTemp, 8, 2*width+32);
 
949
    reallocAlign((void **)&c->nonBQPTable, 8, qpStride*mbHeight*sizeof(QP_STORE_T));
 
950
    reallocAlign((void **)&c->stdQPTable, 8, qpStride*mbHeight*sizeof(QP_STORE_T));
 
951
    reallocAlign((void **)&c->forcedQPTable, 8, mbWidth*sizeof(QP_STORE_T));
 
952
}
 
953
 
 
954
static const char * context_to_name(void * ptr) {
 
955
    return "postproc";
 
956
}
 
957
 
 
958
static const AVClass av_codec_context_class = { "Postproc", context_to_name, NULL };
 
959
 
 
960
pp_context *pp_get_context(int width, int height, int cpuCaps){
 
961
    PPContext *c= av_malloc(sizeof(PPContext));
 
962
    int stride= FFALIGN(width, 16);  //assumed / will realloc if needed
 
963
    int qpStride= (width+15)/16 + 2; //assumed / will realloc if needed
 
964
 
 
965
    memset(c, 0, sizeof(PPContext));
 
966
    c->av_class = &av_codec_context_class;
 
967
    c->cpuCaps= cpuCaps;
 
968
    if(cpuCaps&PP_FORMAT){
 
969
        c->hChromaSubSample= cpuCaps&0x3;
 
970
        c->vChromaSubSample= (cpuCaps>>4)&0x3;
 
971
    }else{
 
972
        c->hChromaSubSample= 1;
 
973
        c->vChromaSubSample= 1;
 
974
    }
 
975
 
 
976
    reallocBuffers(c, width, height, stride, qpStride);
 
977
 
 
978
    c->frameNum=-1;
 
979
 
 
980
    return c;
 
981
}
 
982
 
 
983
void pp_free_context(void *vc){
 
984
    PPContext *c = (PPContext*)vc;
 
985
    int i;
 
986
 
 
987
    for(i=0; i<3; i++) av_free(c->tempBlurred[i]);
 
988
    for(i=0; i<3; i++) av_free(c->tempBlurredPast[i]);
 
989
 
 
990
    av_free(c->tempBlocks);
 
991
    av_free(c->yHistogram);
 
992
    av_free(c->tempDst);
 
993
    av_free(c->tempSrc);
 
994
    av_free(c->deintTemp);
 
995
    av_free(c->stdQPTable);
 
996
    av_free(c->nonBQPTable);
 
997
    av_free(c->forcedQPTable);
 
998
 
 
999
    memset(c, 0, sizeof(PPContext));
 
1000
 
 
1001
    av_free(c);
 
1002
}
 
1003
 
 
1004
void  pp_postprocess(const uint8_t * src[3], const int srcStride[3],
 
1005
                     uint8_t * dst[3], const int dstStride[3],
 
1006
                     int width, int height,
 
1007
                     const QP_STORE_T *QP_store,  int QPStride,
 
1008
                     pp_mode *vm,  void *vc, int pict_type)
 
1009
{
 
1010
    int mbWidth = (width+15)>>4;
 
1011
    int mbHeight= (height+15)>>4;
 
1012
    PPMode *mode = (PPMode*)vm;
 
1013
    PPContext *c = (PPContext*)vc;
 
1014
    int minStride= FFMAX(FFABS(srcStride[0]), FFABS(dstStride[0]));
 
1015
    int absQPStride = FFABS(QPStride);
 
1016
 
 
1017
    // c->stride and c->QPStride are always positive
 
1018
    if(c->stride < minStride || c->qpStride < absQPStride)
 
1019
        reallocBuffers(c, width, height,
 
1020
                       FFMAX(minStride, c->stride),
 
1021
                       FFMAX(c->qpStride, absQPStride));
 
1022
 
 
1023
    if(QP_store==NULL || (mode->lumMode & FORCE_QUANT)){
 
1024
        int i;
 
1025
        QP_store= c->forcedQPTable;
 
1026
        absQPStride = QPStride = 0;
 
1027
        if(mode->lumMode & FORCE_QUANT)
 
1028
            for(i=0; i<mbWidth; i++) c->forcedQPTable[i]= mode->forcedQuant;
 
1029
        else
 
1030
            for(i=0; i<mbWidth; i++) c->forcedQPTable[i]= 1;
 
1031
    }
 
1032
 
 
1033
    if(pict_type & PP_PICT_TYPE_QP2){
 
1034
        int i;
 
1035
        const int count= mbHeight * absQPStride;
 
1036
        for(i=0; i<(count>>2); i++){
 
1037
            ((uint32_t*)c->stdQPTable)[i] = (((const uint32_t*)QP_store)[i]>>1) & 0x7F7F7F7F;
 
1038
        }
 
1039
        for(i<<=2; i<count; i++){
 
1040
            c->stdQPTable[i] = QP_store[i]>>1;
 
1041
        }
 
1042
        QP_store= c->stdQPTable;
 
1043
        QPStride= absQPStride;
 
1044
    }
 
1045
 
 
1046
    if(0){
 
1047
        int x,y;
 
1048
        for(y=0; y<mbHeight; y++){
 
1049
            for(x=0; x<mbWidth; x++){
 
1050
                av_log(c, AV_LOG_INFO, "%2d ", QP_store[x + y*QPStride]);
 
1051
            }
 
1052
            av_log(c, AV_LOG_INFO, "\n");
 
1053
        }
 
1054
        av_log(c, AV_LOG_INFO, "\n");
 
1055
    }
 
1056
 
 
1057
    if((pict_type&7)!=3){
 
1058
        if (QPStride >= 0){
 
1059
            int i;
 
1060
            const int count= mbHeight * QPStride;
 
1061
            for(i=0; i<(count>>2); i++){
 
1062
                ((uint32_t*)c->nonBQPTable)[i] = ((const uint32_t*)QP_store)[i] & 0x3F3F3F3F;
 
1063
            }
 
1064
            for(i<<=2; i<count; i++){
 
1065
                c->nonBQPTable[i] = QP_store[i] & 0x3F;
 
1066
            }
 
1067
        } else {
 
1068
            int i,j;
 
1069
            for(i=0; i<mbHeight; i++) {
 
1070
                for(j=0; j<absQPStride; j++) {
 
1071
                    c->nonBQPTable[i*absQPStride+j] = QP_store[i*QPStride+j] & 0x3F;
 
1072
                }
 
1073
            }
 
1074
        }
 
1075
    }
 
1076
 
 
1077
    av_log(c, AV_LOG_DEBUG, "using npp filters 0x%X/0x%X\n",
 
1078
           mode->lumMode, mode->chromMode);
 
1079
 
 
1080
    postProcess(src[0], srcStride[0], dst[0], dstStride[0],
 
1081
                width, height, QP_store, QPStride, 0, mode, c);
 
1082
 
 
1083
    width  = (width )>>c->hChromaSubSample;
 
1084
    height = (height)>>c->vChromaSubSample;
 
1085
 
 
1086
    if(mode->chromMode){
 
1087
        postProcess(src[1], srcStride[1], dst[1], dstStride[1],
 
1088
                    width, height, QP_store, QPStride, 1, mode, c);
 
1089
        postProcess(src[2], srcStride[2], dst[2], dstStride[2],
 
1090
                    width, height, QP_store, QPStride, 2, mode, c);
 
1091
    }
 
1092
    else if(srcStride[1] == dstStride[1] && srcStride[2] == dstStride[2]){
 
1093
        linecpy(dst[1], src[1], height, srcStride[1]);
 
1094
        linecpy(dst[2], src[2], height, srcStride[2]);
 
1095
    }else{
 
1096
        int y;
 
1097
        for(y=0; y<height; y++){
 
1098
            memcpy(&(dst[1][y*dstStride[1]]), &(src[1][y*srcStride[1]]), width);
 
1099
            memcpy(&(dst[2][y*dstStride[2]]), &(src[2][y*srcStride[2]]), width);
 
1100
        }
 
1101
    }
 
1102
}