Enable AVFMT_FLAG_NONBLOCK.
[libav.git] / libavcodec / imgresample.c
CommitLineData
de6d9b64 1/*
115329f1 2 * High quality image resampling with polyphase filters
406792e7 3 * Copyright (c) 2001 Fabrice Bellard
de6d9b64 4 *
b78e7197
DB
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
ff4ec49e
FB
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
b78e7197 10 * version 2.1 of the License, or (at your option) any later version.
de6d9b64 11 *
b78e7197 12 * FFmpeg is distributed in the hope that it will be useful,
de6d9b64 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ff4ec49e
FB
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
de6d9b64 16 *
ff4ec49e 17 * You should have received a copy of the GNU Lesser General Public
b78e7197 18 * License along with FFmpeg; if not, write to the Free Software
5509bffa 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
de6d9b64 20 */
115329f1 21
983e3246 22/**
bad5537e 23 * @file libavcodec/imgresample.c
983e3246 24 * High quality image resampling with polyphase filters .
d3b771bb
VS
25 *
26 * WARNING: This file is deprecated and will be removed after FFmpeg 0.5
27 * release, do not lose your time improving it!
983e3246 28 */
115329f1 29
de6d9b64 30#include "avcodec.h"
6000abfa 31#include "dsputil.h"
db95d3bf 32#include "imgconvert.h"
223d678a 33#include "libswscale/swscale.h"
de6d9b64 34
b250f9c6 35#if HAVE_ALTIVEC
89523bee
LB
36#include "ppc/imgresample_altivec.h"
37#endif
38
de6d9b64
FB
39#define NB_COMPONENTS 3
40
41#define PHASE_BITS 4
42#define NB_PHASES (1 << PHASE_BITS)
43#define NB_TAPS 4
44#define FCENTER 1 /* index of the center of the filter */
ab6d194a 45//#define TEST 1 /* Test it */
de6d9b64
FB
46
47#define POS_FRAC_BITS 16
48#define POS_FRAC (1 << POS_FRAC_BITS)
49/* 6 bits precision is needed for MMX */
50#define FILTER_BITS 8
51
52#define LINE_BUF_HEIGHT (NB_TAPS * 4)
53
a163ed1a 54struct SwsContext {
d42a814e 55 const AVClass *av_class;
a163ed1a
LA
56 struct ImgReSampleContext *resampling_ctx;
57 enum PixelFormat src_pix_fmt, dst_pix_fmt;
58};
59
dd1c8f3e 60typedef struct ImgReSampleContext {
1ff93ffc
TK
61 int iwidth, iheight, owidth, oheight;
62 int topBand, bottomBand, leftBand, rightBand;
63 int padtop, padbottom, padleft, padright;
64 int pad_owidth, pad_oheight;
de6d9b64 65 int h_incr, v_incr;
68b51e58
SH
66 DECLARE_ALIGNED_8(int16_t, h_filters[NB_PHASES][NB_TAPS]); /* horizontal filters */
67 DECLARE_ALIGNED_8(int16_t, v_filters[NB_PHASES][NB_TAPS]); /* vertical filters */
0c1a9eda 68 uint8_t *line_buf;
dd1c8f3e 69} ImgReSampleContext;
de6d9b64 70
aaaf1635
MN
71void av_build_filter(int16_t *filter, double factor, int tap_count, int phase_count, int scale, int type);
72
de6d9b64
FB
73static inline int get_phase(int pos)
74{
75 return ((pos) >> (POS_FRAC_BITS - PHASE_BITS)) & ((1 << PHASE_BITS) - 1);
76}
77
78/* This function must be optimized */
da64ecc3 79static void h_resample_fast(uint8_t *dst, int dst_width, const uint8_t *src,
bb270c08
DB
80 int src_width, int src_start, int src_incr,
81 int16_t *filters)
de6d9b64
FB
82{
83 int src_pos, phase, sum, i;
da64ecc3 84 const uint8_t *s;
0c1a9eda 85 int16_t *filter;
de6d9b64
FB
86
87 src_pos = src_start;
88 for(i=0;i<dst_width;i++) {
89#ifdef TEST
90 /* test */
91 if ((src_pos >> POS_FRAC_BITS) < 0 ||
92 (src_pos >> POS_FRAC_BITS) > (src_width - NB_TAPS))
02ac3136 93 av_abort();
de6d9b64
FB
94#endif
95 s = src + (src_pos >> POS_FRAC_BITS);
96 phase = get_phase(src_pos);
97 filter = filters + phase * NB_TAPS;
98#if NB_TAPS == 4
99 sum = s[0] * filter[0] +
100 s[1] * filter[1] +
101 s[2] * filter[2] +
102 s[3] * filter[3];
103#else
104 {
105 int j;
106 sum = 0;
107 for(j=0;j<NB_TAPS;j++)
108 sum += s[j] * filter[j];
109 }
110#endif
111 sum = sum >> FILTER_BITS;
112 if (sum < 0)
113 sum = 0;
114 else if (sum > 255)
115 sum = 255;
116 dst[0] = sum;
117 src_pos += src_incr;
118 dst++;
119 }
120}
121
122/* This function must be optimized */
da64ecc3 123static void v_resample(uint8_t *dst, int dst_width, const uint8_t *src,
bb270c08 124 int wrap, int16_t *filter)
de6d9b64
FB
125{
126 int sum, i;
da64ecc3 127 const uint8_t *s;
de6d9b64
FB
128
129 s = src;
130 for(i=0;i<dst_width;i++) {
131#if NB_TAPS == 4
132 sum = s[0 * wrap] * filter[0] +
133 s[1 * wrap] * filter[1] +
134 s[2 * wrap] * filter[2] +
135 s[3 * wrap] * filter[3];
136#else
137 {
138 int j;
0c1a9eda 139 uint8_t *s1 = s;
de6d9b64
FB
140
141 sum = 0;
142 for(j=0;j<NB_TAPS;j++) {
143 sum += s1[0] * filter[j];
144 s1 += wrap;
145 }
146 }
147#endif
148 sum = sum >> FILTER_BITS;
149 if (sum < 0)
150 sum = 0;
151 else if (sum > 255)
152 sum = 255;
153 dst[0] = sum;
154 dst++;
155 s++;
156 }
157}
158
b250f9c6 159#if HAVE_MMX
de6d9b64 160
a6493a8f 161#include "x86/mmx.h"
de6d9b64
FB
162
163#define FILTER4(reg) \
164{\
165 s = src + (src_pos >> POS_FRAC_BITS);\
166 phase = get_phase(src_pos);\
167 filter = filters + phase * NB_TAPS;\
168 movq_m2r(*s, reg);\
169 punpcklbw_r2r(mm7, reg);\
170 movq_m2r(*filter, mm6);\
171 pmaddwd_r2r(reg, mm6);\
172 movq_r2r(mm6, reg);\
173 psrlq_i2r(32, reg);\
174 paddd_r2r(mm6, reg);\
175 psrad_i2r(FILTER_BITS, reg);\
176 src_pos += src_incr;\
177}
178
949b1a13 179#define DUMP(reg) movq_r2m(reg, tmp); printf(#reg "=%016"PRIx64"\n", tmp.uq);
de6d9b64
FB
180
181/* XXX: do four pixels at a time */
da64ecc3 182static void h_resample_fast4_mmx(uint8_t *dst, int dst_width,
bb270c08 183 const uint8_t *src, int src_width,
0c1a9eda 184 int src_start, int src_incr, int16_t *filters)
de6d9b64
FB
185{
186 int src_pos, phase;
da64ecc3 187 const uint8_t *s;
0c1a9eda 188 int16_t *filter;
d08ea32c 189 uint64_t tmp;
115329f1 190
de6d9b64
FB
191 src_pos = src_start;
192 pxor_r2r(mm7, mm7);
193
194 while (dst_width >= 4) {
195
196 FILTER4(mm0);
197 FILTER4(mm1);
198 FILTER4(mm2);
199 FILTER4(mm3);
200
201 packuswb_r2r(mm7, mm0);
202 packuswb_r2r(mm7, mm1);
203 packuswb_r2r(mm7, mm3);
204 packuswb_r2r(mm7, mm2);
205 movq_r2m(mm0, tmp);
d08ea32c 206 dst[0] = tmp & 0xFF;
de6d9b64 207 movq_r2m(mm1, tmp);
d08ea32c 208 dst[1] = tmp & 0xFF;
de6d9b64 209 movq_r2m(mm2, tmp);
d08ea32c 210 dst[2] = tmp & 0xFF;
de6d9b64 211 movq_r2m(mm3, tmp);
d08ea32c 212 dst[3] = tmp & 0xFF;
de6d9b64
FB
213 dst += 4;
214 dst_width -= 4;
215 }
216 while (dst_width > 0) {
217 FILTER4(mm0);
218 packuswb_r2r(mm7, mm0);
219 movq_r2m(mm0, tmp);
d08ea32c 220 dst[0] = tmp & 0xFF;
de6d9b64
FB
221 dst++;
222 dst_width--;
223 }
224 emms();
225}
226
da64ecc3 227static void v_resample4_mmx(uint8_t *dst, int dst_width, const uint8_t *src,
bb270c08 228 int wrap, int16_t *filter)
de6d9b64 229{
d08ea32c 230 int sum, i;
da64ecc3 231 const uint8_t *s;
d08ea32c
AJ
232 uint64_t tmp;
233 uint64_t coefs[4];
115329f1 234
de6d9b64 235 for(i=0;i<4;i++) {
d08ea32c
AJ
236 tmp = filter[i];
237 coefs[i] = (tmp<<48) + (tmp<<32) + (tmp<<16) + tmp;
de6d9b64 238 }
115329f1 239
de6d9b64
FB
240 pxor_r2r(mm7, mm7);
241 s = src;
242 while (dst_width >= 4) {
243 movq_m2r(s[0 * wrap], mm0);
244 punpcklbw_r2r(mm7, mm0);
245 movq_m2r(s[1 * wrap], mm1);
246 punpcklbw_r2r(mm7, mm1);
247 movq_m2r(s[2 * wrap], mm2);
248 punpcklbw_r2r(mm7, mm2);
249 movq_m2r(s[3 * wrap], mm3);
250 punpcklbw_r2r(mm7, mm3);
251
252 pmullw_m2r(coefs[0], mm0);
253 pmullw_m2r(coefs[1], mm1);
254 pmullw_m2r(coefs[2], mm2);
255 pmullw_m2r(coefs[3], mm3);
256
257 paddw_r2r(mm1, mm0);
258 paddw_r2r(mm3, mm2);
259 paddw_r2r(mm2, mm0);
260 psraw_i2r(FILTER_BITS, mm0);
115329f1 261
de6d9b64
FB
262 packuswb_r2r(mm7, mm0);
263 movq_r2m(mm0, tmp);
264
d08ea32c 265 *(uint32_t *)dst = tmp & 0xFFFFFFFF;
de6d9b64
FB
266 dst += 4;
267 s += 4;
268 dst_width -= 4;
269 }
270 while (dst_width > 0) {
271 sum = s[0 * wrap] * filter[0] +
272 s[1 * wrap] * filter[1] +
273 s[2 * wrap] * filter[2] +
274 s[3 * wrap] * filter[3];
275 sum = sum >> FILTER_BITS;
276 if (sum < 0)
277 sum = 0;
278 else if (sum > 255)
279 sum = 255;
280 dst[0] = sum;
281 dst++;
282 s++;
283 dst_width--;
284 }
285 emms();
286}
fca6a0dd 287#endif /* HAVE_MMX */
de6d9b64 288
52b541ad 289/* slow version to handle limit cases. Does not need optimization */
da64ecc3 290static void h_resample_slow(uint8_t *dst, int dst_width,
bb270c08 291 const uint8_t *src, int src_width,
0c1a9eda 292 int src_start, int src_incr, int16_t *filters)
de6d9b64
FB
293{
294 int src_pos, phase, sum, j, v, i;
da64ecc3 295 const uint8_t *s, *src_end;
0c1a9eda 296 int16_t *filter;
de6d9b64
FB
297
298 src_end = src + src_width;
299 src_pos = src_start;
300 for(i=0;i<dst_width;i++) {
301 s = src + (src_pos >> POS_FRAC_BITS);
302 phase = get_phase(src_pos);
303 filter = filters + phase * NB_TAPS;
304 sum = 0;
305 for(j=0;j<NB_TAPS;j++) {
306 if (s < src)
307 v = src[0];
308 else if (s >= src_end)
309 v = src_end[-1];
310 else
311 v = s[0];
312 sum += v * filter[j];
313 s++;
314 }
315 sum = sum >> FILTER_BITS;
316 if (sum < 0)
317 sum = 0;
318 else if (sum > 255)
319 sum = 255;
320 dst[0] = sum;
321 src_pos += src_incr;
322 dst++;
323 }
324}
325
da64ecc3 326static void h_resample(uint8_t *dst, int dst_width, const uint8_t *src,
bb270c08
DB
327 int src_width, int src_start, int src_incr,
328 int16_t *filters)
de6d9b64
FB
329{
330 int n, src_end;
331
332 if (src_start < 0) {
333 n = (0 - src_start + src_incr - 1) / src_incr;
334 h_resample_slow(dst, n, src, src_width, src_start, src_incr, filters);
335 dst += n;
336 dst_width -= n;
337 src_start += n * src_incr;
338 }
339 src_end = src_start + dst_width * src_incr;
340 if (src_end > ((src_width - NB_TAPS) << POS_FRAC_BITS)) {
115329f1 341 n = (((src_width - NB_TAPS + 1) << POS_FRAC_BITS) - 1 - src_start) /
de6d9b64
FB
342 src_incr;
343 } else {
344 n = dst_width;
345 }
b250f9c6 346#if HAVE_MMX
82d1605f 347 if ((mm_flags & FF_MM_MMX) && NB_TAPS == 4)
115329f1 348 h_resample_fast4_mmx(dst, n,
de6d9b64
FB
349 src, src_width, src_start, src_incr, filters);
350 else
351#endif
115329f1 352 h_resample_fast(dst, n,
de6d9b64
FB
353 src, src_width, src_start, src_incr, filters);
354 if (n < dst_width) {
355 dst += n;
356 dst_width -= n;
357 src_start += n * src_incr;
115329f1 358 h_resample_slow(dst, dst_width,
de6d9b64
FB
359 src, src_width, src_start, src_incr, filters);
360 }
361}
362
115329f1 363static void component_resample(ImgReSampleContext *s,
0c1a9eda
ZK
364 uint8_t *output, int owrap, int owidth, int oheight,
365 uint8_t *input, int iwrap, int iwidth, int iheight)
de6d9b64
FB
366{
367 int src_y, src_y1, last_src_y, ring_y, phase_y, y1, y;
0c1a9eda 368 uint8_t *new_line, *src_line;
de6d9b64
FB
369
370 last_src_y = - FCENTER - 1;
371 /* position of the bottom of the filter in the source image */
115329f1 372 src_y = (last_src_y + NB_TAPS) * POS_FRAC;
de6d9b64
FB
373 ring_y = NB_TAPS; /* position in ring buffer */
374 for(y=0;y<oheight;y++) {
375 /* apply horizontal filter on new lines from input if needed */
376 src_y1 = src_y >> POS_FRAC_BITS;
377 while (last_src_y < src_y1) {
378 if (++ring_y >= LINE_BUF_HEIGHT + NB_TAPS)
379 ring_y = NB_TAPS;
380 last_src_y++;
ab6d194a
MN
381 /* handle limit conditions : replicate line (slightly
382 inefficient because we filter multiple times) */
de6d9b64
FB
383 y1 = last_src_y;
384 if (y1 < 0) {
385 y1 = 0;
386 } else if (y1 >= iheight) {
387 y1 = iheight - 1;
388 }
389 src_line = input + y1 * iwrap;
390 new_line = s->line_buf + ring_y * owidth;
391 /* apply filter and handle limit cases correctly */
115329f1
DB
392 h_resample(new_line, owidth,
393 src_line, iwidth, - FCENTER * POS_FRAC, s->h_incr,
de6d9b64 394 &s->h_filters[0][0]);
8bfb108b 395 /* handle ring buffer wrapping */
de6d9b64
FB
396 if (ring_y >= LINE_BUF_HEIGHT) {
397 memcpy(s->line_buf + (ring_y - LINE_BUF_HEIGHT) * owidth,
398 new_line, owidth);
399 }
400 }
401 /* apply vertical filter */
402 phase_y = get_phase(src_y);
b250f9c6 403#if HAVE_MMX
de6d9b64 404 /* desactivated MMX because loss of precision */
82d1605f 405 if ((mm_flags & FF_MM_MMX) && NB_TAPS == 4 && 0)
115329f1
DB
406 v_resample4_mmx(output, owidth,
407 s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
de6d9b64 408 &s->v_filters[phase_y][0]);
404d2241
BF
409 else
410#endif
b250f9c6 411#if HAVE_ALTIVEC
82d1605f 412 if ((mm_flags & FF_MM_ALTIVEC) && NB_TAPS == 4 && FILTER_BITS <= 6)
dd857bfd
DB
413 v_resample16_altivec(output, owidth,
414 s->line_buf + (ring_y - NB_TAPS + 1) * owidth,
415 owidth, &s->v_filters[phase_y][0]);
de6d9b64
FB
416 else
417#endif
115329f1
DB
418 v_resample(output, owidth,
419 s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
de6d9b64 420 &s->v_filters[phase_y][0]);
115329f1 421
de6d9b64 422 src_y += s->v_incr;
115329f1 423
de6d9b64
FB
424 output += owrap;
425 }
426}
427
ab6d194a
MN
428ImgReSampleContext *img_resample_full_init(int owidth, int oheight,
429 int iwidth, int iheight,
430 int topBand, int bottomBand,
1ff93ffc
TK
431 int leftBand, int rightBand,
432 int padtop, int padbottom,
433 int padleft, int padright)
ab6d194a 434{
de6d9b64
FB
435 ImgReSampleContext *s;
436
d10dc616 437 if (!owidth || !oheight || !iwidth || !iheight)
bb270c08 438 return NULL;
d10dc616 439
de6d9b64
FB
440 s = av_mallocz(sizeof(ImgReSampleContext));
441 if (!s)
442 return NULL;
0ecca7a4 443 if((unsigned)owidth >= UINT_MAX / (LINE_BUF_HEIGHT + NB_TAPS))
c1815c37 444 goto fail;
de6d9b64 445 s->line_buf = av_mallocz(owidth * (LINE_BUF_HEIGHT + NB_TAPS));
115329f1 446 if (!s->line_buf)
de6d9b64 447 goto fail;
115329f1 448
de6d9b64
FB
449 s->owidth = owidth;
450 s->oheight = oheight;
451 s->iwidth = iwidth;
452 s->iheight = iheight;
115329f1 453
ab6d194a
MN
454 s->topBand = topBand;
455 s->bottomBand = bottomBand;
456 s->leftBand = leftBand;
457 s->rightBand = rightBand;
115329f1 458
1ff93ffc
TK
459 s->padtop = padtop;
460 s->padbottom = padbottom;
461 s->padleft = padleft;
462 s->padright = padright;
463
464 s->pad_owidth = owidth - (padleft + padright);
465 s->pad_oheight = oheight - (padtop + padbottom);
466
467 s->h_incr = ((iwidth - leftBand - rightBand) * POS_FRAC) / s->pad_owidth;
115329f1 468 s->v_incr = ((iheight - topBand - bottomBand) * POS_FRAC) / s->pad_oheight;
1ff93ffc 469
115329f1 470 av_build_filter(&s->h_filters[0][0], (float) s->pad_owidth /
aaaf1635 471 (float) (iwidth - leftBand - rightBand), NB_TAPS, NB_PHASES, 1<<FILTER_BITS, 0);
115329f1 472 av_build_filter(&s->v_filters[0][0], (float) s->pad_oheight /
aaaf1635 473 (float) (iheight - topBand - bottomBand), NB_TAPS, NB_PHASES, 1<<FILTER_BITS, 0);
de6d9b64
FB
474
475 return s;
1ff93ffc 476fail:
6000abfa 477 av_free(s);
de6d9b64
FB
478 return NULL;
479}
480
dd1c8f3e
LA
481ImgReSampleContext *img_resample_init(int owidth, int oheight,
482 int iwidth, int iheight)
483{
484 return img_resample_full_init(owidth, oheight, iwidth, iheight,
485 0, 0, 0, 0, 0, 0, 0, 0);
486}
487
115329f1 488void img_resample(ImgReSampleContext *s,
da64ecc3 489 AVPicture *output, const AVPicture *input)
de6d9b64
FB
490{
491 int i, shift;
1ff93ffc 492 uint8_t* optr;
de6d9b64 493
1ff93ffc 494 for (i=0;i<3;i++) {
de6d9b64 495 shift = (i == 0) ? 0 : 1;
1ff93ffc 496
115329f1 497 optr = output->data[i] + (((output->linesize[i] *
1ff93ffc
TK
498 s->padtop) + s->padleft) >> shift);
499
115329f1 500 component_resample(s, optr, output->linesize[i],
1ff93ffc 501 s->pad_owidth >> shift, s->pad_oheight >> shift,
115329f1 502 input->data[i] + (input->linesize[i] *
1ff93ffc 503 (s->topBand >> shift)) + (s->leftBand >> shift),
115329f1 504 input->linesize[i], ((s->iwidth - s->leftBand -
1ff93ffc 505 s->rightBand) >> shift),
ab6d194a 506 (s->iheight - s->topBand - s->bottomBand) >> shift);
de6d9b64
FB
507 }
508}
509
510void img_resample_close(ImgReSampleContext *s)
511{
6000abfa
FB
512 av_free(s->line_buf);
513 av_free(s);
de6d9b64
FB
514}
515
778346e3
BC
516static const char *context_to_name(void* ptr)
517{
518 return "imgconvert";
519}
520
521static const AVClass context_class = { "imgresample", context_to_name, NULL };
f15e6b86 522
7b748aff
LA
523struct SwsContext *sws_getContext(int srcW, int srcH, int srcFormat,
524 int dstW, int dstH, int dstFormat,
525 int flags, SwsFilter *srcFilter,
526 SwsFilter *dstFilter, double *param)
527{
528 struct SwsContext *ctx;
529
530 ctx = av_malloc(sizeof(struct SwsContext));
f15e6b86 531 if (!ctx) {
7b748aff
LA
532 av_log(NULL, AV_LOG_ERROR, "Cannot allocate a resampling context!\n");
533
534 return NULL;
535 }
f15e6b86 536 ctx->av_class = &context_class;
7b748aff
LA
537
538 if ((srcH != dstH) || (srcW != dstW)) {
539 if ((srcFormat != PIX_FMT_YUV420P) || (dstFormat != PIX_FMT_YUV420P)) {
64e3e661 540 av_log(ctx, AV_LOG_INFO, "PIX_FMT_YUV420P will be used as an intermediate format for rescaling\n");
7b748aff
LA
541 }
542 ctx->resampling_ctx = img_resample_init(dstW, dstH, srcW, srcH);
543 } else {
544 ctx->resampling_ctx = av_malloc(sizeof(ImgReSampleContext));
545 ctx->resampling_ctx->iheight = srcH;
546 ctx->resampling_ctx->iwidth = srcW;
547 ctx->resampling_ctx->oheight = dstH;
548 ctx->resampling_ctx->owidth = dstW;
549 }
550 ctx->src_pix_fmt = srcFormat;
551 ctx->dst_pix_fmt = dstFormat;
552
553 return ctx;
554}
555
556void sws_freeContext(struct SwsContext *ctx)
557{
04675319
PI
558 if (!ctx)
559 return;
7b748aff
LA
560 if ((ctx->resampling_ctx->iwidth != ctx->resampling_ctx->owidth) ||
561 (ctx->resampling_ctx->iheight != ctx->resampling_ctx->oheight)) {
562 img_resample_close(ctx->resampling_ctx);
563 } else {
564 av_free(ctx->resampling_ctx);
565 }
566 av_free(ctx);
567}
568
96db3808
LA
569
570/**
571 * Checks if context is valid or reallocs a new one instead.
572 * If context is NULL, just calls sws_getContext() to get a new one.
573 * Otherwise, checks if the parameters are the same already saved in context.
574 * If that is the case, returns the current context.
575 * Otherwise, frees context and gets a new one.
576 *
577 * Be warned that srcFilter, dstFilter are not checked, they are
7eb2d654 578 * assumed to remain valid.
96db3808
LA
579 */
580struct SwsContext *sws_getCachedContext(struct SwsContext *ctx,
581 int srcW, int srcH, int srcFormat,
582 int dstW, int dstH, int dstFormat, int flags,
583 SwsFilter *srcFilter, SwsFilter *dstFilter, double *param)
584{
585 if (ctx != NULL) {
586 if ((ctx->resampling_ctx->iwidth != srcW) ||
587 (ctx->resampling_ctx->iheight != srcH) ||
588 (ctx->src_pix_fmt != srcFormat) ||
589 (ctx->resampling_ctx->owidth != dstW) ||
590 (ctx->resampling_ctx->oheight != dstH) ||
591 (ctx->dst_pix_fmt != dstFormat))
592 {
593 sws_freeContext(ctx);
594 ctx = NULL;
595 }
596 }
597 if (ctx == NULL) {
598 return sws_getContext(srcW, srcH, srcFormat,
599 dstW, dstH, dstFormat, flags,
600 srcFilter, dstFilter, param);
601 }
602 return ctx;
603}
604
7b748aff
LA
605int sws_scale(struct SwsContext *ctx, uint8_t* src[], int srcStride[],
606 int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[])
607{
608 AVPicture src_pict, dst_pict;
609 int i, res = 0;
610 AVPicture picture_format_temp;
611 AVPicture picture_resample_temp, *formatted_picture, *resampled_picture;
612 uint8_t *buf1 = NULL, *buf2 = NULL;
613 enum PixelFormat current_pix_fmt;
614
9c5d7c56 615 for (i = 0; i < 4; i++) {
7b748aff
LA
616 src_pict.data[i] = src[i];
617 src_pict.linesize[i] = srcStride[i];
618 dst_pict.data[i] = dst[i];
619 dst_pict.linesize[i] = dstStride[i];
620 }
621 if ((ctx->resampling_ctx->iwidth != ctx->resampling_ctx->owidth) ||
622 (ctx->resampling_ctx->iheight != ctx->resampling_ctx->oheight)) {
623 /* We have to rescale the picture, but only YUV420P rescaling is supported... */
624
625 if (ctx->src_pix_fmt != PIX_FMT_YUV420P) {
626 int size;
627
628 /* create temporary picture for rescaling input*/
629 size = avpicture_get_size(PIX_FMT_YUV420P, ctx->resampling_ctx->iwidth, ctx->resampling_ctx->iheight);
630 buf1 = av_malloc(size);
631 if (!buf1) {
632 res = -1;
633 goto the_end;
634 }
635 formatted_picture = &picture_format_temp;
636 avpicture_fill((AVPicture*)formatted_picture, buf1,
637 PIX_FMT_YUV420P, ctx->resampling_ctx->iwidth, ctx->resampling_ctx->iheight);
638
639 if (img_convert((AVPicture*)formatted_picture, PIX_FMT_YUV420P,
640 &src_pict, ctx->src_pix_fmt,
641 ctx->resampling_ctx->iwidth, ctx->resampling_ctx->iheight) < 0) {
642
64e3e661 643 av_log(ctx, AV_LOG_ERROR, "pixel format conversion not handled\n");
7b748aff
LA
644 res = -1;
645 goto the_end;
646 }
647 } else {
648 formatted_picture = &src_pict;
649 }
650
651 if (ctx->dst_pix_fmt != PIX_FMT_YUV420P) {
652 int size;
653
654 /* create temporary picture for rescaling output*/
655 size = avpicture_get_size(PIX_FMT_YUV420P, ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight);
656 buf2 = av_malloc(size);
657 if (!buf2) {
658 res = -1;
659 goto the_end;
660 }
661 resampled_picture = &picture_resample_temp;
662 avpicture_fill((AVPicture*)resampled_picture, buf2,
663 PIX_FMT_YUV420P, ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight);
664
665 } else {
666 resampled_picture = &dst_pict;
667 }
668
669 /* ...and finally rescale!!! */
670 img_resample(ctx->resampling_ctx, resampled_picture, formatted_picture);
671 current_pix_fmt = PIX_FMT_YUV420P;
672 } else {
673 resampled_picture = &src_pict;
674 current_pix_fmt = ctx->src_pix_fmt;
675 }
676
677 if (current_pix_fmt != ctx->dst_pix_fmt) {
678 if (img_convert(&dst_pict, ctx->dst_pix_fmt,
679 resampled_picture, current_pix_fmt,
680 ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight) < 0) {
681
64e3e661 682 av_log(ctx, AV_LOG_ERROR, "pixel format conversion not handled\n");
7b748aff
LA
683
684 res = -1;
685 goto the_end;
686 }
2793096f 687 } else if (resampled_picture != &dst_pict) {
636d6a4a 688 av_picture_copy(&dst_pict, resampled_picture, current_pix_fmt,
2793096f 689 ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight);
7b748aff
LA
690 }
691
692the_end:
693 av_free(buf1);
694 av_free(buf2);
695 return res;
696}
697
698
de6d9b64 699#ifdef TEST
13160c07 700#include <stdio.h>
14eb0a2e 701#undef exit
ab6d194a 702
de6d9b64
FB
703/* input */
704#define XSIZE 256
705#define YSIZE 256
0c1a9eda 706uint8_t img[XSIZE * YSIZE];
de6d9b64
FB
707
708/* output */
709#define XSIZE1 512
710#define YSIZE1 512
0c1a9eda
ZK
711uint8_t img1[XSIZE1 * YSIZE1];
712uint8_t img2[XSIZE1 * YSIZE1];
de6d9b64 713
0c1a9eda 714void save_pgm(const char *filename, uint8_t *img, int xsize, int ysize)
de6d9b64 715{
95ae72b7 716#undef fprintf
de6d9b64
FB
717 FILE *f;
718 f=fopen(filename,"w");
719 fprintf(f,"P5\n%d %d\n%d\n", xsize, ysize, 255);
720 fwrite(img,1, xsize * ysize,f);
721 fclose(f);
95ae72b7 722#define fprintf please_use_av_log
de6d9b64
FB
723}
724
0c1a9eda 725static void dump_filter(int16_t *filter)
de6d9b64
FB
726{
727 int i, ph;
728
729 for(ph=0;ph<NB_PHASES;ph++) {
13160c07 730 av_log(NULL, AV_LOG_INFO, "%2d: ", ph);
de6d9b64 731 for(i=0;i<NB_TAPS;i++) {
13160c07 732 av_log(NULL, AV_LOG_INFO, " %5.2f", filter[ph * NB_TAPS + i] / 256.0);
de6d9b64 733 }
13160c07 734 av_log(NULL, AV_LOG_INFO, "\n");
de6d9b64
FB
735 }
736}
737
b250f9c6 738#if HAVE_MMX
6acce86b 739int mm_flags;
de6d9b64
FB
740#endif
741
742int main(int argc, char **argv)
743{
744 int x, y, v, i, xsize, ysize;
745 ImgReSampleContext *s;
746 float fact, factors[] = { 1/2.0, 3.0/4.0, 1.0, 4.0/3.0, 16.0/9.0, 2.0 };
747 char buf[256];
748
749 /* build test image */
750 for(y=0;y<YSIZE;y++) {
751 for(x=0;x<XSIZE;x++) {
752 if (x < XSIZE/2 && y < YSIZE/2) {
753 if (x < XSIZE/4 && y < YSIZE/4) {
754 if ((x % 10) <= 6 &&
755 (y % 10) <= 6)
756 v = 0xff;
757 else
758 v = 0x00;
759 } else if (x < XSIZE/4) {
115329f1 760 if (x & 1)
de6d9b64 761 v = 0xff;
115329f1 762 else
de6d9b64
FB
763 v = 0;
764 } else if (y < XSIZE/4) {
115329f1 765 if (y & 1)
de6d9b64 766 v = 0xff;
115329f1 767 else
de6d9b64
FB
768 v = 0;
769 } else {
770 if (y < YSIZE*3/8) {
115329f1 771 if ((y+x) & 1)
de6d9b64 772 v = 0xff;
115329f1 773 else
de6d9b64
FB
774 v = 0;
775 } else {
776 if (((x+3) % 4) <= 1 &&
777 ((y+3) % 4) <= 1)
778 v = 0xff;
779 else
780 v = 0x00;
781 }
782 }
783 } else if (x < XSIZE/2) {
784 v = ((x - (XSIZE/2)) * 255) / (XSIZE/2);
785 } else if (y < XSIZE/2) {
786 v = ((y - (XSIZE/2)) * 255) / (XSIZE/2);
787 } else {
788 v = ((x + y - XSIZE) * 255) / XSIZE;
789 }
ab6d194a 790 img[(YSIZE - y) * XSIZE + (XSIZE - x)] = v;
de6d9b64
FB
791 }
792 }
793 save_pgm("/tmp/in.pgm", img, XSIZE, YSIZE);
37d3e066 794 for(i=0;i<FF_ARRAY_ELEMS(factors);i++) {
de6d9b64
FB
795 fact = factors[i];
796 xsize = (int)(XSIZE * fact);
ab6d194a 797 ysize = (int)((YSIZE - 100) * fact);
13160c07
PI
798 s = img_resample_full_init(xsize, ysize, XSIZE, YSIZE, 50 ,50, 0, 0, 0, 0, 0, 0);
799 av_log(NULL, AV_LOG_INFO, "Factor=%0.2f\n", fact);
de6d9b64
FB
800 dump_filter(&s->h_filters[0][0]);
801 component_resample(s, img1, xsize, xsize, ysize,
ab6d194a 802 img + 50 * XSIZE, XSIZE, XSIZE, YSIZE - 100);
de6d9b64
FB
803 img_resample_close(s);
804
2fc8ea24 805 snprintf(buf, sizeof(buf), "/tmp/out%d.pgm", i);
de6d9b64
FB
806 save_pgm(buf, img1, xsize, ysize);
807 }
808
809 /* mmx test */
b250f9c6 810#if HAVE_MMX
13160c07 811 av_log(NULL, AV_LOG_INFO, "MMX test\n");
de6d9b64
FB
812 fact = 0.72;
813 xsize = (int)(XSIZE * fact);
814 ysize = (int)(YSIZE * fact);
82d1605f 815 mm_flags = FF_MM_MMX;
de6d9b64
FB
816 s = img_resample_init(xsize, ysize, XSIZE, YSIZE);
817 component_resample(s, img1, xsize, xsize, ysize,
818 img, XSIZE, XSIZE, YSIZE);
819
820 mm_flags = 0;
821 s = img_resample_init(xsize, ysize, XSIZE, YSIZE);
822 component_resample(s, img2, xsize, xsize, ysize,
823 img, XSIZE, XSIZE, YSIZE);
824 if (memcmp(img1, img2, xsize * ysize) != 0) {
13160c07 825 av_log(NULL, AV_LOG_ERROR, "mmx error\n");
de6d9b64
FB
826 exit(1);
827 }
13160c07 828 av_log(NULL, AV_LOG_INFO, "MMX OK\n");
fca6a0dd 829#endif /* HAVE_MMX */
de6d9b64
FB
830 return 0;
831}
832
fca6a0dd 833#endif /* TEST */