00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00030 #include "avcodec.h"
00031 #include "dsputil.h"
00032 #include "imgconvert.h"
00033 #include "libswscale/swscale.h"
00034
00035 #if HAVE_ALTIVEC
00036 #include "ppc/imgresample_altivec.h"
00037 #endif
00038
00039 #define NB_COMPONENTS 3
00040
00041 #define PHASE_BITS 4
00042 #define NB_PHASES (1 << PHASE_BITS)
00043 #define NB_TAPS 4
00044 #define FCENTER 1
00045
00046
00047 #define POS_FRAC_BITS 16
00048 #define POS_FRAC (1 << POS_FRAC_BITS)
00049
00050 #define FILTER_BITS 8
00051
00052 #define LINE_BUF_HEIGHT (NB_TAPS * 4)
00053
00054 struct SwsContext {
00055 const AVClass *av_class;
00056 struct ImgReSampleContext *resampling_ctx;
00057 enum PixelFormat src_pix_fmt, dst_pix_fmt;
00058 };
00059
00060 typedef struct ImgReSampleContext {
00061 int iwidth, iheight, owidth, oheight;
00062 int topBand, bottomBand, leftBand, rightBand;
00063 int padtop, padbottom, padleft, padright;
00064 int pad_owidth, pad_oheight;
00065 int h_incr, v_incr;
00066 DECLARE_ALIGNED_8(int16_t, h_filters[NB_PHASES][NB_TAPS]);
00067 DECLARE_ALIGNED_8(int16_t, v_filters[NB_PHASES][NB_TAPS]);
00068 uint8_t *line_buf;
00069 } ImgReSampleContext;
00070
00071 void av_build_filter(int16_t *filter, double factor, int tap_count, int phase_count, int scale, int type);
00072
00073 static inline int get_phase(int pos)
00074 {
00075 return ((pos) >> (POS_FRAC_BITS - PHASE_BITS)) & ((1 << PHASE_BITS) - 1);
00076 }
00077
00078
00079 static void h_resample_fast(uint8_t *dst, int dst_width, const uint8_t *src,
00080 int src_width, int src_start, int src_incr,
00081 int16_t *filters)
00082 {
00083 int src_pos, phase, sum, i;
00084 const uint8_t *s;
00085 int16_t *filter;
00086
00087 src_pos = src_start;
00088 for(i=0;i<dst_width;i++) {
00089 #ifdef TEST
00090
00091 if ((src_pos >> POS_FRAC_BITS) < 0 ||
00092 (src_pos >> POS_FRAC_BITS) > (src_width - NB_TAPS))
00093 av_abort();
00094 #endif
00095 s = src + (src_pos >> POS_FRAC_BITS);
00096 phase = get_phase(src_pos);
00097 filter = filters + phase * NB_TAPS;
00098 #if NB_TAPS == 4
00099 sum = s[0] * filter[0] +
00100 s[1] * filter[1] +
00101 s[2] * filter[2] +
00102 s[3] * filter[3];
00103 #else
00104 {
00105 int j;
00106 sum = 0;
00107 for(j=0;j<NB_TAPS;j++)
00108 sum += s[j] * filter[j];
00109 }
00110 #endif
00111 sum = sum >> FILTER_BITS;
00112 if (sum < 0)
00113 sum = 0;
00114 else if (sum > 255)
00115 sum = 255;
00116 dst[0] = sum;
00117 src_pos += src_incr;
00118 dst++;
00119 }
00120 }
00121
00122
00123 static void v_resample(uint8_t *dst, int dst_width, const uint8_t *src,
00124 int wrap, int16_t *filter)
00125 {
00126 int sum, i;
00127 const uint8_t *s;
00128
00129 s = src;
00130 for(i=0;i<dst_width;i++) {
00131 #if NB_TAPS == 4
00132 sum = s[0 * wrap] * filter[0] +
00133 s[1 * wrap] * filter[1] +
00134 s[2 * wrap] * filter[2] +
00135 s[3 * wrap] * filter[3];
00136 #else
00137 {
00138 int j;
00139 uint8_t *s1 = s;
00140
00141 sum = 0;
00142 for(j=0;j<NB_TAPS;j++) {
00143 sum += s1[0] * filter[j];
00144 s1 += wrap;
00145 }
00146 }
00147 #endif
00148 sum = sum >> FILTER_BITS;
00149 if (sum < 0)
00150 sum = 0;
00151 else if (sum > 255)
00152 sum = 255;
00153 dst[0] = sum;
00154 dst++;
00155 s++;
00156 }
00157 }
00158
00159 #if HAVE_MMX
00160
00161 #include "x86/mmx.h"
00162
00163 #define FILTER4(reg) \
00164 {\
00165 s = src + (src_pos >> POS_FRAC_BITS);\
00166 phase = get_phase(src_pos);\
00167 filter = filters + phase * NB_TAPS;\
00168 movq_m2r(*s, reg);\
00169 punpcklbw_r2r(mm7, reg);\
00170 movq_m2r(*filter, mm6);\
00171 pmaddwd_r2r(reg, mm6);\
00172 movq_r2r(mm6, reg);\
00173 psrlq_i2r(32, reg);\
00174 paddd_r2r(mm6, reg);\
00175 psrad_i2r(FILTER_BITS, reg);\
00176 src_pos += src_incr;\
00177 }
00178
00179 #define DUMP(reg) movq_r2m(reg, tmp); printf(#reg "=%016"PRIx64"\n", tmp.uq);
00180
00181
00182 static void h_resample_fast4_mmx(uint8_t *dst, int dst_width,
00183 const uint8_t *src, int src_width,
00184 int src_start, int src_incr, int16_t *filters)
00185 {
00186 int src_pos, phase;
00187 const uint8_t *s;
00188 int16_t *filter;
00189 uint64_t tmp;
00190
00191 src_pos = src_start;
00192 pxor_r2r(mm7, mm7);
00193
00194 while (dst_width >= 4) {
00195
00196 FILTER4(mm0);
00197 FILTER4(mm1);
00198 FILTER4(mm2);
00199 FILTER4(mm3);
00200
00201 packuswb_r2r(mm7, mm0);
00202 packuswb_r2r(mm7, mm1);
00203 packuswb_r2r(mm7, mm3);
00204 packuswb_r2r(mm7, mm2);
00205 movq_r2m(mm0, tmp);
00206 dst[0] = tmp & 0xFF;
00207 movq_r2m(mm1, tmp);
00208 dst[1] = tmp & 0xFF;
00209 movq_r2m(mm2, tmp);
00210 dst[2] = tmp & 0xFF;
00211 movq_r2m(mm3, tmp);
00212 dst[3] = tmp & 0xFF;
00213 dst += 4;
00214 dst_width -= 4;
00215 }
00216 while (dst_width > 0) {
00217 FILTER4(mm0);
00218 packuswb_r2r(mm7, mm0);
00219 movq_r2m(mm0, tmp);
00220 dst[0] = tmp & 0xFF;
00221 dst++;
00222 dst_width--;
00223 }
00224 emms();
00225 }
00226
00227 static void v_resample4_mmx(uint8_t *dst, int dst_width, const uint8_t *src,
00228 int wrap, int16_t *filter)
00229 {
00230 int sum, i;
00231 const uint8_t *s;
00232 uint64_t tmp;
00233 uint64_t coefs[4];
00234
00235 for(i=0;i<4;i++) {
00236 tmp = filter[i];
00237 coefs[i] = (tmp<<48) + (tmp<<32) + (tmp<<16) + tmp;
00238 }
00239
00240 pxor_r2r(mm7, mm7);
00241 s = src;
00242 while (dst_width >= 4) {
00243 movq_m2r(s[0 * wrap], mm0);
00244 punpcklbw_r2r(mm7, mm0);
00245 movq_m2r(s[1 * wrap], mm1);
00246 punpcklbw_r2r(mm7, mm1);
00247 movq_m2r(s[2 * wrap], mm2);
00248 punpcklbw_r2r(mm7, mm2);
00249 movq_m2r(s[3 * wrap], mm3);
00250 punpcklbw_r2r(mm7, mm3);
00251
00252 pmullw_m2r(coefs[0], mm0);
00253 pmullw_m2r(coefs[1], mm1);
00254 pmullw_m2r(coefs[2], mm2);
00255 pmullw_m2r(coefs[3], mm3);
00256
00257 paddw_r2r(mm1, mm0);
00258 paddw_r2r(mm3, mm2);
00259 paddw_r2r(mm2, mm0);
00260 psraw_i2r(FILTER_BITS, mm0);
00261
00262 packuswb_r2r(mm7, mm0);
00263 movq_r2m(mm0, tmp);
00264
00265 *(uint32_t *)dst = tmp & 0xFFFFFFFF;
00266 dst += 4;
00267 s += 4;
00268 dst_width -= 4;
00269 }
00270 while (dst_width > 0) {
00271 sum = s[0 * wrap] * filter[0] +
00272 s[1 * wrap] * filter[1] +
00273 s[2 * wrap] * filter[2] +
00274 s[3 * wrap] * filter[3];
00275 sum = sum >> FILTER_BITS;
00276 if (sum < 0)
00277 sum = 0;
00278 else if (sum > 255)
00279 sum = 255;
00280 dst[0] = sum;
00281 dst++;
00282 s++;
00283 dst_width--;
00284 }
00285 emms();
00286 }
00287 #endif
00288
00289
00290 static void h_resample_slow(uint8_t *dst, int dst_width,
00291 const uint8_t *src, int src_width,
00292 int src_start, int src_incr, int16_t *filters)
00293 {
00294 int src_pos, phase, sum, j, v, i;
00295 const uint8_t *s, *src_end;
00296 int16_t *filter;
00297
00298 src_end = src + src_width;
00299 src_pos = src_start;
00300 for(i=0;i<dst_width;i++) {
00301 s = src + (src_pos >> POS_FRAC_BITS);
00302 phase = get_phase(src_pos);
00303 filter = filters + phase * NB_TAPS;
00304 sum = 0;
00305 for(j=0;j<NB_TAPS;j++) {
00306 if (s < src)
00307 v = src[0];
00308 else if (s >= src_end)
00309 v = src_end[-1];
00310 else
00311 v = s[0];
00312 sum += v * filter[j];
00313 s++;
00314 }
00315 sum = sum >> FILTER_BITS;
00316 if (sum < 0)
00317 sum = 0;
00318 else if (sum > 255)
00319 sum = 255;
00320 dst[0] = sum;
00321 src_pos += src_incr;
00322 dst++;
00323 }
00324 }
00325
00326 static void h_resample(uint8_t *dst, int dst_width, const uint8_t *src,
00327 int src_width, int src_start, int src_incr,
00328 int16_t *filters)
00329 {
00330 int n, src_end;
00331
00332 if (src_start < 0) {
00333 n = (0 - src_start + src_incr - 1) / src_incr;
00334 h_resample_slow(dst, n, src, src_width, src_start, src_incr, filters);
00335 dst += n;
00336 dst_width -= n;
00337 src_start += n * src_incr;
00338 }
00339 src_end = src_start + dst_width * src_incr;
00340 if (src_end > ((src_width - NB_TAPS) << POS_FRAC_BITS)) {
00341 n = (((src_width - NB_TAPS + 1) << POS_FRAC_BITS) - 1 - src_start) /
00342 src_incr;
00343 } else {
00344 n = dst_width;
00345 }
00346 #if HAVE_MMX
00347 if ((mm_flags & FF_MM_MMX) && NB_TAPS == 4)
00348 h_resample_fast4_mmx(dst, n,
00349 src, src_width, src_start, src_incr, filters);
00350 else
00351 #endif
00352 h_resample_fast(dst, n,
00353 src, src_width, src_start, src_incr, filters);
00354 if (n < dst_width) {
00355 dst += n;
00356 dst_width -= n;
00357 src_start += n * src_incr;
00358 h_resample_slow(dst, dst_width,
00359 src, src_width, src_start, src_incr, filters);
00360 }
00361 }
00362
00363 static void component_resample(ImgReSampleContext *s,
00364 uint8_t *output, int owrap, int owidth, int oheight,
00365 uint8_t *input, int iwrap, int iwidth, int iheight)
00366 {
00367 int src_y, src_y1, last_src_y, ring_y, phase_y, y1, y;
00368 uint8_t *new_line, *src_line;
00369
00370 last_src_y = - FCENTER - 1;
00371
00372 src_y = (last_src_y + NB_TAPS) * POS_FRAC;
00373 ring_y = NB_TAPS;
00374 for(y=0;y<oheight;y++) {
00375
00376 src_y1 = src_y >> POS_FRAC_BITS;
00377 while (last_src_y < src_y1) {
00378 if (++ring_y >= LINE_BUF_HEIGHT + NB_TAPS)
00379 ring_y = NB_TAPS;
00380 last_src_y++;
00381
00382
00383 y1 = last_src_y;
00384 if (y1 < 0) {
00385 y1 = 0;
00386 } else if (y1 >= iheight) {
00387 y1 = iheight - 1;
00388 }
00389 src_line = input + y1 * iwrap;
00390 new_line = s->line_buf + ring_y * owidth;
00391
00392 h_resample(new_line, owidth,
00393 src_line, iwidth, - FCENTER * POS_FRAC, s->h_incr,
00394 &s->h_filters[0][0]);
00395
00396 if (ring_y >= LINE_BUF_HEIGHT) {
00397 memcpy(s->line_buf + (ring_y - LINE_BUF_HEIGHT) * owidth,
00398 new_line, owidth);
00399 }
00400 }
00401
00402 phase_y = get_phase(src_y);
00403 #if HAVE_MMX
00404
00405 if ((mm_flags & FF_MM_MMX) && NB_TAPS == 4 && 0)
00406 v_resample4_mmx(output, owidth,
00407 s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
00408 &s->v_filters[phase_y][0]);
00409 else
00410 #endif
00411 #if HAVE_ALTIVEC
00412 if ((mm_flags & FF_MM_ALTIVEC) && NB_TAPS == 4 && FILTER_BITS <= 6)
00413 v_resample16_altivec(output, owidth,
00414 s->line_buf + (ring_y - NB_TAPS + 1) * owidth,
00415 owidth, &s->v_filters[phase_y][0]);
00416 else
00417 #endif
00418 v_resample(output, owidth,
00419 s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
00420 &s->v_filters[phase_y][0]);
00421
00422 src_y += s->v_incr;
00423
00424 output += owrap;
00425 }
00426 }
00427
00428 ImgReSampleContext *img_resample_full_init(int owidth, int oheight,
00429 int iwidth, int iheight,
00430 int topBand, int bottomBand,
00431 int leftBand, int rightBand,
00432 int padtop, int padbottom,
00433 int padleft, int padright)
00434 {
00435 ImgReSampleContext *s;
00436
00437 if (!owidth || !oheight || !iwidth || !iheight)
00438 return NULL;
00439
00440 s = av_mallocz(sizeof(ImgReSampleContext));
00441 if (!s)
00442 return NULL;
00443 if((unsigned)owidth >= UINT_MAX / (LINE_BUF_HEIGHT + NB_TAPS))
00444 goto fail;
00445 s->line_buf = av_mallocz(owidth * (LINE_BUF_HEIGHT + NB_TAPS));
00446 if (!s->line_buf)
00447 goto fail;
00448
00449 s->owidth = owidth;
00450 s->oheight = oheight;
00451 s->iwidth = iwidth;
00452 s->iheight = iheight;
00453
00454 s->topBand = topBand;
00455 s->bottomBand = bottomBand;
00456 s->leftBand = leftBand;
00457 s->rightBand = rightBand;
00458
00459 s->padtop = padtop;
00460 s->padbottom = padbottom;
00461 s->padleft = padleft;
00462 s->padright = padright;
00463
00464 s->pad_owidth = owidth - (padleft + padright);
00465 s->pad_oheight = oheight - (padtop + padbottom);
00466
00467 s->h_incr = ((iwidth - leftBand - rightBand) * POS_FRAC) / s->pad_owidth;
00468 s->v_incr = ((iheight - topBand - bottomBand) * POS_FRAC) / s->pad_oheight;
00469
00470 av_build_filter(&s->h_filters[0][0], (float) s->pad_owidth /
00471 (float) (iwidth - leftBand - rightBand), NB_TAPS, NB_PHASES, 1<<FILTER_BITS, 0);
00472 av_build_filter(&s->v_filters[0][0], (float) s->pad_oheight /
00473 (float) (iheight - topBand - bottomBand), NB_TAPS, NB_PHASES, 1<<FILTER_BITS, 0);
00474
00475 return s;
00476 fail:
00477 av_free(s);
00478 return NULL;
00479 }
00480
00481 ImgReSampleContext *img_resample_init(int owidth, int oheight,
00482 int iwidth, int iheight)
00483 {
00484 return img_resample_full_init(owidth, oheight, iwidth, iheight,
00485 0, 0, 0, 0, 0, 0, 0, 0);
00486 }
00487
00488 void img_resample(ImgReSampleContext *s,
00489 AVPicture *output, const AVPicture *input)
00490 {
00491 int i, shift;
00492 uint8_t* optr;
00493
00494 for (i=0;i<3;i++) {
00495 shift = (i == 0) ? 0 : 1;
00496
00497 optr = output->data[i] + (((output->linesize[i] *
00498 s->padtop) + s->padleft) >> shift);
00499
00500 component_resample(s, optr, output->linesize[i],
00501 s->pad_owidth >> shift, s->pad_oheight >> shift,
00502 input->data[i] + (input->linesize[i] *
00503 (s->topBand >> shift)) + (s->leftBand >> shift),
00504 input->linesize[i], ((s->iwidth - s->leftBand -
00505 s->rightBand) >> shift),
00506 (s->iheight - s->topBand - s->bottomBand) >> shift);
00507 }
00508 }
00509
00510 void img_resample_close(ImgReSampleContext *s)
00511 {
00512 av_free(s->line_buf);
00513 av_free(s);
00514 }
00515
00516 static const char *context_to_name(void* ptr)
00517 {
00518 return "imgconvert";
00519 }
00520
00521 static const AVClass context_class = { "imgresample", context_to_name, NULL };
00522
00523 struct SwsContext *sws_getContext(int srcW, int srcH, int srcFormat,
00524 int dstW, int dstH, int dstFormat,
00525 int flags, SwsFilter *srcFilter,
00526 SwsFilter *dstFilter, double *param)
00527 {
00528 struct SwsContext *ctx;
00529
00530 ctx = av_malloc(sizeof(struct SwsContext));
00531 if (!ctx) {
00532 av_log(NULL, AV_LOG_ERROR, "Cannot allocate a resampling context!\n");
00533
00534 return NULL;
00535 }
00536 ctx->av_class = &context_class;
00537
00538 if ((srcH != dstH) || (srcW != dstW)) {
00539 if ((srcFormat != PIX_FMT_YUV420P) || (dstFormat != PIX_FMT_YUV420P)) {
00540 av_log(ctx, AV_LOG_INFO, "PIX_FMT_YUV420P will be used as an intermediate format for rescaling\n");
00541 }
00542 ctx->resampling_ctx = img_resample_init(dstW, dstH, srcW, srcH);
00543 } else {
00544 ctx->resampling_ctx = av_malloc(sizeof(ImgReSampleContext));
00545 ctx->resampling_ctx->iheight = srcH;
00546 ctx->resampling_ctx->iwidth = srcW;
00547 ctx->resampling_ctx->oheight = dstH;
00548 ctx->resampling_ctx->owidth = dstW;
00549 }
00550 ctx->src_pix_fmt = srcFormat;
00551 ctx->dst_pix_fmt = dstFormat;
00552
00553 return ctx;
00554 }
00555
00556 void sws_freeContext(struct SwsContext *ctx)
00557 {
00558 if (!ctx)
00559 return;
00560 if ((ctx->resampling_ctx->iwidth != ctx->resampling_ctx->owidth) ||
00561 (ctx->resampling_ctx->iheight != ctx->resampling_ctx->oheight)) {
00562 img_resample_close(ctx->resampling_ctx);
00563 } else {
00564 av_free(ctx->resampling_ctx);
00565 }
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(ctx, 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(ctx, 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
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 #if 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<FF_ARRAY_ELEMS(factors);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 #if 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 = FF_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