~ubuntu-branches/debian/wheezy/vlc/wheezy

« back to all changes in this revision

Viewing changes to modules/codec/ffmpeg/postprocessing/postprocessing_mmxext.c

Tags: upstream-0.7.2.final
ImportĀ upstreamĀ versionĀ 0.7.2.final

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 * postprocessing_mmxext.c: Post Processing plugin MMXEXT
 
3
 *****************************************************************************
 
4
 * Copyright (C) 2001 VideoLAN
 
5
 * $Id: postprocessing_mmxext.c 6961 2004-03-05 17:34:23Z sam $
 
6
 *
 
7
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 
22
 *****************************************************************************/
 
23
 
 
24
#include <vlc/vlc.h> /* only use uint8_t, uint32_t .... */
 
25
 
 
26
#include "postprocessing.h"
 
27
#include "postprocessing_common.h"
 
28
 
 
29
/*****************************************************************************
 
30
 *
 
31
 * Internals functions common to pp_Deblock_V and pp_Deblock_H
 
32
 *
 
33
 *****************************************************************************/
 
34
 
 
35
/*****************************************************************************
 
36
 * MMX stuff
 
37
 *****************************************************************************/
 
38
 
 
39
 
 
40
/* XXX PP_THR1 need to be defined as ULL */
 
41
 
 
42
/* Use same things as in idct but how it work ? */
 
43
#define UNUSED_LONGLONG( foo ) \
 
44
    static const unsigned long long foo __asm__ (#foo)  __attribute__((unused))
 
45
 
 
46
/* to calculate isDC_mode for mmx */
 
47
UNUSED_LONGLONG( mmx_thr1 ) = ( PP_THR1 << 56 )|
 
48
                              ( PP_THR1 << 48 )|
 
49
                              ( PP_THR1 << 40 )|
 
50
                              ( PP_THR1 << 32 )|
 
51
                              ( PP_THR1 << 24 )|
 
52
                              ( PP_THR1 << 16 )|
 
53
                              ( PP_THR1 <<  8 )|
 
54
                              ( PP_THR1 );
 
55
 
 
56
UNUSED_LONGLONG( mmx_127_thr1 ) = ( ( 127ULL - PP_THR1 ) << 56 )|
 
57
                                  ( ( 127ULL - PP_THR1 ) << 48 )|
 
58
                                  ( ( 127ULL - PP_THR1 ) << 40 )|
 
59
                                  ( ( 127ULL - PP_THR1 ) << 32 )|
 
60
                                  ( ( 127ULL - PP_THR1 ) << 24 )|
 
61
                                  ( ( 127ULL - PP_THR1 ) << 16 )|
 
62
                                  ( ( 127ULL - PP_THR1 ) <<  8 )|
 
63
                                  ( ( 127ULL - PP_THR1 ) );
 
64
 
 
65
UNUSED_LONGLONG( mmx_127_2xthr1_1 ) = ( ( 127ULL - PP_2xTHR1 -1) << 56 )|
 
66
                                    ( ( 127ULL - PP_2xTHR1 -1 ) << 48 )|
 
67
                                    ( ( 127ULL - PP_2xTHR1 -1 ) << 40 )|
 
68
                                    ( ( 127ULL - PP_2xTHR1 -1 ) << 32 )|
 
69
                                    ( ( 127ULL - PP_2xTHR1 -1 ) << 24 )|
 
70
                                    ( ( 127ULL - PP_2xTHR1 -1 ) << 16 )|
 
71
                                    ( ( 127ULL - PP_2xTHR1 -1 ) <<  8 )|
 
72
                                    ( ( 127ULL - PP_2xTHR1 -1 ) );
 
73
 
 
74
UNUSED_LONGLONG( mmx_m2_5_m5_2 ) = 0xfffe0005fffb0002ULL;
 
75
 
 
76
 
 
77
/* find min bytes from r ans set it in r, t is destroyed */
 
78
#define MMXEXT_GET_PMIN( r, t ) \
 
79
   "movq      " #r ",     " #t "                                \n" \
 
80
   "psrlq       $8,       " #t "                                \n" \
 
81
   "pminub    " #t ",     " #r "                                \n" \
 
82
   "pshufw $0xf5, " #r ", " #t " #instead of shift with tmp reg \n" \
 
83
   "pminub    " #t ",     " #r "                                \n" \
 
84
   "pshufw $0xfe, " #r ", " #t "                                \n" \
 
85
   "pminub    " #t ",     " #r "                                \n"
 
86
 
 
87
 /* find mzx bytes from r ans set it in r, t is destroyed */
 
88
#define MMXEXT_GET_PMAX( r, t ) \
 
89
   "movq      " #r ",     " #t "                                \n" \
 
90
   "psrlq       $8,       " #t "                                \n" \
 
91
   "pmaxub    " #t ",     " #r "                                \n" \
 
92
   "pshufw $0xf5, " #r ", " #t "                                \n" \
 
93
   "pmaxub    " #t ",     " #r "                                \n" \
 
94
   "pshufw $0xfe, " #r ", " #t "                                \n" \
 
95
   "pmaxub    " #t ",     " #r "                                \n"
 
96
 
 
97
 
 
98
 
 
99
#define MMXEXT_GET_LMINMAX( s, m, M, t ) \
 
100
    "movq   " #s ",        " #t "   \n" \
 
101
    "pminub " #t ",        " #m "   \n" \
 
102
    "pmaxub " #t ",        " #M "   \n"
 
103
 
 
104
/* Some tips for MMX
 
105
 
 
106
    * |a-b| :
 
107
        d1 = a - b with unsigned saturate
 
108
        d2 = b - a  with ...
 
109
        |a-b| = d1 | d2
 
110
 
 
111
 
 
112
*/
 
113
 
 
114
/****************************************************************************
 
115
 * pp_deblock_isDC_mode : Check if we will use DC mode or Default mode
 
116
 ****************************************************************************
 
117
 * Use constant PP_THR1 and PP_THR2 ( PP_2xTHR1 )
 
118
 *
 
119
 * Called for for each pixel on a boundary block when doing deblocking
 
120
 *  so need to be fast ...
 
121
 *
 
122
 ****************************************************************************/
 
123
static inline int pp_deblock_isDC_mode( uint8_t *p_v )
 
124
{
 
125
    unsigned int i_eq_cnt;
 
126
 
 
127
 
 
128
    /* algo :
 
129
       x = v[i] - v[i+1] without signed saturation
 
130
        ( XXX see if there is'nt problem, but can't be with signed
 
131
        sat because pixel will be saturate :(
 
132
       so x within [-128, 127] and we have to test if it fit in [-M, M]
 
133
       we add 127-M with wrap around -> good value fit in [ 127-2*M, 127]
 
134
       and if x >= 127 - 2 * M ie x > 127 -2*M - 1 value is good
 
135
    */
 
136
#if 0
 
137
    __asm__ __volatile__ (
 
138
   "                                #* Do (v0-v1) to (v7-v8)            \n"
 
139
   "movq      (%1),         %%mm1   #  load v0->v7                      \n"
 
140
   "movq      1(%1),        %%mm2   #  load v1->v8                      \n"
 
141
   "psubb    %%mm2,         %%mm1   #  v[i]-v[i+1]                      \n"
 
142
   "paddb     mmx_127_thr1, %%mm1   #  + 127-THR1 with wrap             \n"
 
143
   "pcmpgtb   mmx_127_2xthr1_1, %%mm1 #  >  127 -2*thr1 - 1             \n"
 
144
   "pxor      %%mm0,        %%mm0   # mm0 = 0                           \n"
 
145
   "psadbw    %%mm1,        %%mm0                                       \n"
 
146
   "movd      %%mm0,        %0      #                                   \n"
 
147
   "negl      %0                                                        \n"
 
148
   "andl      $255,         %0"
 
149
 
 
150
       : "=r"(i_eq_cnt) : "r" (p_v) );
 
151
#endif
 
152
     __asm__ __volatile__ (
 
153
   "                                #* Do (v0-v1) to (v7-v8)            \n"
 
154
   "movq      (%1),         %%mm1   #  load v0->v7                      \n"
 
155
   "pxor      %%mm0,        %%mm0   # mm0 = 0                           \n"
 
156
   "movq      1(%1),        %%mm2   #  load v1->v8                      \n"
 
157
   "psubb    %%mm2,         %%mm1   #  v[i]-v[i+1]                      \n"
 
158
   "paddb     mmx_127_thr1, %%mm1   #  + 127-THR1 with wrap             \n"
 
159
   "pcmpgtb   mmx_127_2xthr1_1, %%mm1 #  >  127 -2*thr1 - 1             \n"
 
160
   "psadbw    %%mm1,        %%mm0                                       \n"
 
161
   "movd      %%mm0,        %0      #                                   \n"
 
162
   "negl      %0"
 
163
 
 
164
       : "=r"(i_eq_cnt) : "r" (p_v) );
 
165
 
 
166
    /* last test, hey, 9 don't fit in MMX */
 
167
    if((  ( p_v[8] - p_v[9] + PP_THR1 )&0xffff )<= PP_2xTHR1 )
 
168
    {
 
169
         i_eq_cnt++;
 
170
    }
 
171
 
 
172
#if 0
 
173
    /* algo :  if ( | v[i] -v[i+1] | <= PP_THR1 ) { i_eq_cnt++; } */
 
174
    i_eq_cnt = 0;
 
175
 
 
176
    for( i =0; i < 9; i++ )
 
177
    {
 
178
        if((  ( p_v[i] - p_v[i+1] + PP_THR1 )&0xffff )<= PP_2xTHR1 )
 
179
        {
 
180
            i_eq_cnt++;
 
181
        }
 
182
    }
 
183
#endif
 
184
 
 
185
    return( (i_eq_cnt >= PP_THR2 ) ? 1 : 0 );
 
186
}
 
187
 
 
188
static inline int pp_deblock_isMinMaxOk( uint8_t *p_v, int i_QP )
 
189
{
 
190
    int i_range;
 
191
 
 
192
    __asm__ __volatile__ (
 
193
   "movq        1(%1),      %%mm0   # 8 bytes                   \n"
 
194
   "movq        %%mm0,      %%mm1                               \n"
 
195
    MMXEXT_GET_PMIN( %%mm0, %%mm7 )
 
196
    MMXEXT_GET_PMAX( %%mm1, %%mm7 )
 
197
   "psubd       %%mm0,      %%mm1   # max - min                 \n"
 
198
   "movd        %%mm1,      %0                                  \n"
 
199
   "andl        $255,       %0" : "=r"(i_range) : "r"(p_v) );
 
200
 
 
201
#if 0
 
202
    int i_max, i_min;
 
203
    int i;
 
204
 
 
205
    i_min = i_max = p_v[1];
 
206
    for( i = 2; i < 9; i++ )
 
207
    {
 
208
        if( i_max < p_v[i] ) i_max = p_v[i];
 
209
        if( i_min > p_v[i] ) i_min = p_v[i];
 
210
    }
 
211
    i_range = i_max - i_min;
 
212
#endif
 
213
 
 
214
    return( i_range< 2*i_QP ? 1 : 0 );
 
215
}
 
216
 
 
217
 
 
218
static inline void pp_deblock_DefaultMode( uint8_t i_v[10], int i_stride,
 
219
                                      int i_QP )
 
220
{
 
221
    int d, i_delta;
 
222
    int a3x0, a3x0_, a3x1, a3x2;
 
223
    int b_neg;
 
224
 
 
225
    /* d = CLIP( 5(a3x0' - a3x0)//8, 0, (v4-v5)/2 ).d( abs(a3x0) < QP ) */
 
226
 
 
227
    /* First calculate a3x0 */
 
228
    __asm__ __volatile__ (
 
229
   "pxor    %%mm7,  %%mm7           # mm7 = 0          \n"
 
230
   "movq    mmx_m2_5_m5_2, %%mm6    # mm6 =(2,-5,5,-2) \n"
 
231
   "movd    3(%1),  %%mm0           \n"
 
232
   "punpcklbw %%mm7,%%mm0           \n"
 
233
   "pmaddwd %%mm6,  %%mm0           \n"
 
234
   "pshufw  $0xfe,  %%mm0, %%mm1    \n"
 
235
   "paddd   %%mm1,  %%mm0           \n"
 
236
   "movd    %%mm0,  %0" : "=r"(a3x0) :"r"(i_v) );
 
237
#if 0
 
238
    a3x0 = 2 * ( i_v[3] - i_v[6] ) + 5 *( i_v[5] - i_v[4] );
 
239
#endif
 
240
 
 
241
    if( a3x0 < 0 )
 
242
    {
 
243
        b_neg = 1;
 
244
        a3x0  = -a3x0;
 
245
    }
 
246
    else
 
247
    {
 
248
        b_neg = 0;
 
249
    }
 
250
    /* XXX Now a3x0 is abs( a3x0 ) */
 
251
    if( ( a3x0 < 8 * i_QP )&&( a3x0 != 0 ) ) /* |a3x0| < 8*i_QP */
 
252
    {
 
253
        /* calculate a3x1 et a3x2 */
 
254
        __asm__ __volatile__ (
 
255
       "                                # mm7 = 0                   \n"
 
256
       "                                # mm6 = ( 2, -5, 5, -2 )    \n"
 
257
       "movd    1(%2),  %%mm0           \n"
 
258
       "movd    5(%2),  %%mm2           \n"
 
259
       "punpcklbw %%mm7,%%mm0           \n"
 
260
       "punpcklbw %%mm7,%%mm2           \n"
 
261
       "pmaddwd %%mm6,  %%mm0           \n"
 
262
       "pmaddwd %%mm6,  %%mm2           \n"
 
263
       "pshufw  $0xfe,  %%mm0, %%mm1    \n"
 
264
       "paddd   %%mm1,  %%mm0           # mm0 = a3x1    \n"
 
265
       "movd    %%mm0,  %0              \n"
 
266
       "pshufw  $0xfe,  %%mm2, %%mm1    \n"
 
267
       "paddd   %%mm1,  %%mm2           # mm2 = a3x2    \n"
 
268
       "movd    %%mm2,  %1              \n"
 
269
        : "=r"(a3x1), "=r"(a3x2) : "r"(i_v) );
 
270
#if 0
 
271
        a3x1 = 2 * ( i_v[1] - i_v[4] ) + 5 * ( i_v[3] - i_v[2] );
 
272
        a3x2 = 2 * ( i_v[5] - i_v[8] ) + 5 * ( i_v[7] - i_v[6] );
 
273
#endif
 
274
 
 
275
        if( a3x1 < 0) a3x1 = -a3x1; /* abs( a3x1 ) */
 
276
        if( a3x2 < 0) a3x2 = -a3x2; /* abs( a3x2 ) */
 
277
 
 
278
        a3x0_ = PP_MIN3( a3x0, a3x1, a3x2 );
 
279
 
 
280
        d = 5 *( a3x0 - a3x0_ ) / 8; /* always > 0 */
 
281
 
 
282
        i_delta = ( i_v[4] - i_v[5] ) / 2;
 
283
        /* clip into [0, i_delta] or [i_delta, 0] */
 
284
        if( i_delta < 0 )
 
285
        {
 
286
            if( !b_neg ) /* since true d has sgn(d) = - sgn( a3x0 ) */
 
287
            {
 
288
                d = -d;
 
289
                if( d < i_delta ) d = i_delta;
 
290
                i_v[4] -= d;
 
291
                i_v[5] += d;
 
292
            }
 
293
        }
 
294
        else
 
295
        {
 
296
            if( b_neg )
 
297
            {
 
298
                if( d > i_delta ) d = i_delta;
 
299
                i_v[4] -= d;
 
300
                i_v[5] += d;
 
301
            }
 
302
        }
 
303
    }
 
304
}
 
305
 
 
306
 
 
307
 
 
308
static inline void pp_deblock_DCMode( uint8_t *p_v, /*  = int i_v[10] */
 
309
                                 int i_QP )
 
310
{
 
311
    int i_p0, i_p9;
 
312
    i_p0 = PP_ABS( p_v[1] - p_v[0] ) < i_QP ? p_v[0] : p_v[1];
 
313
    i_p9 = PP_ABS( p_v[8] - p_v[9] ) < i_QP ? p_v[9] : p_v[8];
 
314
 
 
315
    /* mm0 = 8 pix unmodified
 
316
     -We will process first 4 pixel
 
317
       mm0 = 8 pix unmodified
 
318
       mm1 = for the first part of the 4 first pix
 
319
             (v1) -> (p0) -> ... ( word )
 
320
             (v2)    (v1)
 
321
             (v3)    (v2)
 
322
             (v4)    (v3)
 
323
 
 
324
           = for the commoin part between first and last pix
 
325
             (v2) -> (v3) -> ... ( word )
 
326
             (v3)    (v4)
 
327
             (v4)    (v5)
 
328
             (v5)    (v6)
 
329
 
 
330
           = for the last part of the 4 last pix
 
331
             (v5) -> (v6) -> ... ( word )
 
332
             (v6)    (v7)
 
333
             (v7)    (v8)
 
334
             (v8)    (p9)
 
335
 
 
336
       mm2 = acu for first new pix
 
337
       mm3 = acu for last pix
 
338
       mm4 = unused
 
339
       mm5 = p0
 
340
       mm6 = p9 << 48
 
341
       mm7 = 0 */
 
342
    __asm__ __volatile__ (
 
343
   "pxor        %%mm7,      %%mm7   \n"
 
344
   "movq        1(%0),      %%mm0   # get 8 pix             \n"
 
345
   "                                # unpack into mm1       \n"
 
346
   "movq        %%mm0,      %%mm1   \n"
 
347
   "punpcklbw   %%mm7,      %%mm1   \n"
 
348
   "                                # get p_0 and i_p9      \n"
 
349
   "movd        %1,         %%mm5   \n"
 
350
   "movd        %2,         %%mm6   \n"
 
351
   "psllq       $48,        %%mm6   \n"
 
352
   "                                \n"
 
353
   "movq        %%mm1,      %%mm3   # p_v[5-8] = v[1-4] !!  \n"
 
354
   "movq        %%mm1,      %%mm2   \n"
 
355
   "psllw       $2,         %%mm2   # p_v[1-4] = 4*v[1-4]   \n"
 
356
   "                                \n"
 
357
   "psllq       $16,        %%mm1   \n"
 
358
   "por         %%mm5,      %%mm1   # mm1 =( p0, v1, v2 ,v3)\n"
 
359
   "                                \n"
 
360
   "paddw       %%mm1,      %%mm2   \n"
 
361
   "paddw       %%mm1,      %%mm2   \n"
 
362
   "                                \n"
 
363
   "pshufw      $0x90,%%mm1,%%mm1   # mm1 =( p0, p0, v1, v2)\n"
 
364
   "paddw       %%mm1,      %%mm2   \n"
 
365
   "paddw       %%mm1,      %%mm2   \n"
 
366
   "                                \n"
 
367
   "pshufw      $0x90,%%mm1,%%mm1   # mm1 =( p0, p0, p0, v2)\n"
 
368
   "paddw       %%mm1,      %%mm2   \n"
 
369
   "                                \n"
 
370
   "pshufw      $0x90,%%mm1,%%mm1   # mm1 =( p0, p0, p0, p0)\n"
 
371
   "paddw       %%mm1,      %%mm2   \n"
 
372
   "                                # Now last part a little borring\n"
 
373
   "                                # last part for mm2, beginig for mm3\n"
 
374
   "movq        %%mm0,      %%mm1   \n"
 
375
   "psrlq       $8,         %%mm1   \n"
 
376
   "punpcklbw   %%mm7,      %%mm1   # mm1 =( v2, v3, v4, v5 )\n"
 
377
   "paddw       %%mm1,      %%mm2   \n"
 
378
   "paddw       %%mm1,      %%mm2   \n"
 
379
   "paddw       %%mm1,      %%mm3   \n"
 
380
 
 
381
   "                                \n"
 
382
   "movq        %%mm0,      %%mm1   \n"
 
383
   "psrlq       $16,        %%mm1   \n"
 
384
   "punpcklbw   %%mm7,      %%mm1   # mm1 =( v3, v4, v5, v6 )\n"
 
385
   "psllw       $1,         %%mm1   \n"
 
386
   "paddw       %%mm1,      %%mm2   \n"
 
387
   "paddw       %%mm1,      %%mm3   \n"
 
388
   "                                \n"
 
389
   "movq        %%mm0,      %%mm1   \n"
 
390
   "psrlq       $24,        %%mm1   \n"
 
391
   "punpcklbw   %%mm7,      %%mm1   # mm1 =( v4, v5, v6, v7)    \n"
 
392
   "paddw       %%mm1,      %%mm2   \n"
 
393
   "paddw       %%mm1,      %%mm3   \n"
 
394
   "paddw       %%mm1,      %%mm3   \n"
 
395
   "                                \n"
 
396
   "movq        %%mm0,      %%mm1   \n"
 
397
   "psrlq       $32,        %%mm1   \n"
 
398
   "punpcklbw   %%mm7,      %%mm1   # mm1 =( v5, v6, v7, v8)    \n"
 
399
   "paddw       %%mm1,      %%mm2   \n"
 
400
   "psllw       $2,         %%mm1   \n"
 
401
   "paddw       %%mm1,      %%mm3   \n"
 
402
   "                                # Now last part for last 4 pix \n"
 
403
   "                                # \n"
 
404
   "movq        %%mm0,      %%mm1   \n"
 
405
   "punpckhbw   %%mm7,      %%mm1   # mm1 = ( v5, v6, v7, v8)      \n"
 
406
   "                                \n"
 
407
   "psrlq       $16,        %%mm1   \n"
 
408
   "por         %%mm6,      %%mm1   # mm1 =( v6, v7, v8, p9 )\n"
 
409
   "                                \n"
 
410
   "paddw       %%mm1,      %%mm3   \n"
 
411
   "paddw       %%mm1,      %%mm3   \n"
 
412
   "                                \n"
 
413
   "pshufw      $0xf9,%%mm1,%%mm1   # mm1 =( v7, v8, p9, p9)\n"
 
414
   "paddw       %%mm1,      %%mm3   \n"
 
415
   "paddw       %%mm1,      %%mm3   \n"
 
416
   "                                \n"
 
417
   "pshufw      $0xf9,%%mm1,%%mm1   # mm1 =( v8, p9, p9, p9)\n"
 
418
   "paddw       %%mm1,      %%mm3   \n"
 
419
   "                                \n"
 
420
   "pshufw      $0xf9,%%mm1,%%mm1   # mm1 =( p9, p9, p9, p9)\n"
 
421
   "paddw       %%mm1,      %%mm3   \n"
 
422
 
 
423
   "psrlw       $4,         %%mm2   \n"
 
424
   "psrlw       $4,         %%mm3   \n"
 
425
   "packuswb    %%mm3,      %%mm2   \n"
 
426
   "movq        %%mm2,      1(%0)   \n"
 
427
 
 
428
    : : "r"(p_v), "r"(i_p0), "r"(i_p9) : "memory" );
 
429
 
 
430
#if 0
 
431
    for( i = 1; i < 9; i++ )
 
432
    {
 
433
        v[i] = p_v[i]; /* save 8 pix that will be modified */
 
434
    }
 
435
 
 
436
    p_v[1] = ( 6 * i_p0                        + 4 * v[1]
 
437
                + 2 *( v[2] + v[3]) + v[4] + v[5]) >> 4;
 
438
 
 
439
    p_v[2] = ( 4 * i_p0    + 2 * v[1]          + 4 * v[2]
 
440
                + 2 *( v[3] + v[4]) + v[5] + v[6]) >> 4;
 
441
 
 
442
    p_v[3] = ( 2 * i_p0    + 2 * (v[1] + v[2]) + 4 * v[3]
 
443
                + 2 *( v[4] + v[5]) + v[6] + v[7]) >> 4;
 
444
 
 
445
    p_v[4] = ( i_p0 + v[1] + 2 * (v[2] + v[3]) + 4 * v[4]
 
446
                + 2 *( v[5] + v[6]) + v[7] + v[8]) >> 4;
 
447
 
 
448
    p_v[5] = ( v[1] + v[2] + 2 * (v[3] + v[4]) + 4 * v[5]
 
449
                + 2 *( v[6] + v[7]) + v[8] + i_p9) >> 4;
 
450
 
 
451
    p_v[6] = ( v[2] + v[3] + 2 * (v[4] + v[5]) + 4 * v[6]
 
452
            + 2 *( v[7] + v[8]) + 2 * i_p9) >> 4;
 
453
 
 
454
    p_v[7] = ( v[3] + v[4] + 2 * (v[5] + v[6]) + 4 * v[7]
 
455
                + 2 * v[8] + 4 * i_p9) >> 4;
 
456
 
 
457
    p_v[8] = ( v[4] + v[5] + 2 * (v[6] + v[7]) + 4 * v[8]
 
458
                                    + 6 * i_p9) >> 4;
 
459
#endif
 
460
 
 
461
}
 
462
 
 
463
 
 
464
 
 
465
/*****************************************************************************/
 
466
/*---------------------------------------------------------------------------*/
 
467
/*                                                                           */
 
468
/*    ---------- filter Vertical lines so follow horizontal edges --------   */
 
469
/*                                                                           */
 
470
/*---------------------------------------------------------------------------*/
 
471
/*****************************************************************************/
 
472
 
 
473
void E_( pp_deblock_V )( uint8_t *p_plane,
 
474
                         int i_width, int i_height, int i_stride,
 
475
                         QT_STORE_T *p_QP_store, int i_QP_stride,
 
476
                         int b_chroma )
 
477
{
 
478
    int x, y, i;
 
479
    uint8_t *p_v;
 
480
    int i_QP_scale; /* use to do ( ? >> i_QP_scale ) */
 
481
    int i_QP;
 
482
 
 
483
    uint8_t i_v[10];
 
484
 
 
485
    i_QP_scale = b_chroma ? 5 : 4 ;
 
486
 
 
487
    for( y = 8; y < i_height - 4; y += 8 )
 
488
    {
 
489
        p_v = p_plane + ( y - 5 )* i_stride;
 
490
        for( x = 0; x < i_width; x++ )
 
491
        {
 
492
            /* First get  10 vert pix to use them without i_stride */
 
493
            for( i = 0; i < 10; i++ )
 
494
            {
 
495
                i_v[i] = p_v[i*i_stride + x];
 
496
            }
 
497
 
 
498
            i_QP = p_QP_store[(y>>i_QP_scale)*i_QP_stride+
 
499
                                (x>>i_QP_scale)];
 
500
            /* XXX QP is for v5 */
 
501
            if( pp_deblock_isDC_mode( i_v ) )
 
502
            {
 
503
                if( pp_deblock_isMinMaxOk( i_v, i_QP ) )
 
504
                {
 
505
                    pp_deblock_DCMode( i_v, i_QP );
 
506
                }
 
507
            }
 
508
            else
 
509
            {
 
510
                pp_deblock_DefaultMode( i_v, i_stride, i_QP );
 
511
 
 
512
            }
 
513
            /* Copy back, XXX only 1-8 were modified */
 
514
            for( i = 1; i < 9; i++ )
 
515
            {
 
516
                p_v[i*i_stride + x] = i_v[i];
 
517
            }
 
518
 
 
519
        }
 
520
    }
 
521
 
 
522
    return;
 
523
}
 
524
/*****************************************************************************/
 
525
/*---------------------------------------------------------------------------*/
 
526
/*                                                                           */
 
527
/*     --------- filter Horizontal lines so follow vertical edges --------   */
 
528
/*                                                                           */
 
529
/*---------------------------------------------------------------------------*/
 
530
/*****************************************************************************/
 
531
 
 
532
void E_( pp_deblock_H )( uint8_t *p_plane,
 
533
                         int i_width, int i_height, int i_stride,
 
534
                         QT_STORE_T *p_QP_store, int i_QP_stride,
 
535
                            int b_chroma )
 
536
{
 
537
    int x, y;
 
538
    uint8_t *p_v;
 
539
    int i_QP_scale;
 
540
    int i_QP;
 
541
 
 
542
    i_QP_scale = b_chroma ? 5 : 4 ;
 
543
 
 
544
    for( y = 0; y < i_height; y++ )
 
545
    {
 
546
        p_v = p_plane + y * i_stride - 5;
 
547
        for( x = 8; x < i_width - 4; x += 8 )
 
548
        {
 
549
            /* p_v point 5 pix before a block boundary */
 
550
            /* XXX QP is for v5 */
 
551
            i_QP = p_QP_store[(y>>i_QP_scale)*i_QP_stride+
 
552
                                 (x>>i_QP_scale)];
 
553
            if( pp_deblock_isDC_mode( p_v + x ) )
 
554
            {
 
555
                if( pp_deblock_isMinMaxOk( p_v+ x, i_QP ) )
 
556
                {
 
557
                    pp_deblock_DCMode( p_v+x, i_QP );
 
558
                }
 
559
            }
 
560
            else
 
561
            {
 
562
                pp_deblock_DefaultMode( p_v+x, i_stride, i_QP );
 
563
            }
 
564
        }
 
565
    }
 
566
 
 
567
    return;
 
568
}
 
569
 
 
570
 
 
571
/*****************************************************************************
 
572
 *
 
573
 * Internals functions common to pp_Dering_Y pp_Dering_C
 
574
 *
 
575
 *****************************************************************************/
 
576
 
 
577
static inline void pp_dering_MinMax( uint8_t *p_block, int i_stride,
 
578
                                     int *pi_min, int *pi_max )
 
579
{
 
580
 
 
581
    /* First we will extract min/max for each pix on vertical line
 
582
        and next extract global min/max */
 
583
    __asm__ __volatile__(
 
584
 
 
585
    "leal   (%2,%3),        %%eax       \n"
 
586
    "movq   (%2),           %%mm0 #load line \n"
 
587
    "movq   %%mm0,          %%mm1       \n"
 
588
 
 
589
    MMXEXT_GET_LMINMAX( (%%eax),        %%mm0, %%mm1, %%mm7 )
 
590
    MMXEXT_GET_LMINMAX( (%%eax, %3),    %%mm0, %%mm1, %%mm7 )
 
591
    MMXEXT_GET_LMINMAX( (%%eax, %3,2), %%mm0, %%mm1, %%mm7 )
 
592
    MMXEXT_GET_LMINMAX( (%2, %3, 4),   %%mm0, %%mm1, %%mm7 )
 
593
    "leal   (%%eax,%3,4),  %%eax       \n"
 
594
 
 
595
    MMXEXT_GET_LMINMAX( (%%eax),        %%mm0, %%mm1, %%mm7 )
 
596
    MMXEXT_GET_LMINMAX( (%%eax, %3),    %%mm0, %%mm1, %%mm7 )
 
597
    MMXEXT_GET_LMINMAX( (%%eax, %3,2), %%mm0, %%mm1, %%mm7 )
 
598
    MMXEXT_GET_PMIN( %%mm0, %%mm7 )
 
599
    MMXEXT_GET_PMAX( %%mm1, %%mm7 )
 
600
    "movd   %%mm0,  %%eax               \n"
 
601
    "andl   $255,   %%eax               \n"
 
602
    "movl   %%eax,  (%0)                \n"
 
603
    "movd   %%mm1,  %%eax               \n"
 
604
    "andl   $255,   %%eax               \n"
 
605
    "movl   %%eax,  (%1)                \n"
 
606
 
 
607
     : : "r"(pi_min), "r"(pi_max), "r"(p_block), "r"(i_stride) : "%eax", "memory" );
 
608
#if 0
 
609
 
 
610
    i_min = 255; i_max = 0;
 
611
 
 
612
    for( y = 0; y < 8; y++ )
 
613
    {
 
614
        for( x = 0; x < 8; x++ )
 
615
        {
 
616
            if( i_min > p_block[x] ) i_min = p_block[x];
 
617
            if( i_max < p_block[x] ) i_max = p_block[x];
 
618
        }
 
619
        p_block += i_stride;
 
620
    }
 
621
 
 
622
    *pi_min = i_min;
 
623
    *pi_max = i_max;
 
624
#endif
 
625
}
 
626
 
 
627
 
 
628
static inline void pp_dering_BinIndex( uint8_t  *p_block, int i_stride,
 
629
                                       int i_thr, uint32_t *p_bin )
 
630
{
 
631
    int y;
 
632
    uint32_t i_bin;
 
633
 
 
634
    /* first create mm7 with all bytes set to thr and mm6 = 0 */
 
635
    __asm__ __volatile__(
 
636
   "movl        %0,     %%eax   \n"
 
637
   "movb        %%al,   %%ah    \n"
 
638
   "movd        %%eax,  %%mm7   \n"
 
639
   "pshufw      $0x00,  %%mm7,  %%mm7   \n"
 
640
   "pxor        %%mm6,  %%mm6   \n"
 
641
    : : "r"(i_thr) : "%eax" );
 
642
 
 
643
    for( y = 0; y < 10; y++ )
 
644
    {
 
645
        __asm__ __volatile__(
 
646
       "movq        (%1),       %%mm0   \n"
 
647
       "psubusb     %%mm7,      %%mm0   \n" /* sat makes that x <= thr --> 0 */
 
648
       "pcmpeqb     %%mm6,      %%mm0   \n" /* p_block <= i_thr ? -1 : 0 */
 
649
       "pmovmskb    %%mm0,      %0      \n" /* i_bin msb of each bytes */
 
650
         : "=r"(i_bin) :"r"(p_block) );
 
651
        /* Now last 2 tests */
 
652
        if( p_block[8] <= i_thr ) i_bin |= 1 << 8;
 
653
        if( p_block[9] <= i_thr ) i_bin |= 1 << 9;
 
654
 
 
655
        i_bin |= (~i_bin) << 16;  /* for detect three 1 or three 0*/
 
656
        *p_bin = ( i_bin >> 1 )&&( i_bin )&&( i_bin << 1 );
 
657
 
 
658
        p_block += i_stride;
 
659
        p_bin++;
 
660
    }
 
661
 
 
662
#if 0
 
663
    int x, y;
 
664
    for( y = 0; y < 10; y++ )
 
665
    {
 
666
        i_bin = 0;
 
667
        for( x = 0; x < 10; x++ )
 
668
        {
 
669
            if( p_block[x] > i_thr )
 
670
            {
 
671
                i_bin |= 1 << x;
 
672
            }
 
673
        }
 
674
        i_bin |= (~i_bin) << 16;  /* for detect also three 0 */
 
675
        *p_bin = i_bin&( i_bin >> 1 )&( i_bin << 1 );
 
676
        *p_bin = i_bin;
 
677
        p_block += i_stride;
 
678
        p_bin++;
 
679
    }
 
680
#endif
 
681
 
 
682
}
 
683
 
 
684
static inline void pp_dering_Filter( uint8_t  *p_block, int i_stride,
 
685
                                     uint32_t *p_bin,
 
686
                                     int i_QP )
 
687
{
 
688
    int x, y;
 
689
    uint32_t i_bin;
 
690
    uint8_t i_flt[8][8];
 
691
    int i_f;
 
692
    uint8_t *p_sav;
 
693
    int i_QP_2;
 
694
 
 
695
    p_sav = p_block;
 
696
    i_QP_2 = i_QP >> 1;
 
697
 
 
698
    for( y = 0; y < 8; y++ )
 
699
    {
 
700
        i_bin = p_bin[y] & p_bin[y+1] & p_bin[y+2]; /* To be optimised */
 
701
        i_bin |= i_bin >> 16; /* detect 0 or 1 */
 
702
 
 
703
        for( x = 0; x < 8; x++ )
 
704
        {
 
705
            if( i_bin&0x02 ) /* 0x02 since 10 index but want 1-9 */
 
706
            {
 
707
                /* apply dering */
 
708
                /* 1 2 1
 
709
                   2 4 2   + (8)
 
710
                   1 2 1 */
 
711
                i_f =   p_block[x - i_stride - 1] +
 
712
                      ( p_block[x - i_stride    ] << 1)+
 
713
                        p_block[x - i_stride + 1] +
 
714
 
 
715
                      ( p_block[x - 1] << 1 )+
 
716
                      ( p_block[x    ] << 2 )+
 
717
                      ( p_block[x + 1] << 1 )+
 
718
 
 
719
                        p_block[x + i_stride - 1] +
 
720
                      ( p_block[x + i_stride    ] << 1 ) +
 
721
                        p_block[x + i_stride + 1];
 
722
 
 
723
                i_flt[y][x] = ( 8 + i_f ) >> 4;
 
724
            }
 
725
            else
 
726
            {
 
727
                i_flt[y][x] = p_block[x];
 
728
            }
 
729
 
 
730
            i_bin >>= 1;
 
731
 
 
732
        }
 
733
        p_block += i_stride;
 
734
    }
 
735
 
 
736
    /* Create mm7 with all bytes  set to QP/2 */
 
737
    __asm__ __volatile__(
 
738
   "movl        %0,     %%eax   \n"
 
739
   "shrl        $1,     %%eax   \n" /* i_QP/2 */
 
740
   "movb        %%al,   %%ah    \n"
 
741
   "movd        %%eax,  %%mm7   \n"
 
742
   "pshufw      $0x00,  %%mm7,  %%mm7   \n"
 
743
    : : "r"(i_QP) : "%eax" );
 
744
 
 
745
    for( y = 0; y < 8; y++ )
 
746
    {
 
747
        /* clamp those values and copy them */
 
748
        __asm__ __volatile__(
 
749
       "movq    (%0),   %%mm0   \n" /* mm0 = i_ftl[y][0] ... i_ftl[y][7] */
 
750
       "movq    (%1),   %%mm1   \n" /* mm1 = p_sav[0] ... p_sav[7] */
 
751
       "movq    %%mm1,  %%mm2   \n"
 
752
       "psubusb %%mm7,  %%mm1   \n" /* mm1 = psav - i_QP/2 ( >= 0 ) */
 
753
       "paddusb %%mm7,  %%mm2   \n" /* mm2 = psav + i_QP/2 ( <= 255 ) */
 
754
       "pmaxub  %%mm1,  %%mm0   \n" /* psav - i_QP/2 <= mm0 */
 
755
       "pminub  %%mm2,  %%mm0   \n" /*                  mm0 <= psav + i_QP/2 */
 
756
       "movq    %%mm0,  (%1)    \n"
 
757
        : :"r"(i_flt[y]), "r"(p_sav) : "memory" );
 
758
 
 
759
        p_sav+= i_stride;
 
760
    }
 
761
}
 
762
 
 
763
 
 
764
/*****************************************************************************/
 
765
/*---------------------------------------------------------------------------*/
 
766
/*                                                                           */
 
767
/*     ----------------- Dering filter on Y and C blocks -----------------   */
 
768
/*                                                                           */
 
769
/*---------------------------------------------------------------------------*/
 
770
/*****************************************************************************/
 
771
 
 
772
void E_( pp_dering_Y )( uint8_t *p_plane,
 
773
                        int i_width, int i_height, int i_stride,
 
774
                        QT_STORE_T *p_QP_store, int i_QP_stride )
 
775
{
 
776
    int x, y, k;
 
777
    int i_max[4], i_min[4], i_range[4];
 
778
    int i_thr[4];
 
779
    int i_max_range, i_kmax;
 
780
    uint32_t i_bin[4][10];
 
781
    uint8_t  *p_block[4];
 
782
    QT_STORE_T *p_QP;
 
783
 
 
784
    /* We process 4 blocks/loop*/
 
785
    for( y = 8; y < i_height-8; y += 16 )
 
786
    {
 
787
        /* +---+
 
788
           |0|1|
 
789
           +-+-+   :))
 
790
           |2|3|
 
791
           +-+-+ */
 
792
 
 
793
        p_block[0] = p_plane + y * i_stride + 8;
 
794
        p_block[1] = p_block[0] + 8;
 
795
        p_block[2] = p_block[0] + ( i_stride << 3 );
 
796
        p_block[3] = p_block[2] + 8;
 
797
 
 
798
        for( x = 8; x < i_width-8; x += 16 )
 
799
        {
 
800
            /* 1: Calculate threshold */
 
801
            /* Calculate max/min for each block */
 
802
            pp_dering_MinMax( p_block[0], i_stride, &i_min[0], &i_max[0] );
 
803
            pp_dering_MinMax( p_block[1], i_stride, &i_min[1], &i_max[1] );
 
804
            pp_dering_MinMax( p_block[2], i_stride, &i_min[2], &i_max[2] );
 
805
            pp_dering_MinMax( p_block[3], i_stride, &i_min[3], &i_max[3] );
 
806
            /* Calculate range, max_range and thr */
 
807
            i_max_range = 0; i_kmax = 0;
 
808
            for( k = 0; k < 4; k++ )
 
809
            {
 
810
                i_range[k] = i_max[k] - i_min[k];
 
811
                i_thr[k] = ( i_max[k] + i_min[k] + 1 )/2;
 
812
                if( i_max_range < i_max[k])
 
813
                {
 
814
                    i_max_range = i_max[k];
 
815
                    i_kmax = k;
 
816
                }
 
817
            }
 
818
            /* Now rearrange thr */
 
819
            if(  i_max_range > 64 )
 
820
            {
 
821
                for( k = 1; k < 5; k++ )
 
822
                {
 
823
                    if( i_range[k] < 16 )
 
824
                    {
 
825
                        i_thr[k] = 0;
 
826
                    }
 
827
                    else
 
828
                    if( i_range[k] < 32 )
 
829
                    {
 
830
                        i_thr[k] = i_thr[i_kmax];
 
831
                    }
 
832
                }
 
833
            }
 
834
            else
 
835
            {
 
836
                for( k = 1; k < 5; k++ )
 
837
                {
 
838
                    if( i_range[k] < 16 )
 
839
                    {
 
840
                        i_thr[k] = 0;
 
841
                    }
 
842
                }
 
843
            }
 
844
            /* 2: Index acquisition 10x10 ! so " -i_stride - 1"*/
 
845
            pp_dering_BinIndex( p_block[0] - i_stride - 1, i_stride,
 
846
                                i_thr[0], i_bin[0] );
 
847
            pp_dering_BinIndex( p_block[1] - i_stride - 1, i_stride,
 
848
                                i_thr[1], i_bin[1] );
 
849
            pp_dering_BinIndex( p_block[2] - i_stride - 1, i_stride,
 
850
                                i_thr[2], i_bin[2] );
 
851
            pp_dering_BinIndex( p_block[3] - i_stride - 1, i_stride,
 
852
                                i_thr[3], i_bin[3] );
 
853
 
 
854
 
 
855
            /* 3: adaptive smoothing */
 
856
            /* since we begin at (8,8) QP can be different for each block */
 
857
            p_QP = &( p_QP_store[( y >> 4) * i_QP_stride + (x >> 4)] );
 
858
 
 
859
            pp_dering_Filter( p_block[0], i_stride,
 
860
                              i_bin[0], p_QP[0] );
 
861
 
 
862
            pp_dering_Filter( p_block[1], i_stride,
 
863
                              i_bin[1], p_QP[1] );
 
864
 
 
865
            pp_dering_Filter( p_block[2], i_stride,
 
866
                              i_bin[2], p_QP[i_QP_stride] );
 
867
 
 
868
            pp_dering_Filter( p_block[3], i_stride,
 
869
                              i_bin[3], p_QP[i_QP_stride+1] );
 
870
 
 
871
            p_block[0] += 8;
 
872
            p_block[1] += 8;
 
873
            p_block[2] += 8;
 
874
            p_block[3] += 8;
 
875
        }
 
876
    }
 
877
}
 
878
 
 
879
void E_( pp_dering_C )( uint8_t *p_plane,
 
880
                        int i_width, int i_height, int i_stride,
 
881
                        QT_STORE_T *p_QP_store, int i_QP_stride )
 
882
{
 
883
    int x, y;
 
884
    int i_max, i_min;
 
885
    int i_thr;
 
886
    uint32_t i_bin[10];
 
887
 
 
888
    uint8_t *p_block;
 
889
 
 
890
    for( y = 8; y < i_height-8; y += 8 )
 
891
    {
 
892
 
 
893
        p_block = p_plane + y * i_stride + 8;
 
894
        for( x = 8; x < i_width-8; x += 8 )
 
895
        {
 
896
 
 
897
            /* 1: Calculate threshold */
 
898
            /* Calculate max/min for each block */
 
899
            pp_dering_MinMax( p_block, i_stride,
 
900
                              &i_min, &i_max );
 
901
            /* Calculate thr*/
 
902
            i_thr = ( i_max + i_min + 1 )/2;
 
903
 
 
904
            /* 2: Index acquisition 10x10 */
 
905
            /* point on 10x10 in wich we have our 8x8 block */
 
906
            pp_dering_BinIndex( p_block - i_stride -1, i_stride,
 
907
                                i_thr,
 
908
                                i_bin );
 
909
 
 
910
            /* 3: adaptive smoothing */
 
911
            pp_dering_Filter( p_block, i_stride,
 
912
                              i_bin,
 
913
                              p_QP_store[(y>>5)*i_QP_stride+ (x>>5)]);
 
914
            p_block += 8;
 
915
        }
 
916
    }
 
917
}