lossless_videodsp: move shared functions from huffyuvdsp
[ffmpeg.git] / libavcodec / lossless_videodsp.c
1 /*
2  * Lossless video DSP utils
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * 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  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * 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 #include "avcodec.h"
21 #include "lossless_videodsp.h"
22 #include "libavcodec/mathops.h"
23
24 // 0x7f7f7f7f or 0x7f7f7f7f7f7f7f7f or whatever, depending on the cpu's native arithmetic size
25 #define pb_7f (~0UL / 255 * 0x7f)
26 #define pb_80 (~0UL / 255 * 0x80)
27
28 static void add_bytes_c(uint8_t *dst, uint8_t *src, intptr_t w)
29 {
30     long i;
31
32     for (i = 0; i <= w - (int) sizeof(long); i += sizeof(long)) {
33         long a = *(long *) (src + i);
34         long b = *(long *) (dst + i);
35         *(long *) (dst + i) = ((a & pb_7f) + (b & pb_7f)) ^ ((a ^ b) & pb_80);
36     }
37     for (; i < w; i++)
38         dst[i + 0] += src[i + 0];
39 }
40
41 static void add_median_pred_c(uint8_t *dst, const uint8_t *src1,
42                               const uint8_t *diff, intptr_t w,
43                               int *left, int *left_top)
44 {
45     int i;
46     uint8_t l, lt;
47
48     l  = *left;
49     lt = *left_top;
50
51     for (i = 0; i < w; i++) {
52         l      = mid_pred(l, src1[i], (l + src1[i] - lt) & 0xFF) + diff[i];
53         lt     = src1[i];
54         dst[i] = l;
55     }
56
57     *left     = l;
58     *left_top = lt;
59 }
60
61 static int add_left_pred_c(uint8_t *dst, const uint8_t *src, intptr_t w,
62                            int acc)
63 {
64     int i;
65
66     for (i = 0; i < w - 1; i++) {
67         acc   += src[i];
68         dst[i] = acc;
69         i++;
70         acc   += src[i];
71         dst[i] = acc;
72     }
73
74     for (; i < w; i++) {
75         acc   += src[i];
76         dst[i] = acc;
77     }
78
79     return acc;
80 }
81
82 static void add_int16_c(uint16_t *dst, const uint16_t *src, unsigned mask, int w){
83     long i;
84     unsigned long pw_lsb = (mask >> 1) * 0x0001000100010001ULL;
85     unsigned long pw_msb = pw_lsb +  0x0001000100010001ULL;
86     for (i = 0; i <= w - (int)sizeof(long)/2; i += sizeof(long)/2) {
87         long a = *(long*)(src+i);
88         long b = *(long*)(dst+i);
89         *(long*)(dst+i) = ((a&pw_lsb) + (b&pw_lsb)) ^ ((a^b)&pw_msb);
90     }
91     for(; i<w; i++)
92         dst[i] = (dst[i] + src[i]) & mask;
93 }
94
95 static void diff_int16_c(uint16_t *dst, const uint16_t *src1, const uint16_t *src2, unsigned mask, int w){
96     long i;
97 #if !HAVE_FAST_UNALIGNED
98     if((long)src2 & (sizeof(long)-1)){
99         for(i=0; i+3<w; i+=4){
100             dst[i+0] = (src1[i+0]-src2[i+0]) & mask;
101             dst[i+1] = (src1[i+1]-src2[i+1]) & mask;
102             dst[i+2] = (src1[i+2]-src2[i+2]) & mask;
103             dst[i+3] = (src1[i+3]-src2[i+3]) & mask;
104         }
105     }else
106 #endif
107     {
108         unsigned long pw_lsb = (mask >> 1) * 0x0001000100010001ULL;
109         unsigned long pw_msb = pw_lsb +  0x0001000100010001ULL;
110
111         for (i = 0; i <= w - (int)sizeof(long)/2; i += sizeof(long)/2) {
112             long a = *(long*)(src1+i);
113             long b = *(long*)(src2+i);
114             *(long*)(dst+i) = ((a|pw_msb) - (b&pw_lsb)) ^ ((a^b^pw_msb)&pw_msb);
115         }
116     }
117     for (; i<w; i++)
118         dst[i] = (src1[i] - src2[i]) & mask;
119 }
120
121 static void add_hfyu_median_pred_int16_c(uint16_t *dst, const uint16_t *src, const uint16_t *diff, unsigned mask, int w, int *left, int *left_top){
122     int i;
123     uint16_t l, lt;
124
125     l  = *left;
126     lt = *left_top;
127
128     for(i=0; i<w; i++){
129         l  = (mid_pred(l, src[i], (l + src[i] - lt) & mask) + diff[i]) & mask;
130         lt = src[i];
131         dst[i] = l;
132     }
133
134     *left     = l;
135     *left_top = lt;
136 }
137
138 static void sub_hfyu_median_pred_int16_c(uint16_t *dst, const uint16_t *src1, const uint16_t *src2, unsigned mask, int w, int *left, int *left_top){
139     int i;
140     uint16_t l, lt;
141
142     l  = *left;
143     lt = *left_top;
144
145     for(i=0; i<w; i++){
146         const int pred = mid_pred(l, src1[i], (l + src1[i] - lt) & mask);
147         lt = src1[i];
148         l  = src2[i];
149         dst[i] = (l - pred) & mask;
150     }
151
152     *left     = l;
153     *left_top = lt;
154 }
155
156 static int add_hfyu_left_pred_int16_c(uint16_t *dst, const uint16_t *src, unsigned mask, int w, unsigned acc){
157     int i;
158
159     for(i=0; i<w-1; i++){
160         acc+= src[i];
161         dst[i]= acc &= mask;
162         i++;
163         acc+= src[i];
164         dst[i]= acc &= mask;
165     }
166
167     for(; i<w; i++){
168         acc+= src[i];
169         dst[i]= acc &= mask;
170     }
171
172     return acc;
173 }
174
175
176 void ff_llviddsp_init(LLVidDSPContext *c, AVCodecContext *avctx)
177 {
178     c->add_bytes                  = add_bytes_c;
179     c->add_median_pred            = add_median_pred_c;
180     c->add_left_pred              = add_left_pred_c;
181
182     c->add_int16 = add_int16_c;
183     c->diff_int16= diff_int16_c;
184     c->add_hfyu_left_pred_int16   = add_hfyu_left_pred_int16_c;
185     c->add_hfyu_median_pred_int16 = add_hfyu_median_pred_int16_c;
186     c->sub_hfyu_median_pred_int16 = sub_hfyu_median_pred_int16_c;
187
188     if (ARCH_X86)
189         ff_llviddsp_init_x86(c, avctx);
190 }