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
00516
00517
00518
00519
00520 #if 0
00521 struct SwsContext *sws_getContext(int srcW, int srcH, int srcFormat,
00522 int dstW, int dstH, int dstFormat,
00523 int flags, SwsFilter *srcFilter,
00524 SwsFilter *dstFilter, double *param)
00525 {
00526 struct SwsContext *ctx;
00527
00528 ctx = av_malloc(sizeof(struct SwsContext));
00529 if (ctx)
00530 ctx->av_class = av_mallocz(sizeof(AVClass));
00531 if (!ctx || !ctx->av_class) {
00532 av_log(NULL, AV_LOG_ERROR, "Cannot allocate a resampling context!\n");
00533
00534 return NULL;
00535 }
00536
00537 if ((srcH != dstH) || (srcW != dstW)) {
00538 if ((srcFormat != PIX_FMT_YUV420P) || (dstFormat != PIX_FMT_YUV420P)) {
00539 av_log(NULL, AV_LOG_INFO, "PIX_FMT_YUV420P will be used as an intermediate format for rescaling\n");
00540 }
00541 ctx->resampling_ctx = img_resample_init(dstW, dstH, srcW, srcH);
00542 } else {
00543 ctx->resampling_ctx = av_malloc(sizeof(ImgReSampleContext));
00544 ctx->resampling_ctx->iheight = srcH;
00545 ctx->resampling_ctx->iwidth = srcW;
00546 ctx->resampling_ctx->oheight = dstH;
00547 ctx->resampling_ctx->owidth = dstW;
00548 }
00549 ctx->src_pix_fmt = srcFormat;
00550 ctx->dst_pix_fmt = dstFormat;
00551
00552 return ctx;
00553 }
00554
00555 void sws_freeContext(struct SwsContext *ctx)
00556 {
00557 if (!ctx)
00558 return;
00559 if ((ctx->resampling_ctx->iwidth != ctx->resampling_ctx->owidth) ||
00560 (ctx->resampling_ctx->iheight != ctx->resampling_ctx->oheight)) {
00561 img_resample_close(ctx->resampling_ctx);
00562 } else {
00563 av_free(ctx->resampling_ctx);
00564 }
00565 av_free(ctx->av_class);
00566 av_free(ctx);
00567 }
00568
00569
00580 struct SwsContext *sws_getCachedContext(struct SwsContext *ctx,
00581 int srcW, int srcH, int srcFormat,
00582 int dstW, int dstH, int dstFormat, int flags,
00583 SwsFilter *srcFilter, SwsFilter *dstFilter, double *param)
00584 {
00585 if (ctx != NULL) {
00586 if ((ctx->resampling_ctx->iwidth != srcW) ||
00587 (ctx->resampling_ctx->iheight != srcH) ||
00588 (ctx->src_pix_fmt != srcFormat) ||
00589 (ctx->resampling_ctx->owidth != dstW) ||
00590 (ctx->resampling_ctx->oheight != dstH) ||
00591 (ctx->dst_pix_fmt != dstFormat))
00592 {
00593 sws_freeContext(ctx);
00594 ctx = NULL;
00595 }
00596 }
00597 if (ctx == NULL) {
00598 return sws_getContext(srcW, srcH, srcFormat,
00599 dstW, dstH, dstFormat, flags,
00600 srcFilter, dstFilter, param);
00601 }
00602 return ctx;
00603 }
00604
00605 int sws_scale(struct SwsContext *ctx, uint8_t* src[], int srcStride[],
00606 int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[])
00607 {
00608 AVPicture src_pict, dst_pict;
00609 int i, res = 0;
00610 AVPicture picture_format_temp;
00611 AVPicture picture_resample_temp, *formatted_picture, *resampled_picture;
00612 uint8_t *buf1 = NULL, *buf2 = NULL;
00613 enum PixelFormat current_pix_fmt;
00614
00615 for (i = 0; i < 4; i++) {
00616 src_pict.data[i] = src[i];
00617 src_pict.linesize[i] = srcStride[i];
00618 dst_pict.data[i] = dst[i];
00619 dst_pict.linesize[i] = dstStride[i];
00620 }
00621 if ((ctx->resampling_ctx->iwidth != ctx->resampling_ctx->owidth) ||
00622 (ctx->resampling_ctx->iheight != ctx->resampling_ctx->oheight)) {
00623
00624
00625 if (ctx->src_pix_fmt != PIX_FMT_YUV420P) {
00626 int size;
00627
00628
00629 size = avpicture_get_size(PIX_FMT_YUV420P, ctx->resampling_ctx->iwidth, ctx->resampling_ctx->iheight);
00630 buf1 = av_malloc(size);
00631 if (!buf1) {
00632 res = -1;
00633 goto the_end;
00634 }
00635 formatted_picture = &picture_format_temp;
00636 avpicture_fill((AVPicture*)formatted_picture, buf1,
00637 PIX_FMT_YUV420P, ctx->resampling_ctx->iwidth, ctx->resampling_ctx->iheight);
00638
00639 if (img_convert((AVPicture*)formatted_picture, PIX_FMT_YUV420P,
00640 &src_pict, ctx->src_pix_fmt,
00641 ctx->resampling_ctx->iwidth, ctx->resampling_ctx->iheight) < 0) {
00642
00643 av_log(NULL, AV_LOG_ERROR, "pixel format conversion not handled\n");
00644 res = -1;
00645 goto the_end;
00646 }
00647 } else {
00648 formatted_picture = &src_pict;
00649 }
00650
00651 if (ctx->dst_pix_fmt != PIX_FMT_YUV420P) {
00652 int size;
00653
00654
00655 size = avpicture_get_size(PIX_FMT_YUV420P, ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight);
00656 buf2 = av_malloc(size);
00657 if (!buf2) {
00658 res = -1;
00659 goto the_end;
00660 }
00661 resampled_picture = &picture_resample_temp;
00662 avpicture_fill((AVPicture*)resampled_picture, buf2,
00663 PIX_FMT_YUV420P, ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight);
00664
00665 } else {
00666 resampled_picture = &dst_pict;
00667 }
00668
00669
00670 img_resample(ctx->resampling_ctx, resampled_picture, formatted_picture);
00671 current_pix_fmt = PIX_FMT_YUV420P;
00672 } else {
00673 resampled_picture = &src_pict;
00674 current_pix_fmt = ctx->src_pix_fmt;
00675 }
00676
00677 if (current_pix_fmt != ctx->dst_pix_fmt) {
00678 if (img_convert(&dst_pict, ctx->dst_pix_fmt,
00679 resampled_picture, current_pix_fmt,
00680 ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight) < 0) {
00681
00682 av_log(NULL, AV_LOG_ERROR, "pixel format conversion not handled\n");
00683
00684 res = -1;
00685 goto the_end;
00686 }
00687 } else if (resampled_picture != &dst_pict) {
00688 av_picture_copy(&dst_pict, resampled_picture, current_pix_fmt,
00689 ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight);
00690 }
00691
00692 the_end:
00693 av_free(buf1);
00694 av_free(buf2);
00695 return res;
00696 }
00697 #endif
00698
00699 #ifdef TEST
00700 #include <stdio.h>
00701 #undef exit
00702
00703
00704 #define XSIZE 256
00705 #define YSIZE 256
00706 uint8_t img[XSIZE * YSIZE];
00707
00708
00709 #define XSIZE1 512
00710 #define YSIZE1 512
00711 uint8_t img1[XSIZE1 * YSIZE1];
00712 uint8_t img2[XSIZE1 * YSIZE1];
00713
00714 void save_pgm(const char *filename, uint8_t *img, int xsize, int ysize)
00715 {
00716 #undef fprintf
00717 FILE *f;
00718 f=fopen(filename,"w");
00719 fprintf(f,"P5\n%d %d\n%d\n", xsize, ysize, 255);
00720 fwrite(img,1, xsize * ysize,f);
00721 fclose(f);
00722 #define fprintf please_use_av_log
00723 }
00724
00725 static void dump_filter(int16_t *filter)
00726 {
00727 int i, ph;
00728
00729 for(ph=0;ph<NB_PHASES;ph++) {
00730 av_log(NULL, AV_LOG_INFO, "%2d: ", ph);
00731 for(i=0;i<NB_TAPS;i++) {
00732 av_log(NULL, AV_LOG_INFO, " %5.2f", filter[ph * NB_TAPS + i] / 256.0);
00733 }
00734 av_log(NULL, AV_LOG_INFO, "\n");
00735 }
00736 }
00737
00738 #ifdef HAVE_MMX
00739 int mm_flags;
00740 #endif
00741
00742 int main(int argc, char **argv)
00743 {
00744 int x, y, v, i, xsize, ysize;
00745 ImgReSampleContext *s;
00746 float fact, factors[] = { 1/2.0, 3.0/4.0, 1.0, 4.0/3.0, 16.0/9.0, 2.0 };
00747 char buf[256];
00748
00749
00750 for(y=0;y<YSIZE;y++) {
00751 for(x=0;x<XSIZE;x++) {
00752 if (x < XSIZE/2 && y < YSIZE/2) {
00753 if (x < XSIZE/4 && y < YSIZE/4) {
00754 if ((x % 10) <= 6 &&
00755 (y % 10) <= 6)
00756 v = 0xff;
00757 else
00758 v = 0x00;
00759 } else if (x < XSIZE/4) {
00760 if (x & 1)
00761 v = 0xff;
00762 else
00763 v = 0;
00764 } else if (y < XSIZE/4) {
00765 if (y & 1)
00766 v = 0xff;
00767 else
00768 v = 0;
00769 } else {
00770 if (y < YSIZE*3/8) {
00771 if ((y+x) & 1)
00772 v = 0xff;
00773 else
00774 v = 0;
00775 } else {
00776 if (((x+3) % 4) <= 1 &&
00777 ((y+3) % 4) <= 1)
00778 v = 0xff;
00779 else
00780 v = 0x00;
00781 }
00782 }
00783 } else if (x < XSIZE/2) {
00784 v = ((x - (XSIZE/2)) * 255) / (XSIZE/2);
00785 } else if (y < XSIZE/2) {
00786 v = ((y - (XSIZE/2)) * 255) / (XSIZE/2);
00787 } else {
00788 v = ((x + y - XSIZE) * 255) / XSIZE;
00789 }
00790 img[(YSIZE - y) * XSIZE + (XSIZE - x)] = v;
00791 }
00792 }
00793 save_pgm("/tmp/in.pgm", img, XSIZE, YSIZE);
00794 for(i=0;i<sizeof(factors)/sizeof(float);i++) {
00795 fact = factors[i];
00796 xsize = (int)(XSIZE * fact);
00797 ysize = (int)((YSIZE - 100) * fact);
00798 s = img_resample_full_init(xsize, ysize, XSIZE, YSIZE, 50 ,50, 0, 0, 0, 0, 0, 0);
00799 av_log(NULL, AV_LOG_INFO, "Factor=%0.2f\n", fact);
00800 dump_filter(&s->h_filters[0][0]);
00801 component_resample(s, img1, xsize, xsize, ysize,
00802 img + 50 * XSIZE, XSIZE, XSIZE, YSIZE - 100);
00803 img_resample_close(s);
00804
00805 snprintf(buf, sizeof(buf), "/tmp/out%d.pgm", i);
00806 save_pgm(buf, img1, xsize, ysize);
00807 }
00808
00809
00810 #ifdef HAVE_MMX
00811 av_log(NULL, AV_LOG_INFO, "MMX test\n");
00812 fact = 0.72;
00813 xsize = (int)(XSIZE * fact);
00814 ysize = (int)(YSIZE * fact);
00815 mm_flags = MM_MMX;
00816 s = img_resample_init(xsize, ysize, XSIZE, YSIZE);
00817 component_resample(s, img1, xsize, xsize, ysize,
00818 img, XSIZE, XSIZE, YSIZE);
00819
00820 mm_flags = 0;
00821 s = img_resample_init(xsize, ysize, XSIZE, YSIZE);
00822 component_resample(s, img2, xsize, xsize, ysize,
00823 img, XSIZE, XSIZE, YSIZE);
00824 if (memcmp(img1, img2, xsize * ysize) != 0) {
00825 av_log(NULL, AV_LOG_ERROR, "mmx error\n");
00826 exit(1);
00827 }
00828 av_log(NULL, AV_LOG_INFO, "MMX OK\n");
00829 #endif
00830 return 0;
00831 }
00832
00833 #endif