yading@11
|
1 /*
|
yading@11
|
2 * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
|
yading@11
|
3 *
|
yading@11
|
4 * This file is part of FFmpeg.
|
yading@11
|
5 *
|
yading@11
|
6 * FFmpeg is free software; you can redistribute it and/or
|
yading@11
|
7 * modify it under the terms of the GNU Lesser General Public
|
yading@11
|
8 * License as published by the Free Software Foundation; either
|
yading@11
|
9 * version 2.1 of the License, or (at your option) any later version.
|
yading@11
|
10 *
|
yading@11
|
11 * FFmpeg is distributed in the hope that it will be useful,
|
yading@11
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@11
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@11
|
14 * Lesser General Public License for more details.
|
yading@11
|
15 *
|
yading@11
|
16 * You should have received a copy of the GNU Lesser General Public
|
yading@11
|
17 * License along with FFmpeg; if not, write to the Free Software
|
yading@11
|
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@11
|
19 */
|
yading@11
|
20
|
yading@11
|
21 #include "config.h"
|
yading@11
|
22
|
yading@11
|
23 #define _SVID_SOURCE // needed for MAP_ANONYMOUS
|
yading@11
|
24 #define _DARWIN_C_SOURCE // needed for MAP_ANON
|
yading@11
|
25 #include <inttypes.h>
|
yading@11
|
26 #include <math.h>
|
yading@11
|
27 #include <stdio.h>
|
yading@11
|
28 #include <string.h>
|
yading@11
|
29 #if HAVE_SYS_MMAN_H
|
yading@11
|
30 #include <sys/mman.h>
|
yading@11
|
31 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
|
yading@11
|
32 #define MAP_ANONYMOUS MAP_ANON
|
yading@11
|
33 #endif
|
yading@11
|
34 #endif
|
yading@11
|
35 #if HAVE_VIRTUALALLOC
|
yading@11
|
36 #define WIN32_LEAN_AND_MEAN
|
yading@11
|
37 #include <windows.h>
|
yading@11
|
38 #endif
|
yading@11
|
39
|
yading@11
|
40 #include "libavutil/attributes.h"
|
yading@11
|
41 #include "libavutil/avassert.h"
|
yading@11
|
42 #include "libavutil/avutil.h"
|
yading@11
|
43 #include "libavutil/bswap.h"
|
yading@11
|
44 #include "libavutil/cpu.h"
|
yading@11
|
45 #include "libavutil/intreadwrite.h"
|
yading@11
|
46 #include "libavutil/mathematics.h"
|
yading@11
|
47 #include "libavutil/opt.h"
|
yading@11
|
48 #include "libavutil/pixdesc.h"
|
yading@11
|
49 #include "libavutil/x86/asm.h"
|
yading@11
|
50 #include "libavutil/x86/cpu.h"
|
yading@11
|
51 #include "rgb2rgb.h"
|
yading@11
|
52 #include "swscale.h"
|
yading@11
|
53 #include "swscale_internal.h"
|
yading@11
|
54
|
yading@11
|
55 unsigned swscale_version(void)
|
yading@11
|
56 {
|
yading@11
|
57 av_assert0(LIBSWSCALE_VERSION_MICRO >= 100);
|
yading@11
|
58 return LIBSWSCALE_VERSION_INT;
|
yading@11
|
59 }
|
yading@11
|
60
|
yading@11
|
61 const char *swscale_configuration(void)
|
yading@11
|
62 {
|
yading@11
|
63 return FFMPEG_CONFIGURATION;
|
yading@11
|
64 }
|
yading@11
|
65
|
yading@11
|
66 const char *swscale_license(void)
|
yading@11
|
67 {
|
yading@11
|
68 #define LICENSE_PREFIX "libswscale license: "
|
yading@11
|
69 return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
|
yading@11
|
70 }
|
yading@11
|
71
|
yading@11
|
72 #define RET 0xC3 // near return opcode for x86
|
yading@11
|
73
|
yading@11
|
74 typedef struct FormatEntry {
|
yading@11
|
75 int is_supported_in, is_supported_out;
|
yading@11
|
76 } FormatEntry;
|
yading@11
|
77
|
yading@11
|
78 static const FormatEntry format_entries[AV_PIX_FMT_NB] = {
|
yading@11
|
79 [AV_PIX_FMT_YUV420P] = { 1, 1 },
|
yading@11
|
80 [AV_PIX_FMT_YUYV422] = { 1, 1 },
|
yading@11
|
81 [AV_PIX_FMT_RGB24] = { 1, 1 },
|
yading@11
|
82 [AV_PIX_FMT_BGR24] = { 1, 1 },
|
yading@11
|
83 [AV_PIX_FMT_YUV422P] = { 1, 1 },
|
yading@11
|
84 [AV_PIX_FMT_YUV444P] = { 1, 1 },
|
yading@11
|
85 [AV_PIX_FMT_YUV410P] = { 1, 1 },
|
yading@11
|
86 [AV_PIX_FMT_YUV411P] = { 1, 1 },
|
yading@11
|
87 [AV_PIX_FMT_GRAY8] = { 1, 1 },
|
yading@11
|
88 [AV_PIX_FMT_MONOWHITE] = { 1, 1 },
|
yading@11
|
89 [AV_PIX_FMT_MONOBLACK] = { 1, 1 },
|
yading@11
|
90 [AV_PIX_FMT_PAL8] = { 1, 0 },
|
yading@11
|
91 [AV_PIX_FMT_YUVJ420P] = { 1, 1 },
|
yading@11
|
92 [AV_PIX_FMT_YUVJ422P] = { 1, 1 },
|
yading@11
|
93 [AV_PIX_FMT_YUVJ444P] = { 1, 1 },
|
yading@11
|
94 [AV_PIX_FMT_UYVY422] = { 1, 1 },
|
yading@11
|
95 [AV_PIX_FMT_UYYVYY411] = { 0, 0 },
|
yading@11
|
96 [AV_PIX_FMT_BGR8] = { 1, 1 },
|
yading@11
|
97 [AV_PIX_FMT_BGR4] = { 0, 1 },
|
yading@11
|
98 [AV_PIX_FMT_BGR4_BYTE] = { 1, 1 },
|
yading@11
|
99 [AV_PIX_FMT_RGB8] = { 1, 1 },
|
yading@11
|
100 [AV_PIX_FMT_RGB4] = { 0, 1 },
|
yading@11
|
101 [AV_PIX_FMT_RGB4_BYTE] = { 1, 1 },
|
yading@11
|
102 [AV_PIX_FMT_NV12] = { 1, 1 },
|
yading@11
|
103 [AV_PIX_FMT_NV21] = { 1, 1 },
|
yading@11
|
104 [AV_PIX_FMT_ARGB] = { 1, 1 },
|
yading@11
|
105 [AV_PIX_FMT_RGBA] = { 1, 1 },
|
yading@11
|
106 [AV_PIX_FMT_ABGR] = { 1, 1 },
|
yading@11
|
107 [AV_PIX_FMT_BGRA] = { 1, 1 },
|
yading@11
|
108 [AV_PIX_FMT_0RGB] = { 1, 1 },
|
yading@11
|
109 [AV_PIX_FMT_RGB0] = { 1, 1 },
|
yading@11
|
110 [AV_PIX_FMT_0BGR] = { 1, 1 },
|
yading@11
|
111 [AV_PIX_FMT_BGR0] = { 1, 1 },
|
yading@11
|
112 [AV_PIX_FMT_GRAY16BE] = { 1, 1 },
|
yading@11
|
113 [AV_PIX_FMT_GRAY16LE] = { 1, 1 },
|
yading@11
|
114 [AV_PIX_FMT_YUV440P] = { 1, 1 },
|
yading@11
|
115 [AV_PIX_FMT_YUVJ440P] = { 1, 1 },
|
yading@11
|
116 [AV_PIX_FMT_YUVA420P] = { 1, 1 },
|
yading@11
|
117 [AV_PIX_FMT_YUVA422P] = { 1, 1 },
|
yading@11
|
118 [AV_PIX_FMT_YUVA444P] = { 1, 1 },
|
yading@11
|
119 [AV_PIX_FMT_YUVA420P9BE] = { 1, 1 },
|
yading@11
|
120 [AV_PIX_FMT_YUVA420P9LE] = { 1, 1 },
|
yading@11
|
121 [AV_PIX_FMT_YUVA422P9BE] = { 1, 1 },
|
yading@11
|
122 [AV_PIX_FMT_YUVA422P9LE] = { 1, 1 },
|
yading@11
|
123 [AV_PIX_FMT_YUVA444P9BE] = { 1, 1 },
|
yading@11
|
124 [AV_PIX_FMT_YUVA444P9LE] = { 1, 1 },
|
yading@11
|
125 [AV_PIX_FMT_YUVA420P10BE]= { 1, 1 },
|
yading@11
|
126 [AV_PIX_FMT_YUVA420P10LE]= { 1, 1 },
|
yading@11
|
127 [AV_PIX_FMT_YUVA422P10BE]= { 1, 1 },
|
yading@11
|
128 [AV_PIX_FMT_YUVA422P10LE]= { 1, 1 },
|
yading@11
|
129 [AV_PIX_FMT_YUVA444P10BE]= { 1, 1 },
|
yading@11
|
130 [AV_PIX_FMT_YUVA444P10LE]= { 1, 1 },
|
yading@11
|
131 [AV_PIX_FMT_YUVA420P16BE]= { 1, 1 },
|
yading@11
|
132 [AV_PIX_FMT_YUVA420P16LE]= { 1, 1 },
|
yading@11
|
133 [AV_PIX_FMT_YUVA422P16BE]= { 1, 1 },
|
yading@11
|
134 [AV_PIX_FMT_YUVA422P16LE]= { 1, 1 },
|
yading@11
|
135 [AV_PIX_FMT_YUVA444P16BE]= { 1, 1 },
|
yading@11
|
136 [AV_PIX_FMT_YUVA444P16LE]= { 1, 1 },
|
yading@11
|
137 [AV_PIX_FMT_RGB48BE] = { 1, 1 },
|
yading@11
|
138 [AV_PIX_FMT_RGB48LE] = { 1, 1 },
|
yading@11
|
139 [AV_PIX_FMT_RGBA64BE] = { 1, 0 },
|
yading@11
|
140 [AV_PIX_FMT_RGBA64LE] = { 1, 0 },
|
yading@11
|
141 [AV_PIX_FMT_RGB565BE] = { 1, 1 },
|
yading@11
|
142 [AV_PIX_FMT_RGB565LE] = { 1, 1 },
|
yading@11
|
143 [AV_PIX_FMT_RGB555BE] = { 1, 1 },
|
yading@11
|
144 [AV_PIX_FMT_RGB555LE] = { 1, 1 },
|
yading@11
|
145 [AV_PIX_FMT_BGR565BE] = { 1, 1 },
|
yading@11
|
146 [AV_PIX_FMT_BGR565LE] = { 1, 1 },
|
yading@11
|
147 [AV_PIX_FMT_BGR555BE] = { 1, 1 },
|
yading@11
|
148 [AV_PIX_FMT_BGR555LE] = { 1, 1 },
|
yading@11
|
149 [AV_PIX_FMT_YUV420P16LE] = { 1, 1 },
|
yading@11
|
150 [AV_PIX_FMT_YUV420P16BE] = { 1, 1 },
|
yading@11
|
151 [AV_PIX_FMT_YUV422P16LE] = { 1, 1 },
|
yading@11
|
152 [AV_PIX_FMT_YUV422P16BE] = { 1, 1 },
|
yading@11
|
153 [AV_PIX_FMT_YUV444P16LE] = { 1, 1 },
|
yading@11
|
154 [AV_PIX_FMT_YUV444P16BE] = { 1, 1 },
|
yading@11
|
155 [AV_PIX_FMT_RGB444LE] = { 1, 1 },
|
yading@11
|
156 [AV_PIX_FMT_RGB444BE] = { 1, 1 },
|
yading@11
|
157 [AV_PIX_FMT_BGR444LE] = { 1, 1 },
|
yading@11
|
158 [AV_PIX_FMT_BGR444BE] = { 1, 1 },
|
yading@11
|
159 [AV_PIX_FMT_Y400A] = { 1, 0 },
|
yading@11
|
160 [AV_PIX_FMT_BGR48BE] = { 1, 1 },
|
yading@11
|
161 [AV_PIX_FMT_BGR48LE] = { 1, 1 },
|
yading@11
|
162 [AV_PIX_FMT_BGRA64BE] = { 0, 0 },
|
yading@11
|
163 [AV_PIX_FMT_BGRA64LE] = { 0, 0 },
|
yading@11
|
164 [AV_PIX_FMT_YUV420P9BE] = { 1, 1 },
|
yading@11
|
165 [AV_PIX_FMT_YUV420P9LE] = { 1, 1 },
|
yading@11
|
166 [AV_PIX_FMT_YUV420P10BE] = { 1, 1 },
|
yading@11
|
167 [AV_PIX_FMT_YUV420P10LE] = { 1, 1 },
|
yading@11
|
168 [AV_PIX_FMT_YUV420P12BE] = { 1, 1 },
|
yading@11
|
169 [AV_PIX_FMT_YUV420P12LE] = { 1, 1 },
|
yading@11
|
170 [AV_PIX_FMT_YUV420P14BE] = { 1, 1 },
|
yading@11
|
171 [AV_PIX_FMT_YUV420P14LE] = { 1, 1 },
|
yading@11
|
172 [AV_PIX_FMT_YUV422P9BE] = { 1, 1 },
|
yading@11
|
173 [AV_PIX_FMT_YUV422P9LE] = { 1, 1 },
|
yading@11
|
174 [AV_PIX_FMT_YUV422P10BE] = { 1, 1 },
|
yading@11
|
175 [AV_PIX_FMT_YUV422P10LE] = { 1, 1 },
|
yading@11
|
176 [AV_PIX_FMT_YUV422P12BE] = { 1, 1 },
|
yading@11
|
177 [AV_PIX_FMT_YUV422P12LE] = { 1, 1 },
|
yading@11
|
178 [AV_PIX_FMT_YUV422P14BE] = { 1, 1 },
|
yading@11
|
179 [AV_PIX_FMT_YUV422P14LE] = { 1, 1 },
|
yading@11
|
180 [AV_PIX_FMT_YUV444P9BE] = { 1, 1 },
|
yading@11
|
181 [AV_PIX_FMT_YUV444P9LE] = { 1, 1 },
|
yading@11
|
182 [AV_PIX_FMT_YUV444P10BE] = { 1, 1 },
|
yading@11
|
183 [AV_PIX_FMT_YUV444P10LE] = { 1, 1 },
|
yading@11
|
184 [AV_PIX_FMT_YUV444P12BE] = { 1, 1 },
|
yading@11
|
185 [AV_PIX_FMT_YUV444P12LE] = { 1, 1 },
|
yading@11
|
186 [AV_PIX_FMT_YUV444P14BE] = { 1, 1 },
|
yading@11
|
187 [AV_PIX_FMT_YUV444P14LE] = { 1, 1 },
|
yading@11
|
188 [AV_PIX_FMT_GBRP] = { 1, 1 },
|
yading@11
|
189 [AV_PIX_FMT_GBRP9LE] = { 1, 1 },
|
yading@11
|
190 [AV_PIX_FMT_GBRP9BE] = { 1, 1 },
|
yading@11
|
191 [AV_PIX_FMT_GBRP10LE] = { 1, 1 },
|
yading@11
|
192 [AV_PIX_FMT_GBRP10BE] = { 1, 1 },
|
yading@11
|
193 [AV_PIX_FMT_GBRP12LE] = { 1, 1 },
|
yading@11
|
194 [AV_PIX_FMT_GBRP12BE] = { 1, 1 },
|
yading@11
|
195 [AV_PIX_FMT_GBRP14LE] = { 1, 1 },
|
yading@11
|
196 [AV_PIX_FMT_GBRP14BE] = { 1, 1 },
|
yading@11
|
197 [AV_PIX_FMT_GBRP16LE] = { 1, 0 },
|
yading@11
|
198 [AV_PIX_FMT_GBRP16BE] = { 1, 0 },
|
yading@11
|
199 };
|
yading@11
|
200
|
yading@11
|
201 int sws_isSupportedInput(enum AVPixelFormat pix_fmt)
|
yading@11
|
202 {
|
yading@11
|
203 return (unsigned)pix_fmt < AV_PIX_FMT_NB ?
|
yading@11
|
204 format_entries[pix_fmt].is_supported_in : 0;
|
yading@11
|
205 }
|
yading@11
|
206
|
yading@11
|
207 int sws_isSupportedOutput(enum AVPixelFormat pix_fmt)
|
yading@11
|
208 {
|
yading@11
|
209 return (unsigned)pix_fmt < AV_PIX_FMT_NB ?
|
yading@11
|
210 format_entries[pix_fmt].is_supported_out : 0;
|
yading@11
|
211 }
|
yading@11
|
212
|
yading@11
|
213 extern const int32_t ff_yuv2rgb_coeffs[8][4];
|
yading@11
|
214
|
yading@11
|
215 #if FF_API_SWS_FORMAT_NAME
|
yading@11
|
216 const char *sws_format_name(enum AVPixelFormat format)
|
yading@11
|
217 {
|
yading@11
|
218 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format);
|
yading@11
|
219 if (desc)
|
yading@11
|
220 return desc->name;
|
yading@11
|
221 else
|
yading@11
|
222 return "Unknown format";
|
yading@11
|
223 }
|
yading@11
|
224 #endif
|
yading@11
|
225
|
yading@11
|
226 static double getSplineCoeff(double a, double b, double c, double d,
|
yading@11
|
227 double dist)
|
yading@11
|
228 {
|
yading@11
|
229 if (dist <= 1.0)
|
yading@11
|
230 return ((d * dist + c) * dist + b) * dist + a;
|
yading@11
|
231 else
|
yading@11
|
232 return getSplineCoeff(0.0,
|
yading@11
|
233 b + 2.0 * c + 3.0 * d,
|
yading@11
|
234 c + 3.0 * d,
|
yading@11
|
235 -b - 3.0 * c - 6.0 * d,
|
yading@11
|
236 dist - 1.0);
|
yading@11
|
237 }
|
yading@11
|
238
|
yading@11
|
239 static int initFilter(int16_t **outFilter, int32_t **filterPos,
|
yading@11
|
240 int *outFilterSize, int xInc, int srcW, int dstW,
|
yading@11
|
241 int filterAlign, int one, int flags, int cpu_flags,
|
yading@11
|
242 SwsVector *srcFilter, SwsVector *dstFilter,
|
yading@11
|
243 double param[2])
|
yading@11
|
244 {
|
yading@11
|
245 int i;
|
yading@11
|
246 int filterSize;
|
yading@11
|
247 int filter2Size;
|
yading@11
|
248 int minFilterSize;
|
yading@11
|
249 int64_t *filter = NULL;
|
yading@11
|
250 int64_t *filter2 = NULL;
|
yading@11
|
251 const int64_t fone = 1LL << (54 - FFMIN(av_log2(srcW/dstW), 8));
|
yading@11
|
252 int ret = -1;
|
yading@11
|
253
|
yading@11
|
254 emms_c(); // FIXME should not be required but IS (even for non-MMX versions)
|
yading@11
|
255
|
yading@11
|
256 // NOTE: the +3 is for the MMX(+1) / SSE(+3) scaler which reads over the end
|
yading@11
|
257 FF_ALLOC_OR_GOTO(NULL, *filterPos, (dstW + 3) * sizeof(**filterPos), fail);
|
yading@11
|
258
|
yading@11
|
259 if (FFABS(xInc - 0x10000) < 10) { // unscaled
|
yading@11
|
260 int i;
|
yading@11
|
261 filterSize = 1;
|
yading@11
|
262 FF_ALLOCZ_OR_GOTO(NULL, filter,
|
yading@11
|
263 dstW * sizeof(*filter) * filterSize, fail);
|
yading@11
|
264
|
yading@11
|
265 for (i = 0; i < dstW; i++) {
|
yading@11
|
266 filter[i * filterSize] = fone;
|
yading@11
|
267 (*filterPos)[i] = i;
|
yading@11
|
268 }
|
yading@11
|
269 } else if (flags & SWS_POINT) { // lame looking point sampling mode
|
yading@11
|
270 int i;
|
yading@11
|
271 int64_t xDstInSrc;
|
yading@11
|
272 filterSize = 1;
|
yading@11
|
273 FF_ALLOC_OR_GOTO(NULL, filter,
|
yading@11
|
274 dstW * sizeof(*filter) * filterSize, fail);
|
yading@11
|
275
|
yading@11
|
276 xDstInSrc = xInc / 2 - 0x8000;
|
yading@11
|
277 for (i = 0; i < dstW; i++) {
|
yading@11
|
278 int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16;
|
yading@11
|
279
|
yading@11
|
280 (*filterPos)[i] = xx;
|
yading@11
|
281 filter[i] = fone;
|
yading@11
|
282 xDstInSrc += xInc;
|
yading@11
|
283 }
|
yading@11
|
284 } else if ((xInc <= (1 << 16) && (flags & SWS_AREA)) ||
|
yading@11
|
285 (flags & SWS_FAST_BILINEAR)) { // bilinear upscale
|
yading@11
|
286 int i;
|
yading@11
|
287 int64_t xDstInSrc;
|
yading@11
|
288 filterSize = 2;
|
yading@11
|
289 FF_ALLOC_OR_GOTO(NULL, filter,
|
yading@11
|
290 dstW * sizeof(*filter) * filterSize, fail);
|
yading@11
|
291
|
yading@11
|
292 xDstInSrc = xInc / 2 - 0x8000;
|
yading@11
|
293 for (i = 0; i < dstW; i++) {
|
yading@11
|
294 int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16;
|
yading@11
|
295 int j;
|
yading@11
|
296
|
yading@11
|
297 (*filterPos)[i] = xx;
|
yading@11
|
298 // bilinear upscale / linear interpolate / area averaging
|
yading@11
|
299 for (j = 0; j < filterSize; j++) {
|
yading@11
|
300 int64_t coeff= fone - FFABS(((int64_t)xx<<16) - xDstInSrc)*(fone>>16);
|
yading@11
|
301 if (coeff < 0)
|
yading@11
|
302 coeff = 0;
|
yading@11
|
303 filter[i * filterSize + j] = coeff;
|
yading@11
|
304 xx++;
|
yading@11
|
305 }
|
yading@11
|
306 xDstInSrc += xInc;
|
yading@11
|
307 }
|
yading@11
|
308 } else {
|
yading@11
|
309 int64_t xDstInSrc;
|
yading@11
|
310 int sizeFactor;
|
yading@11
|
311
|
yading@11
|
312 if (flags & SWS_BICUBIC)
|
yading@11
|
313 sizeFactor = 4;
|
yading@11
|
314 else if (flags & SWS_X)
|
yading@11
|
315 sizeFactor = 8;
|
yading@11
|
316 else if (flags & SWS_AREA)
|
yading@11
|
317 sizeFactor = 1; // downscale only, for upscale it is bilinear
|
yading@11
|
318 else if (flags & SWS_GAUSS)
|
yading@11
|
319 sizeFactor = 8; // infinite ;)
|
yading@11
|
320 else if (flags & SWS_LANCZOS)
|
yading@11
|
321 sizeFactor = param[0] != SWS_PARAM_DEFAULT ? ceil(2 * param[0]) : 6;
|
yading@11
|
322 else if (flags & SWS_SINC)
|
yading@11
|
323 sizeFactor = 20; // infinite ;)
|
yading@11
|
324 else if (flags & SWS_SPLINE)
|
yading@11
|
325 sizeFactor = 20; // infinite ;)
|
yading@11
|
326 else if (flags & SWS_BILINEAR)
|
yading@11
|
327 sizeFactor = 2;
|
yading@11
|
328 else {
|
yading@11
|
329 av_assert0(0);
|
yading@11
|
330 }
|
yading@11
|
331
|
yading@11
|
332 if (xInc <= 1 << 16)
|
yading@11
|
333 filterSize = 1 + sizeFactor; // upscale
|
yading@11
|
334 else
|
yading@11
|
335 filterSize = 1 + (sizeFactor * srcW + dstW - 1) / dstW;
|
yading@11
|
336
|
yading@11
|
337 filterSize = FFMIN(filterSize, srcW - 2);
|
yading@11
|
338 filterSize = FFMAX(filterSize, 1);
|
yading@11
|
339
|
yading@11
|
340 FF_ALLOC_OR_GOTO(NULL, filter,
|
yading@11
|
341 dstW * sizeof(*filter) * filterSize, fail);
|
yading@11
|
342
|
yading@11
|
343 xDstInSrc = xInc - 0x10000;
|
yading@11
|
344 for (i = 0; i < dstW; i++) {
|
yading@11
|
345 int xx = (xDstInSrc - ((filterSize - 2) << 16)) / (1 << 17);
|
yading@11
|
346 int j;
|
yading@11
|
347 (*filterPos)[i] = xx;
|
yading@11
|
348 for (j = 0; j < filterSize; j++) {
|
yading@11
|
349 int64_t d = (FFABS(((int64_t)xx << 17) - xDstInSrc)) << 13;
|
yading@11
|
350 double floatd;
|
yading@11
|
351 int64_t coeff;
|
yading@11
|
352
|
yading@11
|
353 if (xInc > 1 << 16)
|
yading@11
|
354 d = d * dstW / srcW;
|
yading@11
|
355 floatd = d * (1.0 / (1 << 30));
|
yading@11
|
356
|
yading@11
|
357 if (flags & SWS_BICUBIC) {
|
yading@11
|
358 int64_t B = (param[0] != SWS_PARAM_DEFAULT ? param[0] : 0) * (1 << 24);
|
yading@11
|
359 int64_t C = (param[1] != SWS_PARAM_DEFAULT ? param[1] : 0.6) * (1 << 24);
|
yading@11
|
360
|
yading@11
|
361 if (d >= 1LL << 31) {
|
yading@11
|
362 coeff = 0.0;
|
yading@11
|
363 } else {
|
yading@11
|
364 int64_t dd = (d * d) >> 30;
|
yading@11
|
365 int64_t ddd = (dd * d) >> 30;
|
yading@11
|
366
|
yading@11
|
367 if (d < 1LL << 30)
|
yading@11
|
368 coeff = (12 * (1 << 24) - 9 * B - 6 * C) * ddd +
|
yading@11
|
369 (-18 * (1 << 24) + 12 * B + 6 * C) * dd +
|
yading@11
|
370 (6 * (1 << 24) - 2 * B) * (1 << 30);
|
yading@11
|
371 else
|
yading@11
|
372 coeff = (-B - 6 * C) * ddd +
|
yading@11
|
373 (6 * B + 30 * C) * dd +
|
yading@11
|
374 (-12 * B - 48 * C) * d +
|
yading@11
|
375 (8 * B + 24 * C) * (1 << 30);
|
yading@11
|
376 }
|
yading@11
|
377 coeff /= (1LL<<54)/fone;
|
yading@11
|
378 }
|
yading@11
|
379 #if 0
|
yading@11
|
380 else if (flags & SWS_X) {
|
yading@11
|
381 double p = param ? param * 0.01 : 0.3;
|
yading@11
|
382 coeff = d ? sin(d * M_PI) / (d * M_PI) : 1.0;
|
yading@11
|
383 coeff *= pow(2.0, -p * d * d);
|
yading@11
|
384 }
|
yading@11
|
385 #endif
|
yading@11
|
386 else if (flags & SWS_X) {
|
yading@11
|
387 double A = param[0] != SWS_PARAM_DEFAULT ? param[0] : 1.0;
|
yading@11
|
388 double c;
|
yading@11
|
389
|
yading@11
|
390 if (floatd < 1.0)
|
yading@11
|
391 c = cos(floatd * M_PI);
|
yading@11
|
392 else
|
yading@11
|
393 c = -1.0;
|
yading@11
|
394 if (c < 0.0)
|
yading@11
|
395 c = -pow(-c, A);
|
yading@11
|
396 else
|
yading@11
|
397 c = pow(c, A);
|
yading@11
|
398 coeff = (c * 0.5 + 0.5) * fone;
|
yading@11
|
399 } else if (flags & SWS_AREA) {
|
yading@11
|
400 int64_t d2 = d - (1 << 29);
|
yading@11
|
401 if (d2 * xInc < -(1LL << (29 + 16)))
|
yading@11
|
402 coeff = 1.0 * (1LL << (30 + 16));
|
yading@11
|
403 else if (d2 * xInc < (1LL << (29 + 16)))
|
yading@11
|
404 coeff = -d2 * xInc + (1LL << (29 + 16));
|
yading@11
|
405 else
|
yading@11
|
406 coeff = 0.0;
|
yading@11
|
407 coeff *= fone >> (30 + 16);
|
yading@11
|
408 } else if (flags & SWS_GAUSS) {
|
yading@11
|
409 double p = param[0] != SWS_PARAM_DEFAULT ? param[0] : 3.0;
|
yading@11
|
410 coeff = (pow(2.0, -p * floatd * floatd)) * fone;
|
yading@11
|
411 } else if (flags & SWS_SINC) {
|
yading@11
|
412 coeff = (d ? sin(floatd * M_PI) / (floatd * M_PI) : 1.0) * fone;
|
yading@11
|
413 } else if (flags & SWS_LANCZOS) {
|
yading@11
|
414 double p = param[0] != SWS_PARAM_DEFAULT ? param[0] : 3.0;
|
yading@11
|
415 coeff = (d ? sin(floatd * M_PI) * sin(floatd * M_PI / p) /
|
yading@11
|
416 (floatd * floatd * M_PI * M_PI / p) : 1.0) * fone;
|
yading@11
|
417 if (floatd > p)
|
yading@11
|
418 coeff = 0;
|
yading@11
|
419 } else if (flags & SWS_BILINEAR) {
|
yading@11
|
420 coeff = (1 << 30) - d;
|
yading@11
|
421 if (coeff < 0)
|
yading@11
|
422 coeff = 0;
|
yading@11
|
423 coeff *= fone >> 30;
|
yading@11
|
424 } else if (flags & SWS_SPLINE) {
|
yading@11
|
425 double p = -2.196152422706632;
|
yading@11
|
426 coeff = getSplineCoeff(1.0, 0.0, p, -p - 1.0, floatd) * fone;
|
yading@11
|
427 } else {
|
yading@11
|
428 av_assert0(0);
|
yading@11
|
429 }
|
yading@11
|
430
|
yading@11
|
431 filter[i * filterSize + j] = coeff;
|
yading@11
|
432 xx++;
|
yading@11
|
433 }
|
yading@11
|
434 xDstInSrc += 2 * xInc;
|
yading@11
|
435 }
|
yading@11
|
436 }
|
yading@11
|
437
|
yading@11
|
438 /* apply src & dst Filter to filter -> filter2
|
yading@11
|
439 * av_free(filter);
|
yading@11
|
440 */
|
yading@11
|
441 av_assert0(filterSize > 0);
|
yading@11
|
442 filter2Size = filterSize;
|
yading@11
|
443 if (srcFilter)
|
yading@11
|
444 filter2Size += srcFilter->length - 1;
|
yading@11
|
445 if (dstFilter)
|
yading@11
|
446 filter2Size += dstFilter->length - 1;
|
yading@11
|
447 av_assert0(filter2Size > 0);
|
yading@11
|
448 FF_ALLOCZ_OR_GOTO(NULL, filter2, filter2Size * dstW * sizeof(*filter2), fail);
|
yading@11
|
449
|
yading@11
|
450 for (i = 0; i < dstW; i++) {
|
yading@11
|
451 int j, k;
|
yading@11
|
452
|
yading@11
|
453 if (srcFilter) {
|
yading@11
|
454 for (k = 0; k < srcFilter->length; k++) {
|
yading@11
|
455 for (j = 0; j < filterSize; j++)
|
yading@11
|
456 filter2[i * filter2Size + k + j] +=
|
yading@11
|
457 srcFilter->coeff[k] * filter[i * filterSize + j];
|
yading@11
|
458 }
|
yading@11
|
459 } else {
|
yading@11
|
460 for (j = 0; j < filterSize; j++)
|
yading@11
|
461 filter2[i * filter2Size + j] = filter[i * filterSize + j];
|
yading@11
|
462 }
|
yading@11
|
463 // FIXME dstFilter
|
yading@11
|
464
|
yading@11
|
465 (*filterPos)[i] += (filterSize - 1) / 2 - (filter2Size - 1) / 2;
|
yading@11
|
466 }
|
yading@11
|
467 av_freep(&filter);
|
yading@11
|
468
|
yading@11
|
469 /* try to reduce the filter-size (step1 find size and shift left) */
|
yading@11
|
470 // Assume it is near normalized (*0.5 or *2.0 is OK but * 0.001 is not).
|
yading@11
|
471 minFilterSize = 0;
|
yading@11
|
472 for (i = dstW - 1; i >= 0; i--) {
|
yading@11
|
473 int min = filter2Size;
|
yading@11
|
474 int j;
|
yading@11
|
475 int64_t cutOff = 0.0;
|
yading@11
|
476
|
yading@11
|
477 /* get rid of near zero elements on the left by shifting left */
|
yading@11
|
478 for (j = 0; j < filter2Size; j++) {
|
yading@11
|
479 int k;
|
yading@11
|
480 cutOff += FFABS(filter2[i * filter2Size]);
|
yading@11
|
481
|
yading@11
|
482 if (cutOff > SWS_MAX_REDUCE_CUTOFF * fone)
|
yading@11
|
483 break;
|
yading@11
|
484
|
yading@11
|
485 /* preserve monotonicity because the core can't handle the
|
yading@11
|
486 * filter otherwise */
|
yading@11
|
487 if (i < dstW - 1 && (*filterPos)[i] >= (*filterPos)[i + 1])
|
yading@11
|
488 break;
|
yading@11
|
489
|
yading@11
|
490 // move filter coefficients left
|
yading@11
|
491 for (k = 1; k < filter2Size; k++)
|
yading@11
|
492 filter2[i * filter2Size + k - 1] = filter2[i * filter2Size + k];
|
yading@11
|
493 filter2[i * filter2Size + k - 1] = 0;
|
yading@11
|
494 (*filterPos)[i]++;
|
yading@11
|
495 }
|
yading@11
|
496
|
yading@11
|
497 cutOff = 0;
|
yading@11
|
498 /* count near zeros on the right */
|
yading@11
|
499 for (j = filter2Size - 1; j > 0; j--) {
|
yading@11
|
500 cutOff += FFABS(filter2[i * filter2Size + j]);
|
yading@11
|
501
|
yading@11
|
502 if (cutOff > SWS_MAX_REDUCE_CUTOFF * fone)
|
yading@11
|
503 break;
|
yading@11
|
504 min--;
|
yading@11
|
505 }
|
yading@11
|
506
|
yading@11
|
507 if (min > minFilterSize)
|
yading@11
|
508 minFilterSize = min;
|
yading@11
|
509 }
|
yading@11
|
510
|
yading@11
|
511 if (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) {
|
yading@11
|
512 // we can handle the special case 4, so we don't want to go the full 8
|
yading@11
|
513 if (minFilterSize < 5)
|
yading@11
|
514 filterAlign = 4;
|
yading@11
|
515
|
yading@11
|
516 /* We really don't want to waste our time doing useless computation, so
|
yading@11
|
517 * fall back on the scalar C code for very small filters.
|
yading@11
|
518 * Vectorizing is worth it only if you have a decent-sized vector. */
|
yading@11
|
519 if (minFilterSize < 3)
|
yading@11
|
520 filterAlign = 1;
|
yading@11
|
521 }
|
yading@11
|
522
|
yading@11
|
523 if (INLINE_MMX(cpu_flags)) {
|
yading@11
|
524 // special case for unscaled vertical filtering
|
yading@11
|
525 if (minFilterSize == 1 && filterAlign == 2)
|
yading@11
|
526 filterAlign = 1;
|
yading@11
|
527 }
|
yading@11
|
528
|
yading@11
|
529 av_assert0(minFilterSize > 0);
|
yading@11
|
530 filterSize = (minFilterSize + (filterAlign - 1)) & (~(filterAlign - 1));
|
yading@11
|
531 av_assert0(filterSize > 0);
|
yading@11
|
532 filter = av_malloc(filterSize * dstW * sizeof(*filter));
|
yading@11
|
533 if (filterSize >= MAX_FILTER_SIZE * 16 /
|
yading@11
|
534 ((flags & SWS_ACCURATE_RND) ? APCK_SIZE : 16) || !filter) {
|
yading@11
|
535 av_log(NULL, AV_LOG_ERROR, "sws: filterSize %d is too large, try less extreem scaling or increase MAX_FILTER_SIZE and recompile\n", filterSize);
|
yading@11
|
536 goto fail;
|
yading@11
|
537 }
|
yading@11
|
538 *outFilterSize = filterSize;
|
yading@11
|
539
|
yading@11
|
540 if (flags & SWS_PRINT_INFO)
|
yading@11
|
541 av_log(NULL, AV_LOG_VERBOSE,
|
yading@11
|
542 "SwScaler: reducing / aligning filtersize %d -> %d\n",
|
yading@11
|
543 filter2Size, filterSize);
|
yading@11
|
544 /* try to reduce the filter-size (step2 reduce it) */
|
yading@11
|
545 for (i = 0; i < dstW; i++) {
|
yading@11
|
546 int j;
|
yading@11
|
547
|
yading@11
|
548 for (j = 0; j < filterSize; j++) {
|
yading@11
|
549 if (j >= filter2Size)
|
yading@11
|
550 filter[i * filterSize + j] = 0;
|
yading@11
|
551 else
|
yading@11
|
552 filter[i * filterSize + j] = filter2[i * filter2Size + j];
|
yading@11
|
553 if ((flags & SWS_BITEXACT) && j >= minFilterSize)
|
yading@11
|
554 filter[i * filterSize + j] = 0;
|
yading@11
|
555 }
|
yading@11
|
556 }
|
yading@11
|
557
|
yading@11
|
558 // FIXME try to align filterPos if possible
|
yading@11
|
559
|
yading@11
|
560 // fix borders
|
yading@11
|
561 for (i = 0; i < dstW; i++) {
|
yading@11
|
562 int j;
|
yading@11
|
563 if ((*filterPos)[i] < 0) {
|
yading@11
|
564 // move filter coefficients left to compensate for filterPos
|
yading@11
|
565 for (j = 1; j < filterSize; j++) {
|
yading@11
|
566 int left = FFMAX(j + (*filterPos)[i], 0);
|
yading@11
|
567 filter[i * filterSize + left] += filter[i * filterSize + j];
|
yading@11
|
568 filter[i * filterSize + j] = 0;
|
yading@11
|
569 }
|
yading@11
|
570 (*filterPos)[i]= 0;
|
yading@11
|
571 }
|
yading@11
|
572
|
yading@11
|
573 if ((*filterPos)[i] + filterSize > srcW) {
|
yading@11
|
574 int shift = (*filterPos)[i] + filterSize - srcW;
|
yading@11
|
575 // move filter coefficients right to compensate for filterPos
|
yading@11
|
576 for (j = filterSize - 2; j >= 0; j--) {
|
yading@11
|
577 int right = FFMIN(j + shift, filterSize - 1);
|
yading@11
|
578 filter[i * filterSize + right] += filter[i * filterSize + j];
|
yading@11
|
579 filter[i * filterSize + j] = 0;
|
yading@11
|
580 }
|
yading@11
|
581 (*filterPos)[i]= srcW - filterSize;
|
yading@11
|
582 }
|
yading@11
|
583 }
|
yading@11
|
584
|
yading@11
|
585 // Note the +1 is for the MMX scaler which reads over the end
|
yading@11
|
586 /* align at 16 for AltiVec (needed by hScale_altivec_real) */
|
yading@11
|
587 FF_ALLOCZ_OR_GOTO(NULL, *outFilter,
|
yading@11
|
588 *outFilterSize * (dstW + 3) * sizeof(int16_t), fail);
|
yading@11
|
589
|
yading@11
|
590 /* normalize & store in outFilter */
|
yading@11
|
591 for (i = 0; i < dstW; i++) {
|
yading@11
|
592 int j;
|
yading@11
|
593 int64_t error = 0;
|
yading@11
|
594 int64_t sum = 0;
|
yading@11
|
595
|
yading@11
|
596 for (j = 0; j < filterSize; j++) {
|
yading@11
|
597 sum += filter[i * filterSize + j];
|
yading@11
|
598 }
|
yading@11
|
599 sum = (sum + one / 2) / one;
|
yading@11
|
600 for (j = 0; j < *outFilterSize; j++) {
|
yading@11
|
601 int64_t v = filter[i * filterSize + j] + error;
|
yading@11
|
602 int intV = ROUNDED_DIV(v, sum);
|
yading@11
|
603 (*outFilter)[i * (*outFilterSize) + j] = intV;
|
yading@11
|
604 error = v - intV * sum;
|
yading@11
|
605 }
|
yading@11
|
606 }
|
yading@11
|
607
|
yading@11
|
608 (*filterPos)[dstW + 0] =
|
yading@11
|
609 (*filterPos)[dstW + 1] =
|
yading@11
|
610 (*filterPos)[dstW + 2] = (*filterPos)[dstW - 1]; /* the MMX/SSE scaler will
|
yading@11
|
611 * read over the end */
|
yading@11
|
612 for (i = 0; i < *outFilterSize; i++) {
|
yading@11
|
613 int k = (dstW - 1) * (*outFilterSize) + i;
|
yading@11
|
614 (*outFilter)[k + 1 * (*outFilterSize)] =
|
yading@11
|
615 (*outFilter)[k + 2 * (*outFilterSize)] =
|
yading@11
|
616 (*outFilter)[k + 3 * (*outFilterSize)] = (*outFilter)[k];
|
yading@11
|
617 }
|
yading@11
|
618
|
yading@11
|
619 ret = 0;
|
yading@11
|
620
|
yading@11
|
621 fail:
|
yading@11
|
622 if(ret < 0)
|
yading@11
|
623 av_log(NULL, AV_LOG_ERROR, "sws: initFilter failed\n");
|
yading@11
|
624 av_free(filter);
|
yading@11
|
625 av_free(filter2);
|
yading@11
|
626 return ret;
|
yading@11
|
627 }
|
yading@11
|
628
|
yading@11
|
629 #if HAVE_MMXEXT_INLINE
|
yading@11
|
630 static int init_hscaler_mmxext(int dstW, int xInc, uint8_t *filterCode,
|
yading@11
|
631 int16_t *filter, int32_t *filterPos,
|
yading@11
|
632 int numSplits)
|
yading@11
|
633 {
|
yading@11
|
634 uint8_t *fragmentA;
|
yading@11
|
635 x86_reg imm8OfPShufW1A;
|
yading@11
|
636 x86_reg imm8OfPShufW2A;
|
yading@11
|
637 x86_reg fragmentLengthA;
|
yading@11
|
638 uint8_t *fragmentB;
|
yading@11
|
639 x86_reg imm8OfPShufW1B;
|
yading@11
|
640 x86_reg imm8OfPShufW2B;
|
yading@11
|
641 x86_reg fragmentLengthB;
|
yading@11
|
642 int fragmentPos;
|
yading@11
|
643
|
yading@11
|
644 int xpos, i;
|
yading@11
|
645
|
yading@11
|
646 // create an optimized horizontal scaling routine
|
yading@11
|
647 /* This scaler is made of runtime-generated MMXEXT code using specially tuned
|
yading@11
|
648 * pshufw instructions. For every four output pixels, if four input pixels
|
yading@11
|
649 * are enough for the fast bilinear scaling, then a chunk of fragmentB is
|
yading@11
|
650 * used. If five input pixels are needed, then a chunk of fragmentA is used.
|
yading@11
|
651 */
|
yading@11
|
652
|
yading@11
|
653 // code fragment
|
yading@11
|
654
|
yading@11
|
655 __asm__ volatile (
|
yading@11
|
656 "jmp 9f \n\t"
|
yading@11
|
657 // Begin
|
yading@11
|
658 "0: \n\t"
|
yading@11
|
659 "movq (%%"REG_d", %%"REG_a"), %%mm3 \n\t"
|
yading@11
|
660 "movd (%%"REG_c", %%"REG_S"), %%mm0 \n\t"
|
yading@11
|
661 "movd 1(%%"REG_c", %%"REG_S"), %%mm1 \n\t"
|
yading@11
|
662 "punpcklbw %%mm7, %%mm1 \n\t"
|
yading@11
|
663 "punpcklbw %%mm7, %%mm0 \n\t"
|
yading@11
|
664 "pshufw $0xFF, %%mm1, %%mm1 \n\t"
|
yading@11
|
665 "1: \n\t"
|
yading@11
|
666 "pshufw $0xFF, %%mm0, %%mm0 \n\t"
|
yading@11
|
667 "2: \n\t"
|
yading@11
|
668 "psubw %%mm1, %%mm0 \n\t"
|
yading@11
|
669 "movl 8(%%"REG_b", %%"REG_a"), %%esi \n\t"
|
yading@11
|
670 "pmullw %%mm3, %%mm0 \n\t"
|
yading@11
|
671 "psllw $7, %%mm1 \n\t"
|
yading@11
|
672 "paddw %%mm1, %%mm0 \n\t"
|
yading@11
|
673
|
yading@11
|
674 "movq %%mm0, (%%"REG_D", %%"REG_a") \n\t"
|
yading@11
|
675
|
yading@11
|
676 "add $8, %%"REG_a" \n\t"
|
yading@11
|
677 // End
|
yading@11
|
678 "9: \n\t"
|
yading@11
|
679 // "int $3 \n\t"
|
yading@11
|
680 "lea " LOCAL_MANGLE(0b) ", %0 \n\t"
|
yading@11
|
681 "lea " LOCAL_MANGLE(1b) ", %1 \n\t"
|
yading@11
|
682 "lea " LOCAL_MANGLE(2b) ", %2 \n\t"
|
yading@11
|
683 "dec %1 \n\t"
|
yading@11
|
684 "dec %2 \n\t"
|
yading@11
|
685 "sub %0, %1 \n\t"
|
yading@11
|
686 "sub %0, %2 \n\t"
|
yading@11
|
687 "lea " LOCAL_MANGLE(9b) ", %3 \n\t"
|
yading@11
|
688 "sub %0, %3 \n\t"
|
yading@11
|
689
|
yading@11
|
690
|
yading@11
|
691 : "=r" (fragmentA), "=r" (imm8OfPShufW1A), "=r" (imm8OfPShufW2A),
|
yading@11
|
692 "=r" (fragmentLengthA)
|
yading@11
|
693 );
|
yading@11
|
694
|
yading@11
|
695 __asm__ volatile (
|
yading@11
|
696 "jmp 9f \n\t"
|
yading@11
|
697 // Begin
|
yading@11
|
698 "0: \n\t"
|
yading@11
|
699 "movq (%%"REG_d", %%"REG_a"), %%mm3 \n\t"
|
yading@11
|
700 "movd (%%"REG_c", %%"REG_S"), %%mm0 \n\t"
|
yading@11
|
701 "punpcklbw %%mm7, %%mm0 \n\t"
|
yading@11
|
702 "pshufw $0xFF, %%mm0, %%mm1 \n\t"
|
yading@11
|
703 "1: \n\t"
|
yading@11
|
704 "pshufw $0xFF, %%mm0, %%mm0 \n\t"
|
yading@11
|
705 "2: \n\t"
|
yading@11
|
706 "psubw %%mm1, %%mm0 \n\t"
|
yading@11
|
707 "movl 8(%%"REG_b", %%"REG_a"), %%esi \n\t"
|
yading@11
|
708 "pmullw %%mm3, %%mm0 \n\t"
|
yading@11
|
709 "psllw $7, %%mm1 \n\t"
|
yading@11
|
710 "paddw %%mm1, %%mm0 \n\t"
|
yading@11
|
711
|
yading@11
|
712 "movq %%mm0, (%%"REG_D", %%"REG_a") \n\t"
|
yading@11
|
713
|
yading@11
|
714 "add $8, %%"REG_a" \n\t"
|
yading@11
|
715 // End
|
yading@11
|
716 "9: \n\t"
|
yading@11
|
717 // "int $3 \n\t"
|
yading@11
|
718 "lea " LOCAL_MANGLE(0b) ", %0 \n\t"
|
yading@11
|
719 "lea " LOCAL_MANGLE(1b) ", %1 \n\t"
|
yading@11
|
720 "lea " LOCAL_MANGLE(2b) ", %2 \n\t"
|
yading@11
|
721 "dec %1 \n\t"
|
yading@11
|
722 "dec %2 \n\t"
|
yading@11
|
723 "sub %0, %1 \n\t"
|
yading@11
|
724 "sub %0, %2 \n\t"
|
yading@11
|
725 "lea " LOCAL_MANGLE(9b) ", %3 \n\t"
|
yading@11
|
726 "sub %0, %3 \n\t"
|
yading@11
|
727
|
yading@11
|
728
|
yading@11
|
729 : "=r" (fragmentB), "=r" (imm8OfPShufW1B), "=r" (imm8OfPShufW2B),
|
yading@11
|
730 "=r" (fragmentLengthB)
|
yading@11
|
731 );
|
yading@11
|
732
|
yading@11
|
733 xpos = 0; // lumXInc/2 - 0x8000; // difference between pixel centers
|
yading@11
|
734 fragmentPos = 0;
|
yading@11
|
735
|
yading@11
|
736 for (i = 0; i < dstW / numSplits; i++) {
|
yading@11
|
737 int xx = xpos >> 16;
|
yading@11
|
738
|
yading@11
|
739 if ((i & 3) == 0) {
|
yading@11
|
740 int a = 0;
|
yading@11
|
741 int b = ((xpos + xInc) >> 16) - xx;
|
yading@11
|
742 int c = ((xpos + xInc * 2) >> 16) - xx;
|
yading@11
|
743 int d = ((xpos + xInc * 3) >> 16) - xx;
|
yading@11
|
744 int inc = (d + 1 < 4);
|
yading@11
|
745 uint8_t *fragment = (d + 1 < 4) ? fragmentB : fragmentA;
|
yading@11
|
746 x86_reg imm8OfPShufW1 = (d + 1 < 4) ? imm8OfPShufW1B : imm8OfPShufW1A;
|
yading@11
|
747 x86_reg imm8OfPShufW2 = (d + 1 < 4) ? imm8OfPShufW2B : imm8OfPShufW2A;
|
yading@11
|
748 x86_reg fragmentLength = (d + 1 < 4) ? fragmentLengthB : fragmentLengthA;
|
yading@11
|
749 int maxShift = 3 - (d + inc);
|
yading@11
|
750 int shift = 0;
|
yading@11
|
751
|
yading@11
|
752 if (filterCode) {
|
yading@11
|
753 filter[i] = ((xpos & 0xFFFF) ^ 0xFFFF) >> 9;
|
yading@11
|
754 filter[i + 1] = (((xpos + xInc) & 0xFFFF) ^ 0xFFFF) >> 9;
|
yading@11
|
755 filter[i + 2] = (((xpos + xInc * 2) & 0xFFFF) ^ 0xFFFF) >> 9;
|
yading@11
|
756 filter[i + 3] = (((xpos + xInc * 3) & 0xFFFF) ^ 0xFFFF) >> 9;
|
yading@11
|
757 filterPos[i / 2] = xx;
|
yading@11
|
758
|
yading@11
|
759 memcpy(filterCode + fragmentPos, fragment, fragmentLength);
|
yading@11
|
760
|
yading@11
|
761 filterCode[fragmentPos + imm8OfPShufW1] = (a + inc) |
|
yading@11
|
762 ((b + inc) << 2) |
|
yading@11
|
763 ((c + inc) << 4) |
|
yading@11
|
764 ((d + inc) << 6);
|
yading@11
|
765 filterCode[fragmentPos + imm8OfPShufW2] = a | (b << 2) |
|
yading@11
|
766 (c << 4) |
|
yading@11
|
767 (d << 6);
|
yading@11
|
768
|
yading@11
|
769 if (i + 4 - inc >= dstW)
|
yading@11
|
770 shift = maxShift; // avoid overread
|
yading@11
|
771 else if ((filterPos[i / 2] & 3) <= maxShift)
|
yading@11
|
772 shift = filterPos[i / 2] & 3; // align
|
yading@11
|
773
|
yading@11
|
774 if (shift && i >= shift) {
|
yading@11
|
775 filterCode[fragmentPos + imm8OfPShufW1] += 0x55 * shift;
|
yading@11
|
776 filterCode[fragmentPos + imm8OfPShufW2] += 0x55 * shift;
|
yading@11
|
777 filterPos[i / 2] -= shift;
|
yading@11
|
778 }
|
yading@11
|
779 }
|
yading@11
|
780
|
yading@11
|
781 fragmentPos += fragmentLength;
|
yading@11
|
782
|
yading@11
|
783 if (filterCode)
|
yading@11
|
784 filterCode[fragmentPos] = RET;
|
yading@11
|
785 }
|
yading@11
|
786 xpos += xInc;
|
yading@11
|
787 }
|
yading@11
|
788 if (filterCode)
|
yading@11
|
789 filterPos[((i / 2) + 1) & (~1)] = xpos >> 16; // needed to jump to the next part
|
yading@11
|
790
|
yading@11
|
791 return fragmentPos + 1;
|
yading@11
|
792 }
|
yading@11
|
793 #endif /* HAVE_MMXEXT_INLINE */
|
yading@11
|
794
|
yading@11
|
795 static void getSubSampleFactors(int *h, int *v, enum AVPixelFormat format)
|
yading@11
|
796 {
|
yading@11
|
797 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format);
|
yading@11
|
798 *h = desc->log2_chroma_w;
|
yading@11
|
799 *v = desc->log2_chroma_h;
|
yading@11
|
800 }
|
yading@11
|
801
|
yading@11
|
802 static void fill_rgb2yuv_table(SwsContext *c, const int table[4], int dstRange)
|
yading@11
|
803 {
|
yading@11
|
804 int64_t W, V, Z, Cy, Cu, Cv;
|
yading@11
|
805 int64_t vr = table[0];
|
yading@11
|
806 int64_t ub = table[1];
|
yading@11
|
807 int64_t ug = -table[2];
|
yading@11
|
808 int64_t vg = -table[3];
|
yading@11
|
809 int64_t ONE = 65536;
|
yading@11
|
810 int64_t cy = ONE;
|
yading@11
|
811 uint8_t *p = (uint8_t*)c->input_rgb2yuv_table;
|
yading@11
|
812 int i;
|
yading@11
|
813 static const int8_t map[] = {
|
yading@11
|
814 BY_IDX, GY_IDX, -1 , BY_IDX, BY_IDX, GY_IDX, -1 , BY_IDX,
|
yading@11
|
815 RY_IDX, -1 , GY_IDX, RY_IDX, RY_IDX, -1 , GY_IDX, RY_IDX,
|
yading@11
|
816 RY_IDX, GY_IDX, -1 , RY_IDX, RY_IDX, GY_IDX, -1 , RY_IDX,
|
yading@11
|
817 BY_IDX, -1 , GY_IDX, BY_IDX, BY_IDX, -1 , GY_IDX, BY_IDX,
|
yading@11
|
818 BU_IDX, GU_IDX, -1 , BU_IDX, BU_IDX, GU_IDX, -1 , BU_IDX,
|
yading@11
|
819 RU_IDX, -1 , GU_IDX, RU_IDX, RU_IDX, -1 , GU_IDX, RU_IDX,
|
yading@11
|
820 RU_IDX, GU_IDX, -1 , RU_IDX, RU_IDX, GU_IDX, -1 , RU_IDX,
|
yading@11
|
821 BU_IDX, -1 , GU_IDX, BU_IDX, BU_IDX, -1 , GU_IDX, BU_IDX,
|
yading@11
|
822 BV_IDX, GV_IDX, -1 , BV_IDX, BV_IDX, GV_IDX, -1 , BV_IDX,
|
yading@11
|
823 RV_IDX, -1 , GV_IDX, RV_IDX, RV_IDX, -1 , GV_IDX, RV_IDX,
|
yading@11
|
824 RV_IDX, GV_IDX, -1 , RV_IDX, RV_IDX, GV_IDX, -1 , RV_IDX,
|
yading@11
|
825 BV_IDX, -1 , GV_IDX, BV_IDX, BV_IDX, -1 , GV_IDX, BV_IDX,
|
yading@11
|
826 RY_IDX, BY_IDX, RY_IDX, BY_IDX, RY_IDX, BY_IDX, RY_IDX, BY_IDX,
|
yading@11
|
827 BY_IDX, RY_IDX, BY_IDX, RY_IDX, BY_IDX, RY_IDX, BY_IDX, RY_IDX,
|
yading@11
|
828 GY_IDX, -1 , GY_IDX, -1 , GY_IDX, -1 , GY_IDX, -1 ,
|
yading@11
|
829 -1 , GY_IDX, -1 , GY_IDX, -1 , GY_IDX, -1 , GY_IDX,
|
yading@11
|
830 RU_IDX, BU_IDX, RU_IDX, BU_IDX, RU_IDX, BU_IDX, RU_IDX, BU_IDX,
|
yading@11
|
831 BU_IDX, RU_IDX, BU_IDX, RU_IDX, BU_IDX, RU_IDX, BU_IDX, RU_IDX,
|
yading@11
|
832 GU_IDX, -1 , GU_IDX, -1 , GU_IDX, -1 , GU_IDX, -1 ,
|
yading@11
|
833 -1 , GU_IDX, -1 , GU_IDX, -1 , GU_IDX, -1 , GU_IDX,
|
yading@11
|
834 RV_IDX, BV_IDX, RV_IDX, BV_IDX, RV_IDX, BV_IDX, RV_IDX, BV_IDX,
|
yading@11
|
835 BV_IDX, RV_IDX, BV_IDX, RV_IDX, BV_IDX, RV_IDX, BV_IDX, RV_IDX,
|
yading@11
|
836 GV_IDX, -1 , GV_IDX, -1 , GV_IDX, -1 , GV_IDX, -1 ,
|
yading@11
|
837 -1 , GV_IDX, -1 , GV_IDX, -1 , GV_IDX, -1 , GV_IDX, //23
|
yading@11
|
838 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //24
|
yading@11
|
839 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //25
|
yading@11
|
840 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //26
|
yading@11
|
841 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //27
|
yading@11
|
842 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //28
|
yading@11
|
843 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //29
|
yading@11
|
844 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //30
|
yading@11
|
845 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , //31
|
yading@11
|
846 BY_IDX, GY_IDX, RY_IDX, -1 , -1 , -1 , -1 , -1 , //32
|
yading@11
|
847 BU_IDX, GU_IDX, RU_IDX, -1 , -1 , -1 , -1 , -1 , //33
|
yading@11
|
848 BV_IDX, GV_IDX, RV_IDX, -1 , -1 , -1 , -1 , -1 , //34
|
yading@11
|
849 };
|
yading@11
|
850
|
yading@11
|
851 dstRange = 0; //FIXME range = 1 is handled elsewhere
|
yading@11
|
852
|
yading@11
|
853 if (!dstRange) {
|
yading@11
|
854 cy = cy * 255 / 219;
|
yading@11
|
855 } else {
|
yading@11
|
856 vr = vr * 224 / 255;
|
yading@11
|
857 ub = ub * 224 / 255;
|
yading@11
|
858 ug = ug * 224 / 255;
|
yading@11
|
859 vg = vg * 224 / 255;
|
yading@11
|
860 }
|
yading@11
|
861 W = ROUNDED_DIV(ONE*ONE*ug, ub);
|
yading@11
|
862 V = ROUNDED_DIV(ONE*ONE*vg, vr);
|
yading@11
|
863 Z = ONE*ONE-W-V;
|
yading@11
|
864
|
yading@11
|
865 Cy = ROUNDED_DIV(cy*Z, ONE);
|
yading@11
|
866 Cu = ROUNDED_DIV(ub*Z, ONE);
|
yading@11
|
867 Cv = ROUNDED_DIV(vr*Z, ONE);
|
yading@11
|
868
|
yading@11
|
869 c->input_rgb2yuv_table[RY_IDX] = -ROUNDED_DIV((1 << RGB2YUV_SHIFT)*V , Cy);
|
yading@11
|
870 c->input_rgb2yuv_table[GY_IDX] = ROUNDED_DIV((1 << RGB2YUV_SHIFT)*ONE*ONE , Cy);
|
yading@11
|
871 c->input_rgb2yuv_table[BY_IDX] = -ROUNDED_DIV((1 << RGB2YUV_SHIFT)*W , Cy);
|
yading@11
|
872
|
yading@11
|
873 c->input_rgb2yuv_table[RU_IDX] = ROUNDED_DIV((1 << RGB2YUV_SHIFT)*V , Cu);
|
yading@11
|
874 c->input_rgb2yuv_table[GU_IDX] = -ROUNDED_DIV((1 << RGB2YUV_SHIFT)*ONE*ONE , Cu);
|
yading@11
|
875 c->input_rgb2yuv_table[BU_IDX] = ROUNDED_DIV((1 << RGB2YUV_SHIFT)*(Z+W) , Cu);
|
yading@11
|
876
|
yading@11
|
877 c->input_rgb2yuv_table[RV_IDX] = ROUNDED_DIV((1 << RGB2YUV_SHIFT)*(V+Z) , Cv);
|
yading@11
|
878 c->input_rgb2yuv_table[GV_IDX] = -ROUNDED_DIV((1 << RGB2YUV_SHIFT)*ONE*ONE , Cv);
|
yading@11
|
879 c->input_rgb2yuv_table[BV_IDX] = ROUNDED_DIV((1 << RGB2YUV_SHIFT)*W , Cv);
|
yading@11
|
880
|
yading@11
|
881 if(/*!dstRange && */table == ff_yuv2rgb_coeffs[SWS_CS_DEFAULT]) {
|
yading@11
|
882 c->input_rgb2yuv_table[BY_IDX] = ((int)(0.114 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
|
yading@11
|
883 c->input_rgb2yuv_table[BV_IDX] = (-(int)(0.081 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
|
yading@11
|
884 c->input_rgb2yuv_table[BU_IDX] = ((int)(0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
|
yading@11
|
885 c->input_rgb2yuv_table[GY_IDX] = ((int)(0.587 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
|
yading@11
|
886 c->input_rgb2yuv_table[GV_IDX] = (-(int)(0.419 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
|
yading@11
|
887 c->input_rgb2yuv_table[GU_IDX] = (-(int)(0.331 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
|
yading@11
|
888 c->input_rgb2yuv_table[RY_IDX] = ((int)(0.299 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
|
yading@11
|
889 c->input_rgb2yuv_table[RV_IDX] = ((int)(0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
|
yading@11
|
890 c->input_rgb2yuv_table[RU_IDX] = (-(int)(0.169 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5));
|
yading@11
|
891 }
|
yading@11
|
892 for(i=0; i<FF_ARRAY_ELEMS(map); i++)
|
yading@11
|
893 AV_WL16(p + 16*4 + 2*i, map[i] >= 0 ? c->input_rgb2yuv_table[map[i]] : 0);
|
yading@11
|
894 }
|
yading@11
|
895
|
yading@11
|
896 int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],
|
yading@11
|
897 int srcRange, const int table[4], int dstRange,
|
yading@11
|
898 int brightness, int contrast, int saturation)
|
yading@11
|
899 {
|
yading@11
|
900 const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat);
|
yading@11
|
901 const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat);
|
yading@11
|
902 memcpy(c->srcColorspaceTable, inv_table, sizeof(int) * 4);
|
yading@11
|
903 memcpy(c->dstColorspaceTable, table, sizeof(int) * 4);
|
yading@11
|
904
|
yading@11
|
905 if(!isYUV(c->dstFormat) && !isGray(c->dstFormat))
|
yading@11
|
906 dstRange = 0;
|
yading@11
|
907 if(!isYUV(c->srcFormat) && !isGray(c->srcFormat))
|
yading@11
|
908 srcRange = 0;
|
yading@11
|
909
|
yading@11
|
910 c->brightness = brightness;
|
yading@11
|
911 c->contrast = contrast;
|
yading@11
|
912 c->saturation = saturation;
|
yading@11
|
913 c->srcRange = srcRange;
|
yading@11
|
914 c->dstRange = dstRange;
|
yading@11
|
915
|
yading@11
|
916 if ((isYUV(c->dstFormat) || isGray(c->dstFormat)) && (isYUV(c->srcFormat) || isGray(c->srcFormat)))
|
yading@11
|
917 return -1;
|
yading@11
|
918
|
yading@11
|
919 c->dstFormatBpp = av_get_bits_per_pixel(desc_dst);
|
yading@11
|
920 c->srcFormatBpp = av_get_bits_per_pixel(desc_src);
|
yading@11
|
921
|
yading@11
|
922 if (!isYUV(c->dstFormat) && !isGray(c->dstFormat)) {
|
yading@11
|
923 ff_yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness,
|
yading@11
|
924 contrast, saturation);
|
yading@11
|
925 // FIXME factorize
|
yading@11
|
926
|
yading@11
|
927 if (HAVE_ALTIVEC && av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)
|
yading@11
|
928 ff_yuv2rgb_init_tables_altivec(c, inv_table, brightness,
|
yading@11
|
929 contrast, saturation);
|
yading@11
|
930 }
|
yading@11
|
931
|
yading@11
|
932 fill_rgb2yuv_table(c, table, dstRange);
|
yading@11
|
933
|
yading@11
|
934 return 0;
|
yading@11
|
935 }
|
yading@11
|
936
|
yading@11
|
937 int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table,
|
yading@11
|
938 int *srcRange, int **table, int *dstRange,
|
yading@11
|
939 int *brightness, int *contrast, int *saturation)
|
yading@11
|
940 {
|
yading@11
|
941 if (!c || isYUV(c->dstFormat) || isGray(c->dstFormat))
|
yading@11
|
942 return -1;
|
yading@11
|
943
|
yading@11
|
944 *inv_table = c->srcColorspaceTable;
|
yading@11
|
945 *table = c->dstColorspaceTable;
|
yading@11
|
946 *srcRange = c->srcRange;
|
yading@11
|
947 *dstRange = c->dstRange;
|
yading@11
|
948 *brightness = c->brightness;
|
yading@11
|
949 *contrast = c->contrast;
|
yading@11
|
950 *saturation = c->saturation;
|
yading@11
|
951
|
yading@11
|
952 return 0;
|
yading@11
|
953 }
|
yading@11
|
954
|
yading@11
|
955 static int handle_jpeg(enum AVPixelFormat *format)
|
yading@11
|
956 {
|
yading@11
|
957 switch (*format) {
|
yading@11
|
958 case AV_PIX_FMT_YUVJ420P:
|
yading@11
|
959 *format = AV_PIX_FMT_YUV420P;
|
yading@11
|
960 return 1;
|
yading@11
|
961 case AV_PIX_FMT_YUVJ422P:
|
yading@11
|
962 *format = AV_PIX_FMT_YUV422P;
|
yading@11
|
963 return 1;
|
yading@11
|
964 case AV_PIX_FMT_YUVJ444P:
|
yading@11
|
965 *format = AV_PIX_FMT_YUV444P;
|
yading@11
|
966 return 1;
|
yading@11
|
967 case AV_PIX_FMT_YUVJ440P:
|
yading@11
|
968 *format = AV_PIX_FMT_YUV440P;
|
yading@11
|
969 return 1;
|
yading@11
|
970 default:
|
yading@11
|
971 return 0;
|
yading@11
|
972 }
|
yading@11
|
973 }
|
yading@11
|
974
|
yading@11
|
975 static int handle_0alpha(enum AVPixelFormat *format)
|
yading@11
|
976 {
|
yading@11
|
977 switch (*format) {
|
yading@11
|
978 case AV_PIX_FMT_0BGR : *format = AV_PIX_FMT_ABGR ; return 1;
|
yading@11
|
979 case AV_PIX_FMT_BGR0 : *format = AV_PIX_FMT_BGRA ; return 4;
|
yading@11
|
980 case AV_PIX_FMT_0RGB : *format = AV_PIX_FMT_ARGB ; return 1;
|
yading@11
|
981 case AV_PIX_FMT_RGB0 : *format = AV_PIX_FMT_RGBA ; return 4;
|
yading@11
|
982 default: return 0;
|
yading@11
|
983 }
|
yading@11
|
984 }
|
yading@11
|
985
|
yading@11
|
986 SwsContext *sws_alloc_context(void)
|
yading@11
|
987 {
|
yading@11
|
988 SwsContext *c = av_mallocz(sizeof(SwsContext));
|
yading@11
|
989
|
yading@11
|
990 if (c) {
|
yading@11
|
991 c->av_class = &sws_context_class;
|
yading@11
|
992 av_opt_set_defaults(c);
|
yading@11
|
993 }
|
yading@11
|
994
|
yading@11
|
995 return c;
|
yading@11
|
996 }
|
yading@11
|
997
|
yading@11
|
998 av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
|
yading@11
|
999 SwsFilter *dstFilter)
|
yading@11
|
1000 {
|
yading@11
|
1001 int i, j;
|
yading@11
|
1002 int usesVFilter, usesHFilter;
|
yading@11
|
1003 int unscaled;
|
yading@11
|
1004 SwsFilter dummyFilter = { NULL, NULL, NULL, NULL };
|
yading@11
|
1005 int srcW = c->srcW;
|
yading@11
|
1006 int srcH = c->srcH;
|
yading@11
|
1007 int dstW = c->dstW;
|
yading@11
|
1008 int dstH = c->dstH;
|
yading@11
|
1009 int dst_stride = FFALIGN(dstW * sizeof(int16_t) + 66, 16);
|
yading@11
|
1010 int flags, cpu_flags;
|
yading@11
|
1011 enum AVPixelFormat srcFormat = c->srcFormat;
|
yading@11
|
1012 enum AVPixelFormat dstFormat = c->dstFormat;
|
yading@11
|
1013 const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(srcFormat);
|
yading@11
|
1014 const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(dstFormat);
|
yading@11
|
1015
|
yading@11
|
1016 cpu_flags = av_get_cpu_flags();
|
yading@11
|
1017 flags = c->flags;
|
yading@11
|
1018 emms_c();
|
yading@11
|
1019 if (!rgb15to16)
|
yading@11
|
1020 sws_rgb2rgb_init();
|
yading@11
|
1021
|
yading@11
|
1022 unscaled = (srcW == dstW && srcH == dstH);
|
yading@11
|
1023
|
yading@11
|
1024 handle_jpeg(&srcFormat);
|
yading@11
|
1025 handle_jpeg(&dstFormat);
|
yading@11
|
1026 handle_0alpha(&srcFormat);
|
yading@11
|
1027 handle_0alpha(&dstFormat);
|
yading@11
|
1028
|
yading@11
|
1029 if(srcFormat!=c->srcFormat || dstFormat!=c->dstFormat){
|
yading@11
|
1030 av_log(c, AV_LOG_WARNING, "deprecated pixel format used, make sure you did set range correctly\n");
|
yading@11
|
1031 c->srcFormat= srcFormat;
|
yading@11
|
1032 c->dstFormat= dstFormat;
|
yading@11
|
1033 }
|
yading@11
|
1034
|
yading@11
|
1035 if (!sws_isSupportedInput(srcFormat)) {
|
yading@11
|
1036 av_log(c, AV_LOG_ERROR, "%s is not supported as input pixel format\n",
|
yading@11
|
1037 av_get_pix_fmt_name(srcFormat));
|
yading@11
|
1038 return AVERROR(EINVAL);
|
yading@11
|
1039 }
|
yading@11
|
1040 if (!sws_isSupportedOutput(dstFormat)) {
|
yading@11
|
1041 av_log(c, AV_LOG_ERROR, "%s is not supported as output pixel format\n",
|
yading@11
|
1042 av_get_pix_fmt_name(dstFormat));
|
yading@11
|
1043 return AVERROR(EINVAL);
|
yading@11
|
1044 }
|
yading@11
|
1045
|
yading@11
|
1046 i = flags & (SWS_POINT |
|
yading@11
|
1047 SWS_AREA |
|
yading@11
|
1048 SWS_BILINEAR |
|
yading@11
|
1049 SWS_FAST_BILINEAR |
|
yading@11
|
1050 SWS_BICUBIC |
|
yading@11
|
1051 SWS_X |
|
yading@11
|
1052 SWS_GAUSS |
|
yading@11
|
1053 SWS_LANCZOS |
|
yading@11
|
1054 SWS_SINC |
|
yading@11
|
1055 SWS_SPLINE |
|
yading@11
|
1056 SWS_BICUBLIN);
|
yading@11
|
1057 if (!i || (i & (i - 1))) {
|
yading@11
|
1058 av_log(c, AV_LOG_ERROR, "Exactly one scaler algorithm must be chosen, got %X\n", i);
|
yading@11
|
1059 return AVERROR(EINVAL);
|
yading@11
|
1060 }
|
yading@11
|
1061 /* sanity check */
|
yading@11
|
1062 if (srcW < 1 || srcH < 1 || dstW < 1 || dstH < 1) {
|
yading@11
|
1063 /* FIXME check if these are enough and try to lower them after
|
yading@11
|
1064 * fixing the relevant parts of the code */
|
yading@11
|
1065 av_log(c, AV_LOG_ERROR, "%dx%d -> %dx%d is invalid scaling dimension\n",
|
yading@11
|
1066 srcW, srcH, dstW, dstH);
|
yading@11
|
1067 return AVERROR(EINVAL);
|
yading@11
|
1068 }
|
yading@11
|
1069
|
yading@11
|
1070 if (!dstFilter)
|
yading@11
|
1071 dstFilter = &dummyFilter;
|
yading@11
|
1072 if (!srcFilter)
|
yading@11
|
1073 srcFilter = &dummyFilter;
|
yading@11
|
1074
|
yading@11
|
1075 c->lumXInc = (((int64_t)srcW << 16) + (dstW >> 1)) / dstW;
|
yading@11
|
1076 c->lumYInc = (((int64_t)srcH << 16) + (dstH >> 1)) / dstH;
|
yading@11
|
1077 c->dstFormatBpp = av_get_bits_per_pixel(desc_dst);
|
yading@11
|
1078 c->srcFormatBpp = av_get_bits_per_pixel(desc_src);
|
yading@11
|
1079 c->vRounder = 4 * 0x0001000100010001ULL;
|
yading@11
|
1080
|
yading@11
|
1081 usesVFilter = (srcFilter->lumV && srcFilter->lumV->length > 1) ||
|
yading@11
|
1082 (srcFilter->chrV && srcFilter->chrV->length > 1) ||
|
yading@11
|
1083 (dstFilter->lumV && dstFilter->lumV->length > 1) ||
|
yading@11
|
1084 (dstFilter->chrV && dstFilter->chrV->length > 1);
|
yading@11
|
1085 usesHFilter = (srcFilter->lumH && srcFilter->lumH->length > 1) ||
|
yading@11
|
1086 (srcFilter->chrH && srcFilter->chrH->length > 1) ||
|
yading@11
|
1087 (dstFilter->lumH && dstFilter->lumH->length > 1) ||
|
yading@11
|
1088 (dstFilter->chrH && dstFilter->chrH->length > 1);
|
yading@11
|
1089
|
yading@11
|
1090 getSubSampleFactors(&c->chrSrcHSubSample, &c->chrSrcVSubSample, srcFormat);
|
yading@11
|
1091 getSubSampleFactors(&c->chrDstHSubSample, &c->chrDstVSubSample, dstFormat);
|
yading@11
|
1092
|
yading@11
|
1093 if (isAnyRGB(dstFormat) && !(flags&SWS_FULL_CHR_H_INT)) {
|
yading@11
|
1094 if (dstW&1) {
|
yading@11
|
1095 av_log(c, AV_LOG_DEBUG, "Forcing full internal H chroma due to odd output size\n");
|
yading@11
|
1096 flags |= SWS_FULL_CHR_H_INT;
|
yading@11
|
1097 c->flags = flags;
|
yading@11
|
1098 }
|
yading@11
|
1099 }
|
yading@11
|
1100
|
yading@11
|
1101 if(dstFormat == AV_PIX_FMT_BGR4_BYTE ||
|
yading@11
|
1102 dstFormat == AV_PIX_FMT_RGB4_BYTE ||
|
yading@11
|
1103 dstFormat == AV_PIX_FMT_BGR8 ||
|
yading@11
|
1104 dstFormat == AV_PIX_FMT_RGB8) {
|
yading@11
|
1105 if (flags & SWS_ERROR_DIFFUSION && !(flags & SWS_FULL_CHR_H_INT)) {
|
yading@11
|
1106 av_log(c, AV_LOG_DEBUG,
|
yading@11
|
1107 "Error diffusion dither is only supported in full chroma interpolation for destination format '%s'\n",
|
yading@11
|
1108 av_get_pix_fmt_name(dstFormat));
|
yading@11
|
1109 flags |= SWS_FULL_CHR_H_INT;
|
yading@11
|
1110 c->flags = flags;
|
yading@11
|
1111 }
|
yading@11
|
1112 if (!(flags & SWS_ERROR_DIFFUSION) && (flags & SWS_FULL_CHR_H_INT)) {
|
yading@11
|
1113 av_log(c, AV_LOG_DEBUG,
|
yading@11
|
1114 "Ordered dither is not supported in full chroma interpolation for destination format '%s'\n",
|
yading@11
|
1115 av_get_pix_fmt_name(dstFormat));
|
yading@11
|
1116 flags |= SWS_ERROR_DIFFUSION;
|
yading@11
|
1117 c->flags = flags;
|
yading@11
|
1118 }
|
yading@11
|
1119 }
|
yading@11
|
1120 if (isPlanarRGB(dstFormat)) {
|
yading@11
|
1121 if (!(flags & SWS_FULL_CHR_H_INT)) {
|
yading@11
|
1122 av_log(c, AV_LOG_DEBUG,
|
yading@11
|
1123 "%s output is not supported with half chroma resolution, switching to full\n",
|
yading@11
|
1124 av_get_pix_fmt_name(dstFormat));
|
yading@11
|
1125 flags |= SWS_FULL_CHR_H_INT;
|
yading@11
|
1126 c->flags = flags;
|
yading@11
|
1127 }
|
yading@11
|
1128 }
|
yading@11
|
1129
|
yading@11
|
1130 /* reuse chroma for 2 pixels RGB/BGR unless user wants full
|
yading@11
|
1131 * chroma interpolation */
|
yading@11
|
1132 if (flags & SWS_FULL_CHR_H_INT &&
|
yading@11
|
1133 isAnyRGB(dstFormat) &&
|
yading@11
|
1134 !isPlanarRGB(dstFormat) &&
|
yading@11
|
1135 dstFormat != AV_PIX_FMT_RGBA &&
|
yading@11
|
1136 dstFormat != AV_PIX_FMT_ARGB &&
|
yading@11
|
1137 dstFormat != AV_PIX_FMT_BGRA &&
|
yading@11
|
1138 dstFormat != AV_PIX_FMT_ABGR &&
|
yading@11
|
1139 dstFormat != AV_PIX_FMT_RGB24 &&
|
yading@11
|
1140 dstFormat != AV_PIX_FMT_BGR24 &&
|
yading@11
|
1141 dstFormat != AV_PIX_FMT_BGR4_BYTE &&
|
yading@11
|
1142 dstFormat != AV_PIX_FMT_RGB4_BYTE &&
|
yading@11
|
1143 dstFormat != AV_PIX_FMT_BGR8 &&
|
yading@11
|
1144 dstFormat != AV_PIX_FMT_RGB8
|
yading@11
|
1145 ) {
|
yading@11
|
1146 av_log(c, AV_LOG_WARNING,
|
yading@11
|
1147 "full chroma interpolation for destination format '%s' not yet implemented\n",
|
yading@11
|
1148 av_get_pix_fmt_name(dstFormat));
|
yading@11
|
1149 flags &= ~SWS_FULL_CHR_H_INT;
|
yading@11
|
1150 c->flags = flags;
|
yading@11
|
1151 }
|
yading@11
|
1152 if (isAnyRGB(dstFormat) && !(flags & SWS_FULL_CHR_H_INT))
|
yading@11
|
1153 c->chrDstHSubSample = 1;
|
yading@11
|
1154
|
yading@11
|
1155 // drop some chroma lines if the user wants it
|
yading@11
|
1156 c->vChrDrop = (flags & SWS_SRC_V_CHR_DROP_MASK) >>
|
yading@11
|
1157 SWS_SRC_V_CHR_DROP_SHIFT;
|
yading@11
|
1158 c->chrSrcVSubSample += c->vChrDrop;
|
yading@11
|
1159
|
yading@11
|
1160 /* drop every other pixel for chroma calculation unless user
|
yading@11
|
1161 * wants full chroma */
|
yading@11
|
1162 if (isAnyRGB(srcFormat) && !(flags & SWS_FULL_CHR_H_INP) &&
|
yading@11
|
1163 srcFormat != AV_PIX_FMT_RGB8 && srcFormat != AV_PIX_FMT_BGR8 &&
|
yading@11
|
1164 srcFormat != AV_PIX_FMT_RGB4 && srcFormat != AV_PIX_FMT_BGR4 &&
|
yading@11
|
1165 srcFormat != AV_PIX_FMT_RGB4_BYTE && srcFormat != AV_PIX_FMT_BGR4_BYTE &&
|
yading@11
|
1166 srcFormat != AV_PIX_FMT_GBRP9BE && srcFormat != AV_PIX_FMT_GBRP9LE &&
|
yading@11
|
1167 srcFormat != AV_PIX_FMT_GBRP10BE && srcFormat != AV_PIX_FMT_GBRP10LE &&
|
yading@11
|
1168 srcFormat != AV_PIX_FMT_GBRP12BE && srcFormat != AV_PIX_FMT_GBRP12LE &&
|
yading@11
|
1169 srcFormat != AV_PIX_FMT_GBRP14BE && srcFormat != AV_PIX_FMT_GBRP14LE &&
|
yading@11
|
1170 srcFormat != AV_PIX_FMT_GBRP16BE && srcFormat != AV_PIX_FMT_GBRP16LE &&
|
yading@11
|
1171 ((dstW >> c->chrDstHSubSample) <= (srcW >> 1) ||
|
yading@11
|
1172 (flags & SWS_FAST_BILINEAR)))
|
yading@11
|
1173 c->chrSrcHSubSample = 1;
|
yading@11
|
1174
|
yading@11
|
1175 // Note the -((-x)>>y) is so that we always round toward +inf.
|
yading@11
|
1176 c->chrSrcW = -((-srcW) >> c->chrSrcHSubSample);
|
yading@11
|
1177 c->chrSrcH = -((-srcH) >> c->chrSrcVSubSample);
|
yading@11
|
1178 c->chrDstW = -((-dstW) >> c->chrDstHSubSample);
|
yading@11
|
1179 c->chrDstH = -((-dstH) >> c->chrDstVSubSample);
|
yading@11
|
1180
|
yading@11
|
1181 FF_ALLOC_OR_GOTO(c, c->formatConvBuffer, FFALIGN(srcW*2+78, 16) * 2, fail);
|
yading@11
|
1182
|
yading@11
|
1183 /* unscaled special cases */
|
yading@11
|
1184 if (unscaled && !usesHFilter && !usesVFilter &&
|
yading@11
|
1185 (c->srcRange == c->dstRange || isAnyRGB(dstFormat))) {
|
yading@11
|
1186 ff_get_unscaled_swscale(c);
|
yading@11
|
1187
|
yading@11
|
1188 if (c->swScale) {
|
yading@11
|
1189 if (flags & SWS_PRINT_INFO)
|
yading@11
|
1190 av_log(c, AV_LOG_INFO,
|
yading@11
|
1191 "using unscaled %s -> %s special converter\n",
|
yading@11
|
1192 av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat));
|
yading@11
|
1193 return 0;
|
yading@11
|
1194 }
|
yading@11
|
1195 }
|
yading@11
|
1196
|
yading@11
|
1197 c->srcBpc = 1 + desc_src->comp[0].depth_minus1;
|
yading@11
|
1198 if (c->srcBpc < 8)
|
yading@11
|
1199 c->srcBpc = 8;
|
yading@11
|
1200 c->dstBpc = 1 + desc_dst->comp[0].depth_minus1;
|
yading@11
|
1201 if (c->dstBpc < 8)
|
yading@11
|
1202 c->dstBpc = 8;
|
yading@11
|
1203 if (isAnyRGB(srcFormat) || srcFormat == AV_PIX_FMT_PAL8)
|
yading@11
|
1204 c->srcBpc = 16;
|
yading@11
|
1205 if (c->dstBpc == 16)
|
yading@11
|
1206 dst_stride <<= 1;
|
yading@11
|
1207
|
yading@11
|
1208 if (INLINE_MMXEXT(cpu_flags) && c->srcBpc == 8 && c->dstBpc <= 14) {
|
yading@11
|
1209 c->canMMXEXTBeUsed = (dstW >= srcW && (dstW & 31) == 0 &&
|
yading@11
|
1210 (srcW & 15) == 0) ? 1 : 0;
|
yading@11
|
1211 if (!c->canMMXEXTBeUsed && dstW >= srcW && (srcW & 15) == 0
|
yading@11
|
1212
|
yading@11
|
1213 && (flags & SWS_FAST_BILINEAR)) {
|
yading@11
|
1214 if (flags & SWS_PRINT_INFO)
|
yading@11
|
1215 av_log(c, AV_LOG_INFO,
|
yading@11
|
1216 "output width is not a multiple of 32 -> no MMXEXT scaler\n");
|
yading@11
|
1217 }
|
yading@11
|
1218 if (usesHFilter || isNBPS(c->srcFormat) || is16BPS(c->srcFormat) || isAnyRGB(c->srcFormat))
|
yading@11
|
1219 c->canMMXEXTBeUsed = 0;
|
yading@11
|
1220 } else
|
yading@11
|
1221 c->canMMXEXTBeUsed = 0;
|
yading@11
|
1222
|
yading@11
|
1223 c->chrXInc = (((int64_t)c->chrSrcW << 16) + (c->chrDstW >> 1)) / c->chrDstW;
|
yading@11
|
1224 c->chrYInc = (((int64_t)c->chrSrcH << 16) + (c->chrDstH >> 1)) / c->chrDstH;
|
yading@11
|
1225
|
yading@11
|
1226 /* Match pixel 0 of the src to pixel 0 of dst and match pixel n-2 of src
|
yading@11
|
1227 * to pixel n-2 of dst, but only for the FAST_BILINEAR mode otherwise do
|
yading@11
|
1228 * correct scaling.
|
yading@11
|
1229 * n-2 is the last chrominance sample available.
|
yading@11
|
1230 * This is not perfect, but no one should notice the difference, the more
|
yading@11
|
1231 * correct variant would be like the vertical one, but that would require
|
yading@11
|
1232 * some special code for the first and last pixel */
|
yading@11
|
1233 if (flags & SWS_FAST_BILINEAR) {
|
yading@11
|
1234 if (c->canMMXEXTBeUsed) {
|
yading@11
|
1235 c->lumXInc += 20;
|
yading@11
|
1236 c->chrXInc += 20;
|
yading@11
|
1237 }
|
yading@11
|
1238 // we don't use the x86 asm scaler if MMX is available
|
yading@11
|
1239 else if (INLINE_MMX(cpu_flags) && c->dstBpc <= 14) {
|
yading@11
|
1240 c->lumXInc = ((int64_t)(srcW - 2) << 16) / (dstW - 2) - 20;
|
yading@11
|
1241 c->chrXInc = ((int64_t)(c->chrSrcW - 2) << 16) / (c->chrDstW - 2) - 20;
|
yading@11
|
1242 }
|
yading@11
|
1243 }
|
yading@11
|
1244
|
yading@11
|
1245 #define USE_MMAP (HAVE_MMAP && HAVE_MPROTECT && defined MAP_ANONYMOUS)
|
yading@11
|
1246
|
yading@11
|
1247 /* precalculate horizontal scaler filter coefficients */
|
yading@11
|
1248 {
|
yading@11
|
1249 #if HAVE_MMXEXT_INLINE
|
yading@11
|
1250 // can't downscale !!!
|
yading@11
|
1251 if (c->canMMXEXTBeUsed && (flags & SWS_FAST_BILINEAR)) {
|
yading@11
|
1252 c->lumMmxextFilterCodeSize = init_hscaler_mmxext(dstW, c->lumXInc, NULL,
|
yading@11
|
1253 NULL, NULL, 8);
|
yading@11
|
1254 c->chrMmxextFilterCodeSize = init_hscaler_mmxext(c->chrDstW, c->chrXInc,
|
yading@11
|
1255 NULL, NULL, NULL, 4);
|
yading@11
|
1256
|
yading@11
|
1257 #if USE_MMAP
|
yading@11
|
1258 c->lumMmxextFilterCode = mmap(NULL, c->lumMmxextFilterCodeSize,
|
yading@11
|
1259 PROT_READ | PROT_WRITE,
|
yading@11
|
1260 MAP_PRIVATE | MAP_ANONYMOUS,
|
yading@11
|
1261 -1, 0);
|
yading@11
|
1262 c->chrMmxextFilterCode = mmap(NULL, c->chrMmxextFilterCodeSize,
|
yading@11
|
1263 PROT_READ | PROT_WRITE,
|
yading@11
|
1264 MAP_PRIVATE | MAP_ANONYMOUS,
|
yading@11
|
1265 -1, 0);
|
yading@11
|
1266 #elif HAVE_VIRTUALALLOC
|
yading@11
|
1267 c->lumMmxextFilterCode = VirtualAlloc(NULL,
|
yading@11
|
1268 c->lumMmxextFilterCodeSize,
|
yading@11
|
1269 MEM_COMMIT,
|
yading@11
|
1270 PAGE_EXECUTE_READWRITE);
|
yading@11
|
1271 c->chrMmxextFilterCode = VirtualAlloc(NULL,
|
yading@11
|
1272 c->chrMmxextFilterCodeSize,
|
yading@11
|
1273 MEM_COMMIT,
|
yading@11
|
1274 PAGE_EXECUTE_READWRITE);
|
yading@11
|
1275 #else
|
yading@11
|
1276 c->lumMmxextFilterCode = av_malloc(c->lumMmxextFilterCodeSize);
|
yading@11
|
1277 c->chrMmxextFilterCode = av_malloc(c->chrMmxextFilterCodeSize);
|
yading@11
|
1278 #endif
|
yading@11
|
1279
|
yading@11
|
1280 #ifdef MAP_ANONYMOUS
|
yading@11
|
1281 if (c->lumMmxextFilterCode == MAP_FAILED || c->chrMmxextFilterCode == MAP_FAILED)
|
yading@11
|
1282 #else
|
yading@11
|
1283 if (!c->lumMmxextFilterCode || !c->chrMmxextFilterCode)
|
yading@11
|
1284 #endif
|
yading@11
|
1285 {
|
yading@11
|
1286 av_log(c, AV_LOG_ERROR, "Failed to allocate MMX2FilterCode\n");
|
yading@11
|
1287 return AVERROR(ENOMEM);
|
yading@11
|
1288 }
|
yading@11
|
1289
|
yading@11
|
1290 FF_ALLOCZ_OR_GOTO(c, c->hLumFilter, (dstW / 8 + 8) * sizeof(int16_t), fail);
|
yading@11
|
1291 FF_ALLOCZ_OR_GOTO(c, c->hChrFilter, (c->chrDstW / 4 + 8) * sizeof(int16_t), fail);
|
yading@11
|
1292 FF_ALLOCZ_OR_GOTO(c, c->hLumFilterPos, (dstW / 2 / 8 + 8) * sizeof(int32_t), fail);
|
yading@11
|
1293 FF_ALLOCZ_OR_GOTO(c, c->hChrFilterPos, (c->chrDstW / 2 / 4 + 8) * sizeof(int32_t), fail);
|
yading@11
|
1294
|
yading@11
|
1295 init_hscaler_mmxext( dstW, c->lumXInc, c->lumMmxextFilterCode,
|
yading@11
|
1296 c->hLumFilter, (uint32_t*)c->hLumFilterPos, 8);
|
yading@11
|
1297 init_hscaler_mmxext(c->chrDstW, c->chrXInc, c->chrMmxextFilterCode,
|
yading@11
|
1298 c->hChrFilter, (uint32_t*)c->hChrFilterPos, 4);
|
yading@11
|
1299
|
yading@11
|
1300 #if USE_MMAP
|
yading@11
|
1301 mprotect(c->lumMmxextFilterCode, c->lumMmxextFilterCodeSize, PROT_EXEC | PROT_READ);
|
yading@11
|
1302 mprotect(c->chrMmxextFilterCode, c->chrMmxextFilterCodeSize, PROT_EXEC | PROT_READ);
|
yading@11
|
1303 #endif
|
yading@11
|
1304 } else
|
yading@11
|
1305 #endif /* HAVE_MMXEXT_INLINE */
|
yading@11
|
1306 {
|
yading@11
|
1307 const int filterAlign =
|
yading@11
|
1308 (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? 4 :
|
yading@11
|
1309 (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) ? 8 :
|
yading@11
|
1310 1;
|
yading@11
|
1311
|
yading@11
|
1312 if (initFilter(&c->hLumFilter, &c->hLumFilterPos,
|
yading@11
|
1313 &c->hLumFilterSize, c->lumXInc,
|
yading@11
|
1314 srcW, dstW, filterAlign, 1 << 14,
|
yading@11
|
1315 (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags,
|
yading@11
|
1316 cpu_flags, srcFilter->lumH, dstFilter->lumH,
|
yading@11
|
1317 c->param) < 0)
|
yading@11
|
1318 goto fail;
|
yading@11
|
1319 if (initFilter(&c->hChrFilter, &c->hChrFilterPos,
|
yading@11
|
1320 &c->hChrFilterSize, c->chrXInc,
|
yading@11
|
1321 c->chrSrcW, c->chrDstW, filterAlign, 1 << 14,
|
yading@11
|
1322 (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags,
|
yading@11
|
1323 cpu_flags, srcFilter->chrH, dstFilter->chrH,
|
yading@11
|
1324 c->param) < 0)
|
yading@11
|
1325 goto fail;
|
yading@11
|
1326 }
|
yading@11
|
1327 } // initialize horizontal stuff
|
yading@11
|
1328
|
yading@11
|
1329 /* precalculate vertical scaler filter coefficients */
|
yading@11
|
1330 {
|
yading@11
|
1331 const int filterAlign =
|
yading@11
|
1332 (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? 2 :
|
yading@11
|
1333 (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) ? 8 :
|
yading@11
|
1334 1;
|
yading@11
|
1335
|
yading@11
|
1336 if (initFilter(&c->vLumFilter, &c->vLumFilterPos, &c->vLumFilterSize,
|
yading@11
|
1337 c->lumYInc, srcH, dstH, filterAlign, (1 << 12),
|
yading@11
|
1338 (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags,
|
yading@11
|
1339 cpu_flags, srcFilter->lumV, dstFilter->lumV,
|
yading@11
|
1340 c->param) < 0)
|
yading@11
|
1341 goto fail;
|
yading@11
|
1342 if (initFilter(&c->vChrFilter, &c->vChrFilterPos, &c->vChrFilterSize,
|
yading@11
|
1343 c->chrYInc, c->chrSrcH, c->chrDstH,
|
yading@11
|
1344 filterAlign, (1 << 12),
|
yading@11
|
1345 (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags,
|
yading@11
|
1346 cpu_flags, srcFilter->chrV, dstFilter->chrV,
|
yading@11
|
1347 c->param) < 0)
|
yading@11
|
1348 goto fail;
|
yading@11
|
1349
|
yading@11
|
1350 #if HAVE_ALTIVEC
|
yading@11
|
1351 FF_ALLOC_OR_GOTO(c, c->vYCoeffsBank, sizeof(vector signed short) * c->vLumFilterSize * c->dstH, fail);
|
yading@11
|
1352 FF_ALLOC_OR_GOTO(c, c->vCCoeffsBank, sizeof(vector signed short) * c->vChrFilterSize * c->chrDstH, fail);
|
yading@11
|
1353
|
yading@11
|
1354 for (i = 0; i < c->vLumFilterSize * c->dstH; i++) {
|
yading@11
|
1355 int j;
|
yading@11
|
1356 short *p = (short *)&c->vYCoeffsBank[i];
|
yading@11
|
1357 for (j = 0; j < 8; j++)
|
yading@11
|
1358 p[j] = c->vLumFilter[i];
|
yading@11
|
1359 }
|
yading@11
|
1360
|
yading@11
|
1361 for (i = 0; i < c->vChrFilterSize * c->chrDstH; i++) {
|
yading@11
|
1362 int j;
|
yading@11
|
1363 short *p = (short *)&c->vCCoeffsBank[i];
|
yading@11
|
1364 for (j = 0; j < 8; j++)
|
yading@11
|
1365 p[j] = c->vChrFilter[i];
|
yading@11
|
1366 }
|
yading@11
|
1367 #endif
|
yading@11
|
1368 }
|
yading@11
|
1369
|
yading@11
|
1370 // calculate buffer sizes so that they won't run out while handling these damn slices
|
yading@11
|
1371 c->vLumBufSize = c->vLumFilterSize;
|
yading@11
|
1372 c->vChrBufSize = c->vChrFilterSize;
|
yading@11
|
1373 for (i = 0; i < dstH; i++) {
|
yading@11
|
1374 int chrI = (int64_t)i * c->chrDstH / dstH;
|
yading@11
|
1375 int nextSlice = FFMAX(c->vLumFilterPos[i] + c->vLumFilterSize - 1,
|
yading@11
|
1376 ((c->vChrFilterPos[chrI] + c->vChrFilterSize - 1)
|
yading@11
|
1377 << c->chrSrcVSubSample));
|
yading@11
|
1378
|
yading@11
|
1379 nextSlice >>= c->chrSrcVSubSample;
|
yading@11
|
1380 nextSlice <<= c->chrSrcVSubSample;
|
yading@11
|
1381 if (c->vLumFilterPos[i] + c->vLumBufSize < nextSlice)
|
yading@11
|
1382 c->vLumBufSize = nextSlice - c->vLumFilterPos[i];
|
yading@11
|
1383 if (c->vChrFilterPos[chrI] + c->vChrBufSize <
|
yading@11
|
1384 (nextSlice >> c->chrSrcVSubSample))
|
yading@11
|
1385 c->vChrBufSize = (nextSlice >> c->chrSrcVSubSample) -
|
yading@11
|
1386 c->vChrFilterPos[chrI];
|
yading@11
|
1387 }
|
yading@11
|
1388
|
yading@11
|
1389 for (i = 0; i < 4; i++)
|
yading@11
|
1390 FF_ALLOCZ_OR_GOTO(c, c->dither_error[i], (c->dstW+2) * sizeof(int), fail);
|
yading@11
|
1391
|
yading@11
|
1392 /* Allocate pixbufs (we use dynamic allocation because otherwise we would
|
yading@11
|
1393 * need to allocate several megabytes to handle all possible cases) */
|
yading@11
|
1394 FF_ALLOC_OR_GOTO(c, c->lumPixBuf, c->vLumBufSize * 3 * sizeof(int16_t *), fail);
|
yading@11
|
1395 FF_ALLOC_OR_GOTO(c, c->chrUPixBuf, c->vChrBufSize * 3 * sizeof(int16_t *), fail);
|
yading@11
|
1396 FF_ALLOC_OR_GOTO(c, c->chrVPixBuf, c->vChrBufSize * 3 * sizeof(int16_t *), fail);
|
yading@11
|
1397 if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat) && isALPHA(c->dstFormat))
|
yading@11
|
1398 FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf, c->vLumBufSize * 3 * sizeof(int16_t *), fail);
|
yading@11
|
1399 /* Note we need at least one pixel more at the end because of the MMX code
|
yading@11
|
1400 * (just in case someone wants to replace the 4000/8000). */
|
yading@11
|
1401 /* align at 16 bytes for AltiVec */
|
yading@11
|
1402 for (i = 0; i < c->vLumBufSize; i++) {
|
yading@11
|
1403 FF_ALLOCZ_OR_GOTO(c, c->lumPixBuf[i + c->vLumBufSize],
|
yading@11
|
1404 dst_stride + 16, fail);
|
yading@11
|
1405 c->lumPixBuf[i] = c->lumPixBuf[i + c->vLumBufSize];
|
yading@11
|
1406 }
|
yading@11
|
1407 // 64 / c->scalingBpp is the same as 16 / sizeof(scaling_intermediate)
|
yading@11
|
1408 c->uv_off = (dst_stride>>1) + 64 / (c->dstBpc &~ 7);
|
yading@11
|
1409 c->uv_offx2 = dst_stride + 16;
|
yading@11
|
1410 for (i = 0; i < c->vChrBufSize; i++) {
|
yading@11
|
1411 FF_ALLOC_OR_GOTO(c, c->chrUPixBuf[i + c->vChrBufSize],
|
yading@11
|
1412 dst_stride * 2 + 32, fail);
|
yading@11
|
1413 c->chrUPixBuf[i] = c->chrUPixBuf[i + c->vChrBufSize];
|
yading@11
|
1414 c->chrVPixBuf[i] = c->chrVPixBuf[i + c->vChrBufSize]
|
yading@11
|
1415 = c->chrUPixBuf[i] + (dst_stride >> 1) + 8;
|
yading@11
|
1416 }
|
yading@11
|
1417 if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
|
yading@11
|
1418 for (i = 0; i < c->vLumBufSize; i++) {
|
yading@11
|
1419 FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf[i + c->vLumBufSize],
|
yading@11
|
1420 dst_stride + 16, fail);
|
yading@11
|
1421 c->alpPixBuf[i] = c->alpPixBuf[i + c->vLumBufSize];
|
yading@11
|
1422 }
|
yading@11
|
1423
|
yading@11
|
1424 // try to avoid drawing green stuff between the right end and the stride end
|
yading@11
|
1425 for (i = 0; i < c->vChrBufSize; i++)
|
yading@11
|
1426 if(desc_dst->comp[0].depth_minus1 == 15){
|
yading@11
|
1427 av_assert0(c->dstBpc > 14);
|
yading@11
|
1428 for(j=0; j<dst_stride/2+1; j++)
|
yading@11
|
1429 ((int32_t*)(c->chrUPixBuf[i]))[j] = 1<<18;
|
yading@11
|
1430 } else
|
yading@11
|
1431 for(j=0; j<dst_stride+1; j++)
|
yading@11
|
1432 ((int16_t*)(c->chrUPixBuf[i]))[j] = 1<<14;
|
yading@11
|
1433
|
yading@11
|
1434 av_assert0(c->chrDstH <= dstH);
|
yading@11
|
1435
|
yading@11
|
1436 if (flags & SWS_PRINT_INFO) {
|
yading@11
|
1437 if (flags & SWS_FAST_BILINEAR)
|
yading@11
|
1438 av_log(c, AV_LOG_INFO, "FAST_BILINEAR scaler, ");
|
yading@11
|
1439 else if (flags & SWS_BILINEAR)
|
yading@11
|
1440 av_log(c, AV_LOG_INFO, "BILINEAR scaler, ");
|
yading@11
|
1441 else if (flags & SWS_BICUBIC)
|
yading@11
|
1442 av_log(c, AV_LOG_INFO, "BICUBIC scaler, ");
|
yading@11
|
1443 else if (flags & SWS_X)
|
yading@11
|
1444 av_log(c, AV_LOG_INFO, "Experimental scaler, ");
|
yading@11
|
1445 else if (flags & SWS_POINT)
|
yading@11
|
1446 av_log(c, AV_LOG_INFO, "Nearest Neighbor / POINT scaler, ");
|
yading@11
|
1447 else if (flags & SWS_AREA)
|
yading@11
|
1448 av_log(c, AV_LOG_INFO, "Area Averaging scaler, ");
|
yading@11
|
1449 else if (flags & SWS_BICUBLIN)
|
yading@11
|
1450 av_log(c, AV_LOG_INFO, "luma BICUBIC / chroma BILINEAR scaler, ");
|
yading@11
|
1451 else if (flags & SWS_GAUSS)
|
yading@11
|
1452 av_log(c, AV_LOG_INFO, "Gaussian scaler, ");
|
yading@11
|
1453 else if (flags & SWS_SINC)
|
yading@11
|
1454 av_log(c, AV_LOG_INFO, "Sinc scaler, ");
|
yading@11
|
1455 else if (flags & SWS_LANCZOS)
|
yading@11
|
1456 av_log(c, AV_LOG_INFO, "Lanczos scaler, ");
|
yading@11
|
1457 else if (flags & SWS_SPLINE)
|
yading@11
|
1458 av_log(c, AV_LOG_INFO, "Bicubic spline scaler, ");
|
yading@11
|
1459 else
|
yading@11
|
1460 av_log(c, AV_LOG_INFO, "ehh flags invalid?! ");
|
yading@11
|
1461
|
yading@11
|
1462 av_log(c, AV_LOG_INFO, "from %s to %s%s ",
|
yading@11
|
1463 av_get_pix_fmt_name(srcFormat),
|
yading@11
|
1464 #ifdef DITHER1XBPP
|
yading@11
|
1465 dstFormat == AV_PIX_FMT_BGR555 || dstFormat == AV_PIX_FMT_BGR565 ||
|
yading@11
|
1466 dstFormat == AV_PIX_FMT_RGB444BE || dstFormat == AV_PIX_FMT_RGB444LE ||
|
yading@11
|
1467 dstFormat == AV_PIX_FMT_BGR444BE || dstFormat == AV_PIX_FMT_BGR444LE ?
|
yading@11
|
1468 "dithered " : "",
|
yading@11
|
1469 #else
|
yading@11
|
1470 "",
|
yading@11
|
1471 #endif
|
yading@11
|
1472 av_get_pix_fmt_name(dstFormat));
|
yading@11
|
1473
|
yading@11
|
1474 if (INLINE_MMXEXT(cpu_flags))
|
yading@11
|
1475 av_log(c, AV_LOG_INFO, "using MMXEXT\n");
|
yading@11
|
1476 else if (INLINE_AMD3DNOW(cpu_flags))
|
yading@11
|
1477 av_log(c, AV_LOG_INFO, "using 3DNOW\n");
|
yading@11
|
1478 else if (INLINE_MMX(cpu_flags))
|
yading@11
|
1479 av_log(c, AV_LOG_INFO, "using MMX\n");
|
yading@11
|
1480 else if (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC)
|
yading@11
|
1481 av_log(c, AV_LOG_INFO, "using AltiVec\n");
|
yading@11
|
1482 else
|
yading@11
|
1483 av_log(c, AV_LOG_INFO, "using C\n");
|
yading@11
|
1484
|
yading@11
|
1485 av_log(c, AV_LOG_VERBOSE, "%dx%d -> %dx%d\n", srcW, srcH, dstW, dstH);
|
yading@11
|
1486 av_log(c, AV_LOG_DEBUG,
|
yading@11
|
1487 "lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
|
yading@11
|
1488 c->srcW, c->srcH, c->dstW, c->dstH, c->lumXInc, c->lumYInc);
|
yading@11
|
1489 av_log(c, AV_LOG_DEBUG,
|
yading@11
|
1490 "chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",
|
yading@11
|
1491 c->chrSrcW, c->chrSrcH, c->chrDstW, c->chrDstH,
|
yading@11
|
1492 c->chrXInc, c->chrYInc);
|
yading@11
|
1493 }
|
yading@11
|
1494
|
yading@11
|
1495 c->swScale = ff_getSwsFunc(c);
|
yading@11
|
1496 return 0;
|
yading@11
|
1497 fail: // FIXME replace things by appropriate error codes
|
yading@11
|
1498 return -1;
|
yading@11
|
1499 }
|
yading@11
|
1500
|
yading@11
|
1501 #if FF_API_SWS_GETCONTEXT
|
yading@11
|
1502 SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,
|
yading@11
|
1503 int dstW, int dstH, enum AVPixelFormat dstFormat,
|
yading@11
|
1504 int flags, SwsFilter *srcFilter,
|
yading@11
|
1505 SwsFilter *dstFilter, const double *param)
|
yading@11
|
1506 {
|
yading@11
|
1507 SwsContext *c;
|
yading@11
|
1508
|
yading@11
|
1509 if (!(c = sws_alloc_context()))
|
yading@11
|
1510 return NULL;
|
yading@11
|
1511
|
yading@11
|
1512 c->flags = flags;
|
yading@11
|
1513 c->srcW = srcW;
|
yading@11
|
1514 c->srcH = srcH;
|
yading@11
|
1515 c->dstW = dstW;
|
yading@11
|
1516 c->dstH = dstH;
|
yading@11
|
1517 c->srcRange = handle_jpeg(&srcFormat);
|
yading@11
|
1518 c->dstRange = handle_jpeg(&dstFormat);
|
yading@11
|
1519 c->src0Alpha = handle_0alpha(&srcFormat);
|
yading@11
|
1520 c->dst0Alpha = handle_0alpha(&dstFormat);
|
yading@11
|
1521 c->srcFormat = srcFormat;
|
yading@11
|
1522 c->dstFormat = dstFormat;
|
yading@11
|
1523
|
yading@11
|
1524 if (param) {
|
yading@11
|
1525 c->param[0] = param[0];
|
yading@11
|
1526 c->param[1] = param[1];
|
yading@11
|
1527 }
|
yading@11
|
1528 sws_setColorspaceDetails(c, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], c->srcRange,
|
yading@11
|
1529 ff_yuv2rgb_coeffs[SWS_CS_DEFAULT] /* FIXME*/,
|
yading@11
|
1530 c->dstRange, 0, 1 << 16, 1 << 16);
|
yading@11
|
1531
|
yading@11
|
1532 if (sws_init_context(c, srcFilter, dstFilter) < 0) {
|
yading@11
|
1533 sws_freeContext(c);
|
yading@11
|
1534 return NULL;
|
yading@11
|
1535 }
|
yading@11
|
1536
|
yading@11
|
1537 return c;
|
yading@11
|
1538 }
|
yading@11
|
1539 #endif
|
yading@11
|
1540
|
yading@11
|
1541 SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur,
|
yading@11
|
1542 float lumaSharpen, float chromaSharpen,
|
yading@11
|
1543 float chromaHShift, float chromaVShift,
|
yading@11
|
1544 int verbose)
|
yading@11
|
1545 {
|
yading@11
|
1546 SwsFilter *filter = av_malloc(sizeof(SwsFilter));
|
yading@11
|
1547 if (!filter)
|
yading@11
|
1548 return NULL;
|
yading@11
|
1549
|
yading@11
|
1550 if (lumaGBlur != 0.0) {
|
yading@11
|
1551 filter->lumH = sws_getGaussianVec(lumaGBlur, 3.0);
|
yading@11
|
1552 filter->lumV = sws_getGaussianVec(lumaGBlur, 3.0);
|
yading@11
|
1553 } else {
|
yading@11
|
1554 filter->lumH = sws_getIdentityVec();
|
yading@11
|
1555 filter->lumV = sws_getIdentityVec();
|
yading@11
|
1556 }
|
yading@11
|
1557
|
yading@11
|
1558 if (chromaGBlur != 0.0) {
|
yading@11
|
1559 filter->chrH = sws_getGaussianVec(chromaGBlur, 3.0);
|
yading@11
|
1560 filter->chrV = sws_getGaussianVec(chromaGBlur, 3.0);
|
yading@11
|
1561 } else {
|
yading@11
|
1562 filter->chrH = sws_getIdentityVec();
|
yading@11
|
1563 filter->chrV = sws_getIdentityVec();
|
yading@11
|
1564 }
|
yading@11
|
1565
|
yading@11
|
1566 if (chromaSharpen != 0.0) {
|
yading@11
|
1567 SwsVector *id = sws_getIdentityVec();
|
yading@11
|
1568 sws_scaleVec(filter->chrH, -chromaSharpen);
|
yading@11
|
1569 sws_scaleVec(filter->chrV, -chromaSharpen);
|
yading@11
|
1570 sws_addVec(filter->chrH, id);
|
yading@11
|
1571 sws_addVec(filter->chrV, id);
|
yading@11
|
1572 sws_freeVec(id);
|
yading@11
|
1573 }
|
yading@11
|
1574
|
yading@11
|
1575 if (lumaSharpen != 0.0) {
|
yading@11
|
1576 SwsVector *id = sws_getIdentityVec();
|
yading@11
|
1577 sws_scaleVec(filter->lumH, -lumaSharpen);
|
yading@11
|
1578 sws_scaleVec(filter->lumV, -lumaSharpen);
|
yading@11
|
1579 sws_addVec(filter->lumH, id);
|
yading@11
|
1580 sws_addVec(filter->lumV, id);
|
yading@11
|
1581 sws_freeVec(id);
|
yading@11
|
1582 }
|
yading@11
|
1583
|
yading@11
|
1584 if (chromaHShift != 0.0)
|
yading@11
|
1585 sws_shiftVec(filter->chrH, (int)(chromaHShift + 0.5));
|
yading@11
|
1586
|
yading@11
|
1587 if (chromaVShift != 0.0)
|
yading@11
|
1588 sws_shiftVec(filter->chrV, (int)(chromaVShift + 0.5));
|
yading@11
|
1589
|
yading@11
|
1590 sws_normalizeVec(filter->chrH, 1.0);
|
yading@11
|
1591 sws_normalizeVec(filter->chrV, 1.0);
|
yading@11
|
1592 sws_normalizeVec(filter->lumH, 1.0);
|
yading@11
|
1593 sws_normalizeVec(filter->lumV, 1.0);
|
yading@11
|
1594
|
yading@11
|
1595 if (verbose)
|
yading@11
|
1596 sws_printVec2(filter->chrH, NULL, AV_LOG_DEBUG);
|
yading@11
|
1597 if (verbose)
|
yading@11
|
1598 sws_printVec2(filter->lumH, NULL, AV_LOG_DEBUG);
|
yading@11
|
1599
|
yading@11
|
1600 return filter;
|
yading@11
|
1601 }
|
yading@11
|
1602
|
yading@11
|
1603 SwsVector *sws_allocVec(int length)
|
yading@11
|
1604 {
|
yading@11
|
1605 SwsVector *vec;
|
yading@11
|
1606
|
yading@11
|
1607 if(length <= 0 || length > INT_MAX/ sizeof(double))
|
yading@11
|
1608 return NULL;
|
yading@11
|
1609
|
yading@11
|
1610 vec = av_malloc(sizeof(SwsVector));
|
yading@11
|
1611 if (!vec)
|
yading@11
|
1612 return NULL;
|
yading@11
|
1613 vec->length = length;
|
yading@11
|
1614 vec->coeff = av_malloc(sizeof(double) * length);
|
yading@11
|
1615 if (!vec->coeff)
|
yading@11
|
1616 av_freep(&vec);
|
yading@11
|
1617 return vec;
|
yading@11
|
1618 }
|
yading@11
|
1619
|
yading@11
|
1620 SwsVector *sws_getGaussianVec(double variance, double quality)
|
yading@11
|
1621 {
|
yading@11
|
1622 const int length = (int)(variance * quality + 0.5) | 1;
|
yading@11
|
1623 int i;
|
yading@11
|
1624 double middle = (length - 1) * 0.5;
|
yading@11
|
1625 SwsVector *vec;
|
yading@11
|
1626
|
yading@11
|
1627 if(variance < 0 || quality < 0)
|
yading@11
|
1628 return NULL;
|
yading@11
|
1629
|
yading@11
|
1630 vec = sws_allocVec(length);
|
yading@11
|
1631
|
yading@11
|
1632 if (!vec)
|
yading@11
|
1633 return NULL;
|
yading@11
|
1634
|
yading@11
|
1635 for (i = 0; i < length; i++) {
|
yading@11
|
1636 double dist = i - middle;
|
yading@11
|
1637 vec->coeff[i] = exp(-dist * dist / (2 * variance * variance)) /
|
yading@11
|
1638 sqrt(2 * variance * M_PI);
|
yading@11
|
1639 }
|
yading@11
|
1640
|
yading@11
|
1641 sws_normalizeVec(vec, 1.0);
|
yading@11
|
1642
|
yading@11
|
1643 return vec;
|
yading@11
|
1644 }
|
yading@11
|
1645
|
yading@11
|
1646 SwsVector *sws_getConstVec(double c, int length)
|
yading@11
|
1647 {
|
yading@11
|
1648 int i;
|
yading@11
|
1649 SwsVector *vec = sws_allocVec(length);
|
yading@11
|
1650
|
yading@11
|
1651 if (!vec)
|
yading@11
|
1652 return NULL;
|
yading@11
|
1653
|
yading@11
|
1654 for (i = 0; i < length; i++)
|
yading@11
|
1655 vec->coeff[i] = c;
|
yading@11
|
1656
|
yading@11
|
1657 return vec;
|
yading@11
|
1658 }
|
yading@11
|
1659
|
yading@11
|
1660 SwsVector *sws_getIdentityVec(void)
|
yading@11
|
1661 {
|
yading@11
|
1662 return sws_getConstVec(1.0, 1);
|
yading@11
|
1663 }
|
yading@11
|
1664
|
yading@11
|
1665 static double sws_dcVec(SwsVector *a)
|
yading@11
|
1666 {
|
yading@11
|
1667 int i;
|
yading@11
|
1668 double sum = 0;
|
yading@11
|
1669
|
yading@11
|
1670 for (i = 0; i < a->length; i++)
|
yading@11
|
1671 sum += a->coeff[i];
|
yading@11
|
1672
|
yading@11
|
1673 return sum;
|
yading@11
|
1674 }
|
yading@11
|
1675
|
yading@11
|
1676 void sws_scaleVec(SwsVector *a, double scalar)
|
yading@11
|
1677 {
|
yading@11
|
1678 int i;
|
yading@11
|
1679
|
yading@11
|
1680 for (i = 0; i < a->length; i++)
|
yading@11
|
1681 a->coeff[i] *= scalar;
|
yading@11
|
1682 }
|
yading@11
|
1683
|
yading@11
|
1684 void sws_normalizeVec(SwsVector *a, double height)
|
yading@11
|
1685 {
|
yading@11
|
1686 sws_scaleVec(a, height / sws_dcVec(a));
|
yading@11
|
1687 }
|
yading@11
|
1688
|
yading@11
|
1689 static SwsVector *sws_getConvVec(SwsVector *a, SwsVector *b)
|
yading@11
|
1690 {
|
yading@11
|
1691 int length = a->length + b->length - 1;
|
yading@11
|
1692 int i, j;
|
yading@11
|
1693 SwsVector *vec = sws_getConstVec(0.0, length);
|
yading@11
|
1694
|
yading@11
|
1695 if (!vec)
|
yading@11
|
1696 return NULL;
|
yading@11
|
1697
|
yading@11
|
1698 for (i = 0; i < a->length; i++) {
|
yading@11
|
1699 for (j = 0; j < b->length; j++) {
|
yading@11
|
1700 vec->coeff[i + j] += a->coeff[i] * b->coeff[j];
|
yading@11
|
1701 }
|
yading@11
|
1702 }
|
yading@11
|
1703
|
yading@11
|
1704 return vec;
|
yading@11
|
1705 }
|
yading@11
|
1706
|
yading@11
|
1707 static SwsVector *sws_sumVec(SwsVector *a, SwsVector *b)
|
yading@11
|
1708 {
|
yading@11
|
1709 int length = FFMAX(a->length, b->length);
|
yading@11
|
1710 int i;
|
yading@11
|
1711 SwsVector *vec = sws_getConstVec(0.0, length);
|
yading@11
|
1712
|
yading@11
|
1713 if (!vec)
|
yading@11
|
1714 return NULL;
|
yading@11
|
1715
|
yading@11
|
1716 for (i = 0; i < a->length; i++)
|
yading@11
|
1717 vec->coeff[i + (length - 1) / 2 - (a->length - 1) / 2] += a->coeff[i];
|
yading@11
|
1718 for (i = 0; i < b->length; i++)
|
yading@11
|
1719 vec->coeff[i + (length - 1) / 2 - (b->length - 1) / 2] += b->coeff[i];
|
yading@11
|
1720
|
yading@11
|
1721 return vec;
|
yading@11
|
1722 }
|
yading@11
|
1723
|
yading@11
|
1724 static SwsVector *sws_diffVec(SwsVector *a, SwsVector *b)
|
yading@11
|
1725 {
|
yading@11
|
1726 int length = FFMAX(a->length, b->length);
|
yading@11
|
1727 int i;
|
yading@11
|
1728 SwsVector *vec = sws_getConstVec(0.0, length);
|
yading@11
|
1729
|
yading@11
|
1730 if (!vec)
|
yading@11
|
1731 return NULL;
|
yading@11
|
1732
|
yading@11
|
1733 for (i = 0; i < a->length; i++)
|
yading@11
|
1734 vec->coeff[i + (length - 1) / 2 - (a->length - 1) / 2] += a->coeff[i];
|
yading@11
|
1735 for (i = 0; i < b->length; i++)
|
yading@11
|
1736 vec->coeff[i + (length - 1) / 2 - (b->length - 1) / 2] -= b->coeff[i];
|
yading@11
|
1737
|
yading@11
|
1738 return vec;
|
yading@11
|
1739 }
|
yading@11
|
1740
|
yading@11
|
1741 /* shift left / or right if "shift" is negative */
|
yading@11
|
1742 static SwsVector *sws_getShiftedVec(SwsVector *a, int shift)
|
yading@11
|
1743 {
|
yading@11
|
1744 int length = a->length + FFABS(shift) * 2;
|
yading@11
|
1745 int i;
|
yading@11
|
1746 SwsVector *vec = sws_getConstVec(0.0, length);
|
yading@11
|
1747
|
yading@11
|
1748 if (!vec)
|
yading@11
|
1749 return NULL;
|
yading@11
|
1750
|
yading@11
|
1751 for (i = 0; i < a->length; i++) {
|
yading@11
|
1752 vec->coeff[i + (length - 1) / 2 -
|
yading@11
|
1753 (a->length - 1) / 2 - shift] = a->coeff[i];
|
yading@11
|
1754 }
|
yading@11
|
1755
|
yading@11
|
1756 return vec;
|
yading@11
|
1757 }
|
yading@11
|
1758
|
yading@11
|
1759 void sws_shiftVec(SwsVector *a, int shift)
|
yading@11
|
1760 {
|
yading@11
|
1761 SwsVector *shifted = sws_getShiftedVec(a, shift);
|
yading@11
|
1762 av_free(a->coeff);
|
yading@11
|
1763 a->coeff = shifted->coeff;
|
yading@11
|
1764 a->length = shifted->length;
|
yading@11
|
1765 av_free(shifted);
|
yading@11
|
1766 }
|
yading@11
|
1767
|
yading@11
|
1768 void sws_addVec(SwsVector *a, SwsVector *b)
|
yading@11
|
1769 {
|
yading@11
|
1770 SwsVector *sum = sws_sumVec(a, b);
|
yading@11
|
1771 av_free(a->coeff);
|
yading@11
|
1772 a->coeff = sum->coeff;
|
yading@11
|
1773 a->length = sum->length;
|
yading@11
|
1774 av_free(sum);
|
yading@11
|
1775 }
|
yading@11
|
1776
|
yading@11
|
1777 void sws_subVec(SwsVector *a, SwsVector *b)
|
yading@11
|
1778 {
|
yading@11
|
1779 SwsVector *diff = sws_diffVec(a, b);
|
yading@11
|
1780 av_free(a->coeff);
|
yading@11
|
1781 a->coeff = diff->coeff;
|
yading@11
|
1782 a->length = diff->length;
|
yading@11
|
1783 av_free(diff);
|
yading@11
|
1784 }
|
yading@11
|
1785
|
yading@11
|
1786 void sws_convVec(SwsVector *a, SwsVector *b)
|
yading@11
|
1787 {
|
yading@11
|
1788 SwsVector *conv = sws_getConvVec(a, b);
|
yading@11
|
1789 av_free(a->coeff);
|
yading@11
|
1790 a->coeff = conv->coeff;
|
yading@11
|
1791 a->length = conv->length;
|
yading@11
|
1792 av_free(conv);
|
yading@11
|
1793 }
|
yading@11
|
1794
|
yading@11
|
1795 SwsVector *sws_cloneVec(SwsVector *a)
|
yading@11
|
1796 {
|
yading@11
|
1797 int i;
|
yading@11
|
1798 SwsVector *vec = sws_allocVec(a->length);
|
yading@11
|
1799
|
yading@11
|
1800 if (!vec)
|
yading@11
|
1801 return NULL;
|
yading@11
|
1802
|
yading@11
|
1803 for (i = 0; i < a->length; i++)
|
yading@11
|
1804 vec->coeff[i] = a->coeff[i];
|
yading@11
|
1805
|
yading@11
|
1806 return vec;
|
yading@11
|
1807 }
|
yading@11
|
1808
|
yading@11
|
1809 void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level)
|
yading@11
|
1810 {
|
yading@11
|
1811 int i;
|
yading@11
|
1812 double max = 0;
|
yading@11
|
1813 double min = 0;
|
yading@11
|
1814 double range;
|
yading@11
|
1815
|
yading@11
|
1816 for (i = 0; i < a->length; i++)
|
yading@11
|
1817 if (a->coeff[i] > max)
|
yading@11
|
1818 max = a->coeff[i];
|
yading@11
|
1819
|
yading@11
|
1820 for (i = 0; i < a->length; i++)
|
yading@11
|
1821 if (a->coeff[i] < min)
|
yading@11
|
1822 min = a->coeff[i];
|
yading@11
|
1823
|
yading@11
|
1824 range = max - min;
|
yading@11
|
1825
|
yading@11
|
1826 for (i = 0; i < a->length; i++) {
|
yading@11
|
1827 int x = (int)((a->coeff[i] - min) * 60.0 / range + 0.5);
|
yading@11
|
1828 av_log(log_ctx, log_level, "%1.3f ", a->coeff[i]);
|
yading@11
|
1829 for (; x > 0; x--)
|
yading@11
|
1830 av_log(log_ctx, log_level, " ");
|
yading@11
|
1831 av_log(log_ctx, log_level, "|\n");
|
yading@11
|
1832 }
|
yading@11
|
1833 }
|
yading@11
|
1834
|
yading@11
|
1835 void sws_freeVec(SwsVector *a)
|
yading@11
|
1836 {
|
yading@11
|
1837 if (!a)
|
yading@11
|
1838 return;
|
yading@11
|
1839 av_freep(&a->coeff);
|
yading@11
|
1840 a->length = 0;
|
yading@11
|
1841 av_free(a);
|
yading@11
|
1842 }
|
yading@11
|
1843
|
yading@11
|
1844 void sws_freeFilter(SwsFilter *filter)
|
yading@11
|
1845 {
|
yading@11
|
1846 if (!filter)
|
yading@11
|
1847 return;
|
yading@11
|
1848
|
yading@11
|
1849 if (filter->lumH)
|
yading@11
|
1850 sws_freeVec(filter->lumH);
|
yading@11
|
1851 if (filter->lumV)
|
yading@11
|
1852 sws_freeVec(filter->lumV);
|
yading@11
|
1853 if (filter->chrH)
|
yading@11
|
1854 sws_freeVec(filter->chrH);
|
yading@11
|
1855 if (filter->chrV)
|
yading@11
|
1856 sws_freeVec(filter->chrV);
|
yading@11
|
1857 av_free(filter);
|
yading@11
|
1858 }
|
yading@11
|
1859
|
yading@11
|
1860 void sws_freeContext(SwsContext *c)
|
yading@11
|
1861 {
|
yading@11
|
1862 int i;
|
yading@11
|
1863 if (!c)
|
yading@11
|
1864 return;
|
yading@11
|
1865
|
yading@11
|
1866 if (c->lumPixBuf) {
|
yading@11
|
1867 for (i = 0; i < c->vLumBufSize; i++)
|
yading@11
|
1868 av_freep(&c->lumPixBuf[i]);
|
yading@11
|
1869 av_freep(&c->lumPixBuf);
|
yading@11
|
1870 }
|
yading@11
|
1871
|
yading@11
|
1872 if (c->chrUPixBuf) {
|
yading@11
|
1873 for (i = 0; i < c->vChrBufSize; i++)
|
yading@11
|
1874 av_freep(&c->chrUPixBuf[i]);
|
yading@11
|
1875 av_freep(&c->chrUPixBuf);
|
yading@11
|
1876 av_freep(&c->chrVPixBuf);
|
yading@11
|
1877 }
|
yading@11
|
1878
|
yading@11
|
1879 if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {
|
yading@11
|
1880 for (i = 0; i < c->vLumBufSize; i++)
|
yading@11
|
1881 av_freep(&c->alpPixBuf[i]);
|
yading@11
|
1882 av_freep(&c->alpPixBuf);
|
yading@11
|
1883 }
|
yading@11
|
1884
|
yading@11
|
1885 for (i = 0; i < 4; i++)
|
yading@11
|
1886 av_freep(&c->dither_error[i]);
|
yading@11
|
1887
|
yading@11
|
1888 av_freep(&c->vLumFilter);
|
yading@11
|
1889 av_freep(&c->vChrFilter);
|
yading@11
|
1890 av_freep(&c->hLumFilter);
|
yading@11
|
1891 av_freep(&c->hChrFilter);
|
yading@11
|
1892 #if HAVE_ALTIVEC
|
yading@11
|
1893 av_freep(&c->vYCoeffsBank);
|
yading@11
|
1894 av_freep(&c->vCCoeffsBank);
|
yading@11
|
1895 #endif
|
yading@11
|
1896
|
yading@11
|
1897 av_freep(&c->vLumFilterPos);
|
yading@11
|
1898 av_freep(&c->vChrFilterPos);
|
yading@11
|
1899 av_freep(&c->hLumFilterPos);
|
yading@11
|
1900 av_freep(&c->hChrFilterPos);
|
yading@11
|
1901
|
yading@11
|
1902 #if HAVE_MMX_INLINE
|
yading@11
|
1903 #if USE_MMAP
|
yading@11
|
1904 if (c->lumMmxextFilterCode)
|
yading@11
|
1905 munmap(c->lumMmxextFilterCode, c->lumMmxextFilterCodeSize);
|
yading@11
|
1906 if (c->chrMmxextFilterCode)
|
yading@11
|
1907 munmap(c->chrMmxextFilterCode, c->chrMmxextFilterCodeSize);
|
yading@11
|
1908 #elif HAVE_VIRTUALALLOC
|
yading@11
|
1909 if (c->lumMmxextFilterCode)
|
yading@11
|
1910 VirtualFree(c->lumMmxextFilterCode, 0, MEM_RELEASE);
|
yading@11
|
1911 if (c->chrMmxextFilterCode)
|
yading@11
|
1912 VirtualFree(c->chrMmxextFilterCode, 0, MEM_RELEASE);
|
yading@11
|
1913 #else
|
yading@11
|
1914 av_free(c->lumMmxextFilterCode);
|
yading@11
|
1915 av_free(c->chrMmxextFilterCode);
|
yading@11
|
1916 #endif
|
yading@11
|
1917 c->lumMmxextFilterCode = NULL;
|
yading@11
|
1918 c->chrMmxextFilterCode = NULL;
|
yading@11
|
1919 #endif /* HAVE_MMX_INLINE */
|
yading@11
|
1920
|
yading@11
|
1921 av_freep(&c->yuvTable);
|
yading@11
|
1922 av_freep(&c->formatConvBuffer);
|
yading@11
|
1923
|
yading@11
|
1924 av_free(c);
|
yading@11
|
1925 }
|
yading@11
|
1926
|
yading@11
|
1927 struct SwsContext *sws_getCachedContext(struct SwsContext *context, int srcW,
|
yading@11
|
1928 int srcH, enum AVPixelFormat srcFormat,
|
yading@11
|
1929 int dstW, int dstH,
|
yading@11
|
1930 enum AVPixelFormat dstFormat, int flags,
|
yading@11
|
1931 SwsFilter *srcFilter,
|
yading@11
|
1932 SwsFilter *dstFilter,
|
yading@11
|
1933 const double *param)
|
yading@11
|
1934 {
|
yading@11
|
1935 static const double default_param[2] = { SWS_PARAM_DEFAULT,
|
yading@11
|
1936 SWS_PARAM_DEFAULT };
|
yading@11
|
1937
|
yading@11
|
1938 if (!param)
|
yading@11
|
1939 param = default_param;
|
yading@11
|
1940
|
yading@11
|
1941 if (context &&
|
yading@11
|
1942 (context->srcW != srcW ||
|
yading@11
|
1943 context->srcH != srcH ||
|
yading@11
|
1944 context->srcFormat != srcFormat ||
|
yading@11
|
1945 context->dstW != dstW ||
|
yading@11
|
1946 context->dstH != dstH ||
|
yading@11
|
1947 context->dstFormat != dstFormat ||
|
yading@11
|
1948 context->flags != flags ||
|
yading@11
|
1949 context->param[0] != param[0] ||
|
yading@11
|
1950 context->param[1] != param[1])) {
|
yading@11
|
1951 sws_freeContext(context);
|
yading@11
|
1952 context = NULL;
|
yading@11
|
1953 }
|
yading@11
|
1954
|
yading@11
|
1955 if (!context) {
|
yading@11
|
1956 if (!(context = sws_alloc_context()))
|
yading@11
|
1957 return NULL;
|
yading@11
|
1958 context->srcW = srcW;
|
yading@11
|
1959 context->srcH = srcH;
|
yading@11
|
1960 context->srcRange = handle_jpeg(&srcFormat);
|
yading@11
|
1961 context->src0Alpha = handle_0alpha(&srcFormat);
|
yading@11
|
1962 context->srcFormat = srcFormat;
|
yading@11
|
1963 context->dstW = dstW;
|
yading@11
|
1964 context->dstH = dstH;
|
yading@11
|
1965 context->dstRange = handle_jpeg(&dstFormat);
|
yading@11
|
1966 context->dst0Alpha = handle_0alpha(&dstFormat);
|
yading@11
|
1967 context->dstFormat = dstFormat;
|
yading@11
|
1968 context->flags = flags;
|
yading@11
|
1969 context->param[0] = param[0];
|
yading@11
|
1970 context->param[1] = param[1];
|
yading@11
|
1971 sws_setColorspaceDetails(context, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT],
|
yading@11
|
1972 context->srcRange,
|
yading@11
|
1973 ff_yuv2rgb_coeffs[SWS_CS_DEFAULT] /* FIXME*/,
|
yading@11
|
1974 context->dstRange, 0, 1 << 16, 1 << 16);
|
yading@11
|
1975 if (sws_init_context(context, srcFilter, dstFilter) < 0) {
|
yading@11
|
1976 sws_freeContext(context);
|
yading@11
|
1977 return NULL;
|
yading@11
|
1978 }
|
yading@11
|
1979 }
|
yading@11
|
1980 return context;
|
yading@11
|
1981 }
|