]> git.sesse.net Git - ffmpeg/blob - libavcodec/mpegvideoencdsp.c
h264: eliminate decode_postinit()
[ffmpeg] / libavcodec / mpegvideoencdsp.c
1 /*
2  * This file is part of Libav.
3  *
4  * Libav is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * Libav is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with Libav; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 #include <assert.h>
20 #include <stdint.h>
21 #include <string.h>
22
23 #include "config.h"
24 #include "libavutil/attributes.h"
25 #include "libavutil/imgutils.h"
26 #include "avcodec.h"
27 #include "me_cmp.h"
28 #include "mpegvideoencdsp.h"
29
30 static int try_8x8basis_c(int16_t rem[64], int16_t weight[64],
31                           int16_t basis[64], int scale)
32 {
33     int i;
34     unsigned int sum = 0;
35
36     for (i = 0; i < 8 * 8; i++) {
37         int b = rem[i] + ((basis[i] * scale +
38                            (1 << (BASIS_SHIFT - RECON_SHIFT - 1))) >>
39                           (BASIS_SHIFT - RECON_SHIFT));
40         int w = weight[i];
41         b >>= RECON_SHIFT;
42         assert(-512 < b && b < 512);
43
44         sum += (w * b) * (w * b) >> 4;
45     }
46     return sum >> 2;
47 }
48
49 static void add_8x8basis_c(int16_t rem[64], int16_t basis[64], int scale)
50 {
51     int i;
52
53     for (i = 0; i < 8 * 8; i++)
54         rem[i] += (basis[i] * scale +
55                    (1 << (BASIS_SHIFT - RECON_SHIFT - 1))) >>
56                   (BASIS_SHIFT - RECON_SHIFT);
57 }
58
59 static int pix_sum_c(uint8_t *pix, int line_size)
60 {
61     int s = 0, i, j;
62
63     for (i = 0; i < 16; i++) {
64         for (j = 0; j < 16; j += 8) {
65             s   += pix[0];
66             s   += pix[1];
67             s   += pix[2];
68             s   += pix[3];
69             s   += pix[4];
70             s   += pix[5];
71             s   += pix[6];
72             s   += pix[7];
73             pix += 8;
74         }
75         pix += line_size - 16;
76     }
77     return s;
78 }
79
80 static int pix_norm1_c(uint8_t *pix, int line_size)
81 {
82     int s = 0, i, j;
83     uint32_t *sq = ff_square_tab + 256;
84
85     for (i = 0; i < 16; i++) {
86         for (j = 0; j < 16; j += 8) {
87 #if 0
88             s += sq[pix[0]];
89             s += sq[pix[1]];
90             s += sq[pix[2]];
91             s += sq[pix[3]];
92             s += sq[pix[4]];
93             s += sq[pix[5]];
94             s += sq[pix[6]];
95             s += sq[pix[7]];
96 #else
97 #if HAVE_FAST_64BIT
98             register uint64_t x = *(uint64_t *) pix;
99             s += sq[x         & 0xff];
100             s += sq[(x >>  8) & 0xff];
101             s += sq[(x >> 16) & 0xff];
102             s += sq[(x >> 24) & 0xff];
103             s += sq[(x >> 32) & 0xff];
104             s += sq[(x >> 40) & 0xff];
105             s += sq[(x >> 48) & 0xff];
106             s += sq[(x >> 56) & 0xff];
107 #else
108             register uint32_t x = *(uint32_t *) pix;
109             s += sq[x         & 0xff];
110             s += sq[(x >>  8) & 0xff];
111             s += sq[(x >> 16) & 0xff];
112             s += sq[(x >> 24) & 0xff];
113             x  = *(uint32_t *) (pix + 4);
114             s += sq[x         & 0xff];
115             s += sq[(x >>  8) & 0xff];
116             s += sq[(x >> 16) & 0xff];
117             s += sq[(x >> 24) & 0xff];
118 #endif
119 #endif
120             pix += 8;
121         }
122         pix += line_size - 16;
123     }
124     return s;
125 }
126
127 /* draw the edges of width 'w' of an image of size width, height */
128 // FIXME: Check that this is OK for MPEG-4 interlaced.
129 static void draw_edges_8_c(uint8_t *buf, int wrap, int width, int height,
130                            int w, int h, int sides)
131 {
132     uint8_t *ptr = buf, *last_line;
133     int i;
134
135     /* left and right */
136     for (i = 0; i < height; i++) {
137         memset(ptr - w, ptr[0], w);
138         memset(ptr + width, ptr[width - 1], w);
139         ptr += wrap;
140     }
141
142     /* top and bottom + corners */
143     buf -= w;
144     last_line = buf + (height - 1) * wrap;
145     if (sides & EDGE_TOP)
146         for (i = 0; i < h; i++)
147             // top
148             memcpy(buf - (i + 1) * wrap, buf, width + w + w);
149     if (sides & EDGE_BOTTOM)
150         for (i = 0; i < h; i++)
151             // bottom
152             memcpy(last_line + (i + 1) * wrap, last_line, width + w + w);
153 }
154
155 /* 2x2 -> 1x1 */
156 static void shrink22(uint8_t *dst, int dst_wrap,
157                      const uint8_t *src, int src_wrap,
158                      int width, int height)
159 {
160     int w;
161     const uint8_t *s1, *s2;
162     uint8_t *d;
163
164     for (; height > 0; height--) {
165         s1 = src;
166         s2 = s1 + src_wrap;
167         d = dst;
168         for (w = width; w >= 4; w -= 4) {
169             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
170             d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
171             d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
172             d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
173             s1 += 8;
174             s2 += 8;
175             d += 4;
176         }
177         for (; w > 0; w--) {
178             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
179             s1 += 2;
180             s2 += 2;
181             d++;
182         }
183         src += 2 * src_wrap;
184         dst += dst_wrap;
185     }
186 }
187
188 /* 4x4 -> 1x1 */
189 static void shrink44(uint8_t *dst, int dst_wrap,
190                      const uint8_t *src, int src_wrap,
191                      int width, int height)
192 {
193     int w;
194     const uint8_t *s1, *s2, *s3, *s4;
195     uint8_t *d;
196
197     for (; height > 0; height--) {
198         s1 = src;
199         s2 = s1 + src_wrap;
200         s3 = s2 + src_wrap;
201         s4 = s3 + src_wrap;
202         d = dst;
203         for (w = width; w > 0; w--) {
204             d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
205                     s2[0] + s2[1] + s2[2] + s2[3] +
206                     s3[0] + s3[1] + s3[2] + s3[3] +
207                     s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
208             s1 += 4;
209             s2 += 4;
210             s3 += 4;
211             s4 += 4;
212             d++;
213         }
214         src += 4 * src_wrap;
215         dst += dst_wrap;
216     }
217 }
218
219 /* 8x8 -> 1x1 */
220 static void shrink88(uint8_t *dst, int dst_wrap,
221                      const uint8_t *src, int src_wrap,
222                      int width, int height)
223 {
224     int w, i;
225
226     for (; height > 0; height--) {
227         for(w = width;w > 0; w--) {
228             int tmp = 0;
229             for (i = 0; i < 8; i++) {
230                 tmp += src[0] + src[1] + src[2] + src[3] +
231                        src[4] + src[5] + src[6] + src[7];
232                 src += src_wrap;
233             }
234             *(dst++) = (tmp + 32) >> 6;
235             src += 8 - 8 * src_wrap;
236         }
237         src += 8 * src_wrap - 8 * width;
238         dst += dst_wrap - width;
239     }
240 }
241
242 av_cold void ff_mpegvideoencdsp_init(MpegvideoEncDSPContext *c,
243                                      AVCodecContext *avctx)
244 {
245     c->try_8x8basis = try_8x8basis_c;
246     c->add_8x8basis = add_8x8basis_c;
247
248     c->shrink[0] = av_image_copy_plane;
249     c->shrink[1] = shrink22;
250     c->shrink[2] = shrink44;
251     c->shrink[3] = shrink88;
252
253     c->pix_sum   = pix_sum_c;
254     c->pix_norm1 = pix_norm1_c;
255
256     c->draw_edges = draw_edges_8_c;
257
258     if (ARCH_ARM)
259         ff_mpegvideoencdsp_init_arm(c, avctx);
260     if (ARCH_PPC)
261         ff_mpegvideoencdsp_init_ppc(c, avctx);
262     if (ARCH_X86)
263         ff_mpegvideoencdsp_init_x86(c, avctx);
264 }