vp3dsp.c 7.93 KB
Newer Older
1 2 3
/*
 * Copyright (C) 2004 the ffmpeg project
 *
4 5 6
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
7 8
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * FFmpeg is distributed in the hope that it will be useful,
12 13 14 15 16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with FFmpeg; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 20 21
 */

/**
22
 * @file libavcodec/vp3dsp.c
23
 * Standard C DSP-oriented functions cribbed from the original VP3
24 25 26 27
 * source code.
 */

#include "avcodec.h"
28
#include "dsputil.h"
29 30 31 32 33 34 35 36 37 38

#define IdctAdjustBeforeShift 8
#define xC1S7 64277
#define xC2S6 60547
#define xC3S5 54491
#define xC4S4 46341
#define xC5S3 36410
#define xC6S2 25080
#define xC7S1 12785

39 40
#define M(a,b) (((a) * (b))>>16)

41
static av_always_inline void idct(uint8_t *dst, int stride, int16_t *input, int type)
42
{
43
    int16_t *ip = input;
44
    uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
45

46 47
    int A, B, C, D, Ad, Bd, Cd, Dd, E, F, G, H;
    int Ed, Gd, Add, Bdd, Fd, Hd;
48

49
    int i;
50

51 52 53 54
    /* Inverse DCT on the rows now */
    for (i = 0; i < 8; i++) {
        /* Check for non-zero values */
        if ( ip[0] | ip[1] | ip[2] | ip[3] | ip[4] | ip[5] | ip[6] | ip[7] ) {
55 56 57 58
            A = M(xC1S7, ip[1]) + M(xC7S1, ip[7]);
            B = M(xC7S1, ip[1]) - M(xC1S7, ip[7]);
            C = M(xC3S5, ip[3]) + M(xC5S3, ip[5]);
            D = M(xC3S5, ip[5]) - M(xC5S3, ip[3]);
59

60 61
            Ad = M(xC4S4, (A - C));
            Bd = M(xC4S4, (B - D));
62

63 64
            Cd = A + C;
            Dd = B + D;
65

66 67
            E = M(xC4S4, (ip[0] + ip[4]));
            F = M(xC4S4, (ip[0] - ip[4]));
68

69 70
            G = M(xC2S6, ip[2]) + M(xC6S2, ip[6]);
            H = M(xC6S2, ip[2]) - M(xC2S6, ip[6]);
71

72 73
            Ed = E - G;
            Gd = E + G;
74

75 76
            Add = F + Ad;
            Bdd = Bd - H;
77

78 79
            Fd = F - Ad;
            Hd = Bd + H;
80 81

            /*  Final sequence of operations over-write original inputs. */
82 83
            ip[0] = Gd + Cd ;
            ip[7] = Gd - Cd ;
84

85 86
            ip[1] = Add + Hd;
            ip[2] = Add - Hd;
87

88 89
            ip[3] = Ed + Dd ;
            ip[4] = Ed - Dd ;
90

91 92
            ip[5] = Fd + Bdd;
            ip[6] = Fd - Bdd;
93 94 95 96
        }

        ip += 8;            /* next row */
    }
97

98
    ip = input;
99 100 101

    for ( i = 0; i < 8; i++) {
        /* Check for non-zero values (bitwise or faster than ||) */
102
        if ( ip[1 * 8] | ip[2 * 8] | ip[3 * 8] |
103 104
             ip[4 * 8] | ip[5 * 8] | ip[6 * 8] | ip[7 * 8] ) {

105 106 107 108
            A = M(xC1S7, ip[1*8]) + M(xC7S1, ip[7*8]);
            B = M(xC7S1, ip[1*8]) - M(xC1S7, ip[7*8]);
            C = M(xC3S5, ip[3*8]) + M(xC5S3, ip[5*8]);
            D = M(xC3S5, ip[5*8]) - M(xC5S3, ip[3*8]);
109

110 111
            Ad = M(xC4S4, (A - C));
            Bd = M(xC4S4, (B - D));
112

113 114
            Cd = A + C;
            Dd = B + D;
115

Michael Niedermayer's avatar
Michael Niedermayer committed
116 117 118 119 120 121 122
            E = M(xC4S4, (ip[0*8] + ip[4*8])) + 8;
            F = M(xC4S4, (ip[0*8] - ip[4*8])) + 8;

            if(type==1){  //HACK
                E += 16*128;
                F += 16*128;
            }
123

124 125
            G = M(xC2S6, ip[2*8]) + M(xC6S2, ip[6*8]);
            H = M(xC6S2, ip[2*8]) - M(xC2S6, ip[6*8]);
126

127 128
            Ed = E - G;
            Gd = E + G;
129

130 131
            Add = F + Ad;
            Bdd = Bd - H;
132

133 134
            Fd = F - Ad;
            Hd = Bd + H;
135 136

            /* Final sequence of operations over-write original inputs. */
137
            if(type==0){
138 139
                ip[0*8] = (Gd + Cd )  >> 4;
                ip[7*8] = (Gd - Cd )  >> 4;
140

141 142
                ip[1*8] = (Add + Hd ) >> 4;
                ip[2*8] = (Add - Hd ) >> 4;
143

144 145
                ip[3*8] = (Ed + Dd )  >> 4;
                ip[4*8] = (Ed - Dd )  >> 4;
146

147 148
                ip[5*8] = (Fd + Bdd ) >> 4;
                ip[6*8] = (Fd - Bdd ) >> 4;
149
            }else if(type==1){
150 151
                dst[0*stride] = cm[(Gd + Cd )  >> 4];
                dst[7*stride] = cm[(Gd - Cd )  >> 4];
152

153 154
                dst[1*stride] = cm[(Add + Hd ) >> 4];
                dst[2*stride] = cm[(Add - Hd ) >> 4];
155

156 157
                dst[3*stride] = cm[(Ed + Dd )  >> 4];
                dst[4*stride] = cm[(Ed - Dd )  >> 4];
158

159 160
                dst[5*stride] = cm[(Fd + Bdd ) >> 4];
                dst[6*stride] = cm[(Fd - Bdd ) >> 4];
161
            }else{
162 163
                dst[0*stride] = cm[dst[0*stride] + ((Gd + Cd )  >> 4)];
                dst[7*stride] = cm[dst[7*stride] + ((Gd - Cd )  >> 4)];
164

165 166
                dst[1*stride] = cm[dst[1*stride] + ((Add + Hd ) >> 4)];
                dst[2*stride] = cm[dst[2*stride] + ((Add - Hd ) >> 4)];
167

168 169
                dst[3*stride] = cm[dst[3*stride] + ((Ed + Dd )  >> 4)];
                dst[4*stride] = cm[dst[4*stride] + ((Ed - Dd )  >> 4)];
170

171 172
                dst[5*stride] = cm[dst[5*stride] + ((Fd + Bdd ) >> 4)];
                dst[6*stride] = cm[dst[6*stride] + ((Fd - Bdd ) >> 4)];
173
            }
174 175

        } else {
176
            if(type==0){
177 178 179 180 181 182
                ip[0*8] =
                ip[1*8] =
                ip[2*8] =
                ip[3*8] =
                ip[4*8] =
                ip[5*8] =
183 184 185 186 187 188 189 190 191 192
                ip[6*8] =
                ip[7*8] = ((xC4S4 * ip[0*8] + (IdctAdjustBeforeShift<<16))>>20);
            }else if(type==1){
                dst[0*stride]=
                dst[1*stride]=
                dst[2*stride]=
                dst[3*stride]=
                dst[4*stride]=
                dst[5*stride]=
                dst[6*stride]=
193
                dst[7*stride]= cm[128 + ((xC4S4 * ip[0*8] + (IdctAdjustBeforeShift<<16))>>20)];
194 195 196 197 198 199 200 201 202 203 204 205 206
            }else{
                if(ip[0*8]){
                    int v= ((xC4S4 * ip[0*8] + (IdctAdjustBeforeShift<<16))>>20);
                    dst[0*stride] = cm[dst[0*stride] + v];
                    dst[1*stride] = cm[dst[1*stride] + v];
                    dst[2*stride] = cm[dst[2*stride] + v];
                    dst[3*stride] = cm[dst[3*stride] + v];
                    dst[4*stride] = cm[dst[4*stride] + v];
                    dst[5*stride] = cm[dst[5*stride] + v];
                    dst[6*stride] = cm[dst[6*stride] + v];
                    dst[7*stride] = cm[dst[7*stride] + v];
                }
            }
207 208 209
        }

        ip++;            /* next column */
210
        dst++;
211 212
    }
}
213 214 215 216

void ff_vp3_idct_c(DCTELEM *block/* align 16*/){
    idct(NULL, 0, block, 0);
}
217

218 219 220 221 222 223 224
void ff_vp3_idct_put_c(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/){
    idct(dest, line_size, block, 1);
}

void ff_vp3_idct_add_c(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/){
    idct(dest, line_size, block, 2);
}
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255

void ff_vp3_v_loop_filter_c(uint8_t *first_pixel, int stride, int *bounding_values)
{
    unsigned char *end;
    int filter_value;
    const int nstride= -stride;

    for (end= first_pixel + 8; first_pixel < end; first_pixel++) {
        filter_value =
            (first_pixel[2 * nstride] - first_pixel[ stride])
         +3*(first_pixel[0          ] - first_pixel[nstride]);
        filter_value = bounding_values[(filter_value + 4) >> 3];
        first_pixel[nstride] = av_clip_uint8(first_pixel[nstride] + filter_value);
        first_pixel[0] = av_clip_uint8(first_pixel[0] - filter_value);
    }
}

void ff_vp3_h_loop_filter_c(uint8_t *first_pixel, int stride, int *bounding_values)
{
    unsigned char *end;
    int filter_value;

    for (end= first_pixel + 8*stride; first_pixel != end; first_pixel += stride) {
        filter_value =
            (first_pixel[-2] - first_pixel[ 1])
         +3*(first_pixel[ 0] - first_pixel[-1]);
        filter_value = bounding_values[(filter_value + 4) >> 3];
        first_pixel[-1] = av_clip_uint8(first_pixel[-1] + filter_value);
        first_pixel[ 0] = av_clip_uint8(first_pixel[ 0] - filter_value);
    }
}