vp3dsp.c 8.7 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
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

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

48
    int i;
49

50 51 52 53
    /* 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] ) {
54 55 56 57
            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]);
58

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

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

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

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

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

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

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

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

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

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

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

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

97
    ip = input;
98 99 100

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

104 105 106 107
            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]);
108

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

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

Michael Niedermayer's avatar
Michael Niedermayer committed
115 116 117 118 119 120 121
            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;
            }
122

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

217 218 219 220 221 222 223
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);
}
224

David Conrad's avatar
David Conrad committed
225
void ff_vp3_idct_dc_add_c(uint8_t *dest/*align 8*/, int line_size, const DCTELEM *block/*align 16*/){
226
    int i, dc = (block[0] + 15) >> 5;
David Conrad's avatar
David Conrad committed
227 228

    for(i = 0; i < 8; i++){
229 230 231 232 233 234 235 236
        dest[0] = av_clip_uint8(dest[0] + dc);
        dest[1] = av_clip_uint8(dest[1] + dc);
        dest[2] = av_clip_uint8(dest[2] + dc);
        dest[3] = av_clip_uint8(dest[3] + dc);
        dest[4] = av_clip_uint8(dest[4] + dc);
        dest[5] = av_clip_uint8(dest[5] + dc);
        dest[6] = av_clip_uint8(dest[6] + dc);
        dest[7] = av_clip_uint8(dest[7] + dc);
David Conrad's avatar
David Conrad committed
237 238 239 240
        dest += line_size;
    }
}

241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
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);
    }
}