00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "avcodec.h"
00028 #include "swscale.h"
00029 #include "dsputil.h"
00030
00031 #ifdef HAVE_ALTIVEC
00032 #include "ppc/imgresample_altivec.h"
00033 #endif
00034
00035 #define NB_COMPONENTS 3
00036
00037 #define PHASE_BITS 4
00038 #define NB_PHASES (1 << PHASE_BITS)
00039 #define NB_TAPS 4
00040 #define FCENTER 1
00041
00042
00043 #define POS_FRAC_BITS 16
00044 #define POS_FRAC (1 << POS_FRAC_BITS)
00045
00046 #define FILTER_BITS 8
00047
00048 #define LINE_BUF_HEIGHT (NB_TAPS * 4)
00049
00050 struct SwsContext {
00051 AVClass *av_class;
00052 struct ImgReSampleContext *resampling_ctx;
00053 enum PixelFormat src_pix_fmt, dst_pix_fmt;
00054 };
00055
00056 struct ImgReSampleContext {
00057 int iwidth, iheight, owidth, oheight;
00058 int topBand, bottomBand, leftBand, rightBand;
00059 int padtop, padbottom, padleft, padright;
00060 int pad_owidth, pad_oheight;
00061 int h_incr, v_incr;
00062 DECLARE_ALIGNED_8(int16_t, h_filters[NB_PHASES][NB_TAPS]);
00063 DECLARE_ALIGNED_8(int16_t, v_filters[NB_PHASES][NB_TAPS]);
00064 uint8_t *line_buf;
00065 };
00066
00067 void av_build_filter(int16_t *filter, double factor, int tap_count, int phase_count, int scale, int type);
00068
00069 static inline int get_phase(int pos)
00070 {
00071 return ((pos) >> (POS_FRAC_BITS - PHASE_BITS)) & ((1 << PHASE_BITS) - 1);
00072 }
00073
00074
00075 static void h_resample_fast(uint8_t *dst, int dst_width, const uint8_t *src,
00076 int src_width, int src_start, int src_incr,
00077 int16_t *filters)
00078 {
00079 int src_pos, phase, sum, i;
00080 const uint8_t *s;
00081 int16_t *filter;
00082
00083 src_pos = src_start;
00084 for(i=0;i<dst_width;i++) {
00085 #ifdef TEST
00086
00087 if ((src_pos >> POS_FRAC_BITS) < 0 ||
00088 (src_pos >> POS_FRAC_BITS) > (src_width - NB_TAPS))
00089 av_abort();
00090 #endif
00091 s = src + (src_pos >> POS_FRAC_BITS);
00092 phase = get_phase(src_pos);
00093 filter = filters + phase * NB_TAPS;
00094 #if NB_TAPS == 4
00095 sum = s[0] * filter[0] +
00096 s[1] * filter[1] +
00097 s[2] * filter[2] +
00098 s[3] * filter[3];
00099 #else
00100 {
00101 int j;
00102 sum = 0;
00103 for(j=0;j<NB_TAPS;j++)
00104 sum += s[j] * filter[j];
00105 }
00106 #endif
00107 sum = sum >> FILTER_BITS;
00108 if (sum < 0)
00109 sum = 0;
00110 else if (sum > 255)
00111 sum = 255;
00112 dst[0] = sum;
00113 src_pos += src_incr;
00114 dst++;
00115 }
00116 }
00117
00118
00119 static void v_resample(uint8_t *dst, int dst_width, const uint8_t *src,
00120 int wrap, int16_t *filter)
00121 {
00122 int sum, i;
00123 const uint8_t *s;
00124
00125 s = src;
00126 for(i=0;i<dst_width;i++) {
00127 #if NB_TAPS == 4
00128 sum = s[0 * wrap] * filter[0] +
00129 s[1 * wrap] * filter[1] +
00130 s[2 * wrap] * filter[2] +
00131 s[3 * wrap] * filter[3];
00132 #else
00133 {
00134 int j;
00135 uint8_t *s1 = s;
00136
00137 sum = 0;
00138 for(j=0;j<NB_TAPS;j++) {
00139 sum += s1[0] * filter[j];
00140 s1 += wrap;
00141 }
00142 }
00143 #endif
00144 sum = sum >> FILTER_BITS;
00145 if (sum < 0)
00146 sum = 0;
00147 else if (sum > 255)
00148 sum = 255;
00149 dst[0] = sum;
00150 dst++;
00151 s++;
00152 }
00153 }
00154
00155 #ifdef HAVE_MMX
00156
00157 #include "i386/mmx.h"
00158
00159 #define FILTER4(reg) \
00160 {\
00161 s = src + (src_pos >> POS_FRAC_BITS);\
00162 phase = get_phase(src_pos);\
00163 filter = filters + phase * NB_TAPS;\
00164 movq_m2r(*s, reg);\
00165 punpcklbw_r2r(mm7, reg);\
00166 movq_m2r(*filter, mm6);\
00167 pmaddwd_r2r(reg, mm6);\
00168 movq_r2r(mm6, reg);\
00169 psrlq_i2r(32, reg);\
00170 paddd_r2r(mm6, reg);\
00171 psrad_i2r(FILTER_BITS, reg);\
00172 src_pos += src_incr;\
00173 }
00174
00175 #define DUMP(reg) movq_r2m(reg, tmp); printf(#reg "=%016"PRIx64"\n", tmp.uq);
00176
00177
00178 static void h_resample_fast4_mmx(uint8_t *dst, int dst_width,
00179 const uint8_t *src, int src_width,
00180 int src_start, int src_incr, int16_t *filters)
00181 {
00182 int src_pos, phase;
00183 const uint8_t *s;
00184 int16_t *filter;
00185 mmx_t tmp;
00186
00187 src_pos = src_start;
00188 pxor_r2r(mm7, mm7);
00189
00190 while (dst_width >= 4) {
00191
00192 FILTER4(mm0);
00193 FILTER4(mm1);
00194 FILTER4(mm2);
00195 FILTER4(mm3);
00196
00197 packuswb_r2r(mm7, mm0);
00198 packuswb_r2r(mm7, mm1);
00199 packuswb_r2r(mm7, mm3);
00200 packuswb_r2r(mm7, mm2);
00201 movq_r2m(mm0, tmp);
00202 dst[0] = tmp.ub[0];
00203 movq_r2m(mm1, tmp);
00204 dst[1] = tmp.ub[0];
00205 movq_r2m(mm2, tmp);
00206 dst[2] = tmp.ub[0];
00207 movq_r2m(mm3, tmp);
00208 dst[3] = tmp.ub[0];
00209 dst += 4;
00210 dst_width -= 4;
00211 }
00212 while (dst_width > 0) {
00213 FILTER4(mm0);
00214 packuswb_r2r(mm7, mm0);
00215 movq_r2m(mm0, tmp);
00216 dst[0] = tmp.ub[0];
00217 dst++;
00218 dst_width--;
00219 }
00220 emms();
00221 }
00222
00223 static void v_resample4_mmx(uint8_t *dst, int dst_width, const uint8_t *src,
00224 int wrap, int16_t *filter)
00225 {
00226 int sum, i, v;
00227 const uint8_t *s;
00228 mmx_t tmp;
00229 mmx_t coefs[4];
00230
00231 for(i=0;i<4;i++) {
00232 v = filter[i];
00233 coefs[i].uw[0] = v;
00234 coefs[i].uw[1] = v;
00235 coefs[i].uw[2] = v;
00236 coefs[i].uw[3] = v;
00237 }
00238
00239 pxor_r2r(mm7, mm7);
00240 s = src;
00241 while (dst_width >= 4) {
00242 movq_m2r(s[0 * wrap], mm0);
00243 punpcklbw_r2r(mm7, mm0);
00244 movq_m2r(s[1 * wrap], mm1);
00245 punpcklbw_r2r(mm7, mm1);
00246 movq_m2r(s[2 * wrap], mm2);
00247 punpcklbw_r2r(mm7, mm2);
00248 movq_m2r(s[3 * wrap], mm3);
00249 punpcklbw_r2r(mm7, mm3);
00250
00251 pmullw_m2r(coefs[0], mm0);
00252 pmullw_m2r(coefs[1], mm1);
00253 pmullw_m2r(coefs[2], mm2);
00254 pmullw_m2r(coefs[3], mm3);
00255
00256 paddw_r2r(mm1, mm0);
00257 paddw_r2r(mm3, mm2);
00258 paddw_r2r(mm2, mm0);
00259 psraw_i2r(FILTER_BITS, mm0);
00260
00261 packuswb_r2r(mm7, mm0);
00262 movq_r2m(mm0, tmp);
00263
00264 *(uint32_t *)dst = tmp.ud[0];
00265 dst += 4;
00266 s += 4;
00267 dst_width -= 4;
00268 }
00269 while (dst_width > 0) {
00270 sum = s[0 * wrap] * filter[0] +
00271 s[1 * wrap] * filter[1] +
00272 s[2 * wrap] * filter[2] +
00273 s[3 * wrap] * filter[3];
00274 sum = sum >> FILTER_BITS;
00275 if (sum < 0)
00276 sum = 0;
00277 else if (sum > 255)
00278 sum = 255;
00279 dst[0] = sum;
00280 dst++;
00281 s++;
00282 dst_width--;
00283 }
00284 emms();
00285 }
00286 #endif
00287
00288
00289 static void h_resample_slow(uint8_t *dst, int dst_width,
00290 const uint8_t *src, int src_width,
00291 int src_start, int src_incr, int16_t *filters)
00292 {
00293 int src_pos, phase, sum, j, v, i;
00294 const uint8_t *s, *src_end;
00295 int16_t *filter;
00296
00297 src_end = src + src_width;
00298 src_pos = src_start;
00299 for(i=0;i<dst_width;i++) {
00300 s = src + (src_pos >> POS_FRAC_BITS);
00301 phase = get_phase(src_pos);
00302 filter = filters + phase * NB_TAPS;
00303 sum = 0;
00304 for(j=0;j<NB_TAPS;j++) {
00305 if (s < src)
00306 v = src[0];
00307 else if (s >= src_end)
00308 v = src_end[-1];
00309 else
00310 v = s[0];
00311 sum += v * filter[j];
00312 s++;
00313 }
00314 sum = sum >> FILTER_BITS;
00315 if (sum < 0)
00316 sum = 0;
00317 else if (sum > 255)
00318 sum = 255;
00319 dst[0] = sum;
00320 src_pos += src_incr;
00321 dst++;
00322 }
00323 }
00324
00325 static void h_resample(uint8_t *dst, int dst_width, const uint8_t *src,
00326 int src_width, int src_start, int src_incr,
00327 int16_t *filters)
00328 {
00329 int n, src_end;
00330
00331 if (src_start < 0) {
00332 n = (0 - src_start + src_incr - 1) / src_incr;
00333 h_resample_slow(dst, n, src, src_width, src_start, src_incr, filters);
00334 dst += n;
00335 dst_width -= n;
00336 src_start += n * src_incr;
00337 }
00338 src_end = src_start + dst_width * src_incr;
00339 if (src_end > ((src_width - NB_TAPS) << POS_FRAC_BITS)) {
00340 n = (((src_width - NB_TAPS + 1) << POS_FRAC_BITS) - 1 - src_start) /
00341 src_incr;
00342 } else {
00343 n = dst_width;
00344 }
00345 #ifdef HAVE_MMX
00346 if ((mm_flags & MM_MMX) && NB_TAPS == 4)
00347 h_resample_fast4_mmx(dst, n,
00348 src, src_width, src_start, src_incr, filters);
00349 else
00350 #endif
00351 h_resample_fast(dst, n,
00352 src, src_width, src_start, src_incr, filters);
00353 if (n < dst_width) {
00354 dst += n;
00355 dst_width -= n;
00356 src_start += n * src_incr;
00357 h_resample_slow(dst, dst_width,
00358 src, src_width, src_start, src_incr, filters);
00359 }
00360 }
00361
00362 static void component_resample(ImgReSampleContext *s,
00363 uint8_t *output, int owrap, int owidth, int oheight,
00364 uint8_t *input, int iwrap, int iwidth, int iheight)
00365 {
00366 int src_y, src_y1, last_src_y, ring_y, phase_y, y1, y;
00367 uint8_t *new_line, *src_line;
00368
00369 last_src_y = - FCENTER - 1;
00370
00371 src_y = (last_src_y + NB_TAPS) * POS_FRAC;
00372 ring_y = NB_TAPS;
00373 for(y=0;y<oheight;y++) {
00374
00375 src_y1 = src_y >> POS_FRAC_BITS;
00376 while (last_src_y < src_y1) {
00377 if (++ring_y >= LINE_BUF_HEIGHT + NB_TAPS)
00378 ring_y = NB_TAPS;
00379 last_src_y++;
00380
00381
00382 y1 = last_src_y;
00383 if (y1 < 0) {
00384 y1 = 0;
00385 } else if (y1 >= iheight) {
00386 y1 = iheight - 1;
00387 }
00388 src_line = input + y1 * iwrap;
00389 new_line = s->line_buf + ring_y * owidth;
00390
00391 h_resample(new_line, owidth,
00392 src_line, iwidth, - FCENTER * POS_FRAC, s->h_incr,
00393 &s->h_filters[0][0]);
00394
00395 if (ring_y >= LINE_BUF_HEIGHT) {
00396 memcpy(s->line_buf + (ring_y - LINE_BUF_HEIGHT) * owidth,
00397 new_line, owidth);
00398 }
00399 }
00400
00401 phase_y = get_phase(src_y);
00402 #ifdef HAVE_MMX
00403
00404 if ((mm_flags & MM_MMX) && NB_TAPS == 4 && 0)
00405 v_resample4_mmx(output, owidth,
00406 s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
00407 &s->v_filters[phase_y][0]);
00408 else
00409 #endif
00410 #ifdef HAVE_ALTIVEC
00411 if ((mm_flags & MM_ALTIVEC) && NB_TAPS == 4 && FILTER_BITS <= 6)
00412 v_resample16_altivec(output, owidth,
00413 s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
00414 &s->v_filters[phase_y][0]);
00415 else
00416 #endif
00417 v_resample(output, owidth,
00418 s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
00419 &s->v_filters[phase_y][0]);
00420
00421 src_y += s->v_incr;
00422
00423 output += owrap;
00424 }
00425 }
00426
00427 ImgReSampleContext *img_resample_init(int owidth, int oheight,
00428 int iwidth, int iheight)
00429 {
00430 return img_resample_full_init(owidth, oheight, iwidth, iheight,
00431 0, 0, 0, 0, 0, 0, 0, 0);
00432 }
00433
00434 ImgReSampleContext *img_resample_full_init(int owidth, int oheight,
00435 int iwidth, int iheight,
00436 int topBand, int bottomBand,
00437 int leftBand, int rightBand,
00438 int padtop, int padbottom,
00439 int padleft, int padright)
00440 {
00441 ImgReSampleContext *s;
00442
00443 if (!owidth || !oheight || !iwidth || !iheight)
00444 return NULL;
00445
00446 s = av_mallocz(sizeof(ImgReSampleContext));
00447 if (!s)
00448 return NULL;
00449 if((unsigned)owidth >= UINT_MAX / (LINE_BUF_HEIGHT + NB_TAPS))
00450 return NULL;
00451 s->line_buf = av_mallocz(owidth * (LINE_BUF_HEIGHT + NB_TAPS));
00452 if (!s->line_buf)
00453 goto fail;
00454
00455 s->owidth = owidth;
00456 s->oheight = oheight;
00457 s->iwidth = iwidth;
00458 s->iheight = iheight;
00459
00460 s->topBand = topBand;
00461 s->bottomBand = bottomBand;
00462 s->leftBand = leftBand;
00463 s->rightBand = rightBand;
00464
00465 s->padtop = padtop;
00466 s->padbottom = padbottom;
00467 s->padleft = padleft;
00468 s->padright = padright;
00469
00470 s->pad_owidth = owidth - (padleft + padright);
00471 s->pad_oheight = oheight - (padtop + padbottom);
00472
00473 s->h_incr = ((iwidth - leftBand - rightBand) * POS_FRAC) / s->pad_owidth;
00474 s->v_incr = ((iheight - topBand - bottomBand) * POS_FRAC) / s->pad_oheight;
00475
00476 av_build_filter(&s->h_filters[0][0], (float) s->pad_owidth /
00477 (float) (iwidth - leftBand - rightBand), NB_TAPS, NB_PHASES, 1<<FILTER_BITS, 0);
00478 av_build_filter(&s->v_filters[0][0], (float) s->pad_oheight /
00479 (float) (iheight - topBand - bottomBand), NB_TAPS, NB_PHASES, 1<<FILTER_BITS, 0);
00480
00481 return s;
00482 fail:
00483 av_free(s);
00484 return NULL;
00485 }
00486
00487 void img_resample(ImgReSampleContext *s,
00488 AVPicture *output, const AVPicture *input)
00489 {
00490 int i, shift;
00491 uint8_t* optr;
00492
00493 for (i=0;i<3;i++) {
00494 shift = (i == 0) ? 0 : 1;
00495
00496 optr = output->data[i] + (((output->linesize[i] *
00497 s->padtop) + s->padleft) >> shift);
00498
00499 component_resample(s, optr, output->linesize[i],
00500 s->pad_owidth >> shift, s->pad_oheight >> shift,
00501 input->data[i] + (input->linesize[i] *
00502 (s->topBand >> shift)) + (s->leftBand >> shift),
00503 input->linesize[i], ((s->iwidth - s->leftBand -
00504 s->rightBand) >> shift),
00505 (s->iheight - s->topBand - s->bottomBand) >> shift);
00506 }
00507 }
00508
00509 void img_resample_close(ImgReSampleContext *s)
00510 {
00511 av_free(s->line_buf);
00512 av_free(s);
00513 }
00514
00515 struct SwsContext *sws_getContext(int srcW, int srcH, int srcFormat,
00516 int dstW, int dstH, int dstFormat,
00517 int flags, SwsFilter *srcFilter,
00518 SwsFilter *dstFilter, double *param)
00519 {
00520 struct SwsContext *ctx;
00521
00522 ctx = av_malloc(sizeof(struct SwsContext));
00523 if (ctx)
00524 ctx->av_class = av_mallocz(sizeof(AVClass));
00525 if (!ctx || !ctx->av_class) {
00526 av_log(NULL, AV_LOG_ERROR, "Cannot allocate a resampling context!\n");
00527
00528 return NULL;
00529 }
00530
00531 if ((srcH != dstH) || (srcW != dstW)) {
00532 if ((srcFormat != PIX_FMT_YUV420P) || (dstFormat != PIX_FMT_YUV420P)) {
00533 av_log(NULL, AV_LOG_INFO, "PIX_FMT_YUV420P will be used as an intermediate format for rescaling\n");
00534 }
00535 ctx->resampling_ctx = img_resample_init(dstW, dstH, srcW, srcH);
00536 } else {
00537 ctx->resampling_ctx = av_malloc(sizeof(ImgReSampleContext));
00538 ctx->resampling_ctx->iheight = srcH;
00539 ctx->resampling_ctx->iwidth = srcW;
00540 ctx->resampling_ctx->oheight = dstH;
00541 ctx->resampling_ctx->owidth = dstW;
00542 }
00543 ctx->src_pix_fmt = srcFormat;
00544 ctx->dst_pix_fmt = dstFormat;
00545
00546 return ctx;
00547 }
00548
00549 void sws_freeContext(struct SwsContext *ctx)
00550 {
00551 if (!ctx)
00552 return;
00553 if ((ctx->resampling_ctx->iwidth != ctx->resampling_ctx->owidth) ||
00554 (ctx->resampling_ctx->iheight != ctx->resampling_ctx->oheight)) {
00555 img_resample_close(ctx->resampling_ctx);
00556 } else {
00557 av_free(ctx->resampling_ctx);
00558 }
00559 av_free(ctx->av_class);
00560 av_free(ctx);
00561 }
00562
00563
00574 struct SwsContext *sws_getCachedContext(struct SwsContext *ctx,
00575 int srcW, int srcH, int srcFormat,
00576 int dstW, int dstH, int dstFormat, int flags,
00577 SwsFilter *srcFilter, SwsFilter *dstFilter, double *param)
00578 {
00579 if (ctx != NULL) {
00580 if ((ctx->resampling_ctx->iwidth != srcW) ||
00581 (ctx->resampling_ctx->iheight != srcH) ||
00582 (ctx->src_pix_fmt != srcFormat) ||
00583 (ctx->resampling_ctx->owidth != dstW) ||
00584 (ctx->resampling_ctx->oheight != dstH) ||
00585 (ctx->dst_pix_fmt != dstFormat))
00586 {
00587 sws_freeContext(ctx);
00588 ctx = NULL;
00589 }
00590 }
00591 if (ctx == NULL) {
00592 return sws_getContext(srcW, srcH, srcFormat,
00593 dstW, dstH, dstFormat, flags,
00594 srcFilter, dstFilter, param);
00595 }
00596 return ctx;
00597 }
00598
00599 int sws_scale(struct SwsContext *ctx, uint8_t* src[], int srcStride[],
00600 int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[])
00601 {
00602 AVPicture src_pict, dst_pict;
00603 int i, res = 0;
00604 AVPicture picture_format_temp;
00605 AVPicture picture_resample_temp, *formatted_picture, *resampled_picture;
00606 uint8_t *buf1 = NULL, *buf2 = NULL;
00607 enum PixelFormat current_pix_fmt;
00608
00609 for (i = 0; i < 4; i++) {
00610 src_pict.data[i] = src[i];
00611 src_pict.linesize[i] = srcStride[i];
00612 dst_pict.data[i] = dst[i];
00613 dst_pict.linesize[i] = dstStride[i];
00614 }
00615 if ((ctx->resampling_ctx->iwidth != ctx->resampling_ctx->owidth) ||
00616 (ctx->resampling_ctx->iheight != ctx->resampling_ctx->oheight)) {
00617
00618
00619 if (ctx->src_pix_fmt != PIX_FMT_YUV420P) {
00620 int size;
00621
00622
00623 size = avpicture_get_size(PIX_FMT_YUV420P, ctx->resampling_ctx->iwidth, ctx->resampling_ctx->iheight);
00624 buf1 = av_malloc(size);
00625 if (!buf1) {
00626 res = -1;
00627 goto the_end;
00628 }
00629 formatted_picture = &picture_format_temp;
00630 avpicture_fill((AVPicture*)formatted_picture, buf1,
00631 PIX_FMT_YUV420P, ctx->resampling_ctx->iwidth, ctx->resampling_ctx->iheight);
00632
00633 if (img_convert((AVPicture*)formatted_picture, PIX_FMT_YUV420P,
00634 &src_pict, ctx->src_pix_fmt,
00635 ctx->resampling_ctx->iwidth, ctx->resampling_ctx->iheight) < 0) {
00636
00637 av_log(NULL, AV_LOG_ERROR, "pixel format conversion not handled\n");
00638 res = -1;
00639 goto the_end;
00640 }
00641 } else {
00642 formatted_picture = &src_pict;
00643 }
00644
00645 if (ctx->dst_pix_fmt != PIX_FMT_YUV420P) {
00646 int size;
00647
00648
00649 size = avpicture_get_size(PIX_FMT_YUV420P, ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight);
00650 buf2 = av_malloc(size);
00651 if (!buf2) {
00652 res = -1;
00653 goto the_end;
00654 }
00655 resampled_picture = &picture_resample_temp;
00656 avpicture_fill((AVPicture*)resampled_picture, buf2,
00657 PIX_FMT_YUV420P, ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight);
00658
00659 } else {
00660 resampled_picture = &dst_pict;
00661 }
00662
00663
00664 img_resample(ctx->resampling_ctx, resampled_picture, formatted_picture);
00665 current_pix_fmt = PIX_FMT_YUV420P;
00666 } else {
00667 resampled_picture = &src_pict;
00668 current_pix_fmt = ctx->src_pix_fmt;
00669 }
00670
00671 if (current_pix_fmt != ctx->dst_pix_fmt) {
00672 if (img_convert(&dst_pict, ctx->dst_pix_fmt,
00673 resampled_picture, current_pix_fmt,
00674 ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight) < 0) {
00675
00676 av_log(NULL, AV_LOG_ERROR, "pixel format conversion not handled\n");
00677
00678 res = -1;
00679 goto the_end;
00680 }
00681 } else if (resampled_picture != &dst_pict) {
00682 av_picture_copy(&dst_pict, resampled_picture, current_pix_fmt,
00683 ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight);
00684 }
00685
00686 the_end:
00687 av_free(buf1);
00688 av_free(buf2);
00689 return res;
00690 }
00691
00692
00693 #ifdef TEST
00694 #include <stdio.h>
00695 #undef exit
00696
00697
00698 #define XSIZE 256
00699 #define YSIZE 256
00700 uint8_t img[XSIZE * YSIZE];
00701
00702
00703 #define XSIZE1 512
00704 #define YSIZE1 512
00705 uint8_t img1[XSIZE1 * YSIZE1];
00706 uint8_t img2[XSIZE1 * YSIZE1];
00707
00708 void save_pgm(const char *filename, uint8_t *img, int xsize, int ysize)
00709 {
00710 #undef fprintf
00711 FILE *f;
00712 f=fopen(filename,"w");
00713 fprintf(f,"P5\n%d %d\n%d\n", xsize, ysize, 255);
00714 fwrite(img,1, xsize * ysize,f);
00715 fclose(f);
00716 #define fprintf please_use_av_log
00717 }
00718
00719 static void dump_filter(int16_t *filter)
00720 {
00721 int i, ph;
00722
00723 for(ph=0;ph<NB_PHASES;ph++) {
00724 av_log(NULL, AV_LOG_INFO, "%2d: ", ph);
00725 for(i=0;i<NB_TAPS;i++) {
00726 av_log(NULL, AV_LOG_INFO, " %5.2f", filter[ph * NB_TAPS + i] / 256.0);
00727 }
00728 av_log(NULL, AV_LOG_INFO, "\n");
00729 }
00730 }
00731
00732 #ifdef HAVE_MMX
00733 int mm_flags;
00734 #endif
00735
00736 int main(int argc, char **argv)
00737 {
00738 int x, y, v, i, xsize, ysize;
00739 ImgReSampleContext *s;
00740 float fact, factors[] = { 1/2.0, 3.0/4.0, 1.0, 4.0/3.0, 16.0/9.0, 2.0 };
00741 char buf[256];
00742
00743
00744 for(y=0;y<YSIZE;y++) {
00745 for(x=0;x<XSIZE;x++) {
00746 if (x < XSIZE/2 && y < YSIZE/2) {
00747 if (x < XSIZE/4 && y < YSIZE/4) {
00748 if ((x % 10) <= 6 &&
00749 (y % 10) <= 6)
00750 v = 0xff;
00751 else
00752 v = 0x00;
00753 } else if (x < XSIZE/4) {
00754 if (x & 1)
00755 v = 0xff;
00756 else
00757 v = 0;
00758 } else if (y < XSIZE/4) {
00759 if (y & 1)
00760 v = 0xff;
00761 else
00762 v = 0;
00763 } else {
00764 if (y < YSIZE*3/8) {
00765 if ((y+x) & 1)
00766 v = 0xff;
00767 else
00768 v = 0;
00769 } else {
00770 if (((x+3) % 4) <= 1 &&
00771 ((y+3) % 4) <= 1)
00772 v = 0xff;
00773 else
00774 v = 0x00;
00775 }
00776 }
00777 } else if (x < XSIZE/2) {
00778 v = ((x - (XSIZE/2)) * 255) / (XSIZE/2);
00779 } else if (y < XSIZE/2) {
00780 v = ((y - (XSIZE/2)) * 255) / (XSIZE/2);
00781 } else {
00782 v = ((x + y - XSIZE) * 255) / XSIZE;
00783 }
00784 img[(YSIZE - y) * XSIZE + (XSIZE - x)] = v;
00785 }
00786 }
00787 save_pgm("/tmp/in.pgm", img, XSIZE, YSIZE);
00788 for(i=0;i<sizeof(factors)/sizeof(float);i++) {
00789 fact = factors[i];
00790 xsize = (int)(XSIZE * fact);
00791 ysize = (int)((YSIZE - 100) * fact);
00792 s = img_resample_full_init(xsize, ysize, XSIZE, YSIZE, 50 ,50, 0, 0, 0, 0, 0, 0);
00793 av_log(NULL, AV_LOG_INFO, "Factor=%0.2f\n", fact);
00794 dump_filter(&s->h_filters[0][0]);
00795 component_resample(s, img1, xsize, xsize, ysize,
00796 img + 50 * XSIZE, XSIZE, XSIZE, YSIZE - 100);
00797 img_resample_close(s);
00798
00799 snprintf(buf, sizeof(buf), "/tmp/out%d.pgm", i);
00800 save_pgm(buf, img1, xsize, ysize);
00801 }
00802
00803
00804 #ifdef HAVE_MMX
00805 av_log(NULL, AV_LOG_INFO, "MMX test\n");
00806 fact = 0.72;
00807 xsize = (int)(XSIZE * fact);
00808 ysize = (int)(YSIZE * fact);
00809 mm_flags = MM_MMX;
00810 s = img_resample_init(xsize, ysize, XSIZE, YSIZE);
00811 component_resample(s, img1, xsize, xsize, ysize,
00812 img, XSIZE, XSIZE, YSIZE);
00813
00814 mm_flags = 0;
00815 s = img_resample_init(xsize, ysize, XSIZE, YSIZE);
00816 component_resample(s, img2, xsize, xsize, ysize,
00817 img, XSIZE, XSIZE, YSIZE);
00818 if (memcmp(img1, img2, xsize * ysize) != 0) {
00819 av_log(NULL, AV_LOG_ERROR, "mmx error\n");
00820 exit(1);
00821 }
00822 av_log(NULL, AV_LOG_INFO, "MMX OK\n");
00823 #endif
00824 return 0;
00825 }
00826
00827 #endif