*/
#include "avcodec.h"
-#include "swscale.h"
#include "dsputil.h"
+#include "imgconvert.h"
+#include "libswscale/swscale.h"
+
+#ifdef HAVE_ALTIVEC
+#include "ppc/imgresample_altivec.h"
+#endif
#define NB_COMPONENTS 3
#define LINE_BUF_HEIGHT (NB_TAPS * 4)
struct SwsContext {
- AVClass *av_class;
+ const AVClass *av_class;
struct ImgReSampleContext *resampling_ctx;
enum PixelFormat src_pix_fmt, dst_pix_fmt;
};
-struct ImgReSampleContext {
+typedef struct ImgReSampleContext {
int iwidth, iheight, owidth, oheight;
int topBand, bottomBand, leftBand, rightBand;
int padtop, padbottom, padleft, padright;
DECLARE_ALIGNED_8(int16_t, h_filters[NB_PHASES][NB_TAPS]); /* horizontal filters */
DECLARE_ALIGNED_8(int16_t, v_filters[NB_PHASES][NB_TAPS]); /* vertical filters */
uint8_t *line_buf;
-};
+} ImgReSampleContext;
void av_build_filter(int16_t *filter, double factor, int tap_count, int phase_count, int scale, int type);
#ifdef HAVE_MMX
-#include "i386/mmx.h"
+#include "x86/mmx.h"
#define FILTER4(reg) \
{\
int src_pos, phase;
const uint8_t *s;
int16_t *filter;
- mmx_t tmp;
+ uint64_t tmp;
src_pos = src_start;
pxor_r2r(mm7, mm7);
packuswb_r2r(mm7, mm3);
packuswb_r2r(mm7, mm2);
movq_r2m(mm0, tmp);
- dst[0] = tmp.ub[0];
+ dst[0] = tmp & 0xFF;
movq_r2m(mm1, tmp);
- dst[1] = tmp.ub[0];
+ dst[1] = tmp & 0xFF;
movq_r2m(mm2, tmp);
- dst[2] = tmp.ub[0];
+ dst[2] = tmp & 0xFF;
movq_r2m(mm3, tmp);
- dst[3] = tmp.ub[0];
+ dst[3] = tmp & 0xFF;
dst += 4;
dst_width -= 4;
}
FILTER4(mm0);
packuswb_r2r(mm7, mm0);
movq_r2m(mm0, tmp);
- dst[0] = tmp.ub[0];
+ dst[0] = tmp & 0xFF;
dst++;
dst_width--;
}
static void v_resample4_mmx(uint8_t *dst, int dst_width, const uint8_t *src,
int wrap, int16_t *filter)
{
- int sum, i, v;
+ int sum, i;
const uint8_t *s;
- mmx_t tmp;
- mmx_t coefs[4];
+ uint64_t tmp;
+ uint64_t coefs[4];
for(i=0;i<4;i++) {
- v = filter[i];
- coefs[i].uw[0] = v;
- coefs[i].uw[1] = v;
- coefs[i].uw[2] = v;
- coefs[i].uw[3] = v;
+ tmp = filter[i];
+ coefs[i] = (tmp<<48) + (tmp<<32) + (tmp<<16) + tmp;
}
pxor_r2r(mm7, mm7);
packuswb_r2r(mm7, mm0);
movq_r2m(mm0, tmp);
- *(uint32_t *)dst = tmp.ud[0];
+ *(uint32_t *)dst = tmp & 0xFFFFFFFF;
dst += 4;
s += 4;
dst_width -= 4;
}
#endif /* HAVE_MMX */
-#ifdef HAVE_ALTIVEC
-typedef union {
- vector unsigned char v;
- unsigned char c[16];
-} vec_uc_t;
-
-typedef union {
- vector signed short v;
- signed short s[8];
-} vec_ss_t;
-
-void v_resample16_altivec(uint8_t *dst, int dst_width, const uint8_t *src,
- int wrap, int16_t *filter)
-{
- int sum, i;
- const uint8_t *s;
- vector unsigned char *tv, tmp, dstv, zero;
- vec_ss_t srchv[4], srclv[4], fv[4];
- vector signed short zeros, sumhv, sumlv;
- s = src;
-
- for(i=0;i<4;i++)
- {
- /*
- The vec_madds later on does an implicit >>15 on the result.
- Since FILTER_BITS is 8, and we have 15 bits of magnitude in
- a signed short, we have just enough bits to pre-shift our
- filter constants <<7 to compensate for vec_madds.
- */
- fv[i].s[0] = filter[i] << (15-FILTER_BITS);
- fv[i].v = vec_splat(fv[i].v, 0);
- }
-
- zero = vec_splat_u8(0);
- zeros = vec_splat_s16(0);
-
-
- /*
- When we're resampling, we'd ideally like both our input buffers,
- and output buffers to be 16-byte aligned, so we can do both aligned
- reads and writes. Sadly we can't always have this at the moment, so
- we opt for aligned writes, as unaligned writes have a huge overhead.
- To do this, do enough scalar resamples to get dst 16-byte aligned.
- */
- i = (-(int)dst) & 0xf;
- while(i>0) {
- sum = s[0 * wrap] * filter[0] +
- s[1 * wrap] * filter[1] +
- s[2 * wrap] * filter[2] +
- s[3 * wrap] * filter[3];
- sum = sum >> FILTER_BITS;
- if (sum<0) sum = 0; else if (sum>255) sum=255;
- dst[0] = sum;
- dst++;
- s++;
- dst_width--;
- i--;
- }
-
- /* Do our altivec resampling on 16 pixels at once. */
- while(dst_width>=16) {
- /*
- Read 16 (potentially unaligned) bytes from each of
- 4 lines into 4 vectors, and split them into shorts.
- Interleave the multipy/accumulate for the resample
- filter with the loads to hide the 3 cycle latency
- the vec_madds have.
- */
- tv = (vector unsigned char *) &s[0 * wrap];
- tmp = vec_perm(tv[0], tv[1], vec_lvsl(0, &s[i * wrap]));
- srchv[0].v = (vector signed short) vec_mergeh(zero, tmp);
- srclv[0].v = (vector signed short) vec_mergel(zero, tmp);
- sumhv = vec_madds(srchv[0].v, fv[0].v, zeros);
- sumlv = vec_madds(srclv[0].v, fv[0].v, zeros);
-
- tv = (vector unsigned char *) &s[1 * wrap];
- tmp = vec_perm(tv[0], tv[1], vec_lvsl(0, &s[1 * wrap]));
- srchv[1].v = (vector signed short) vec_mergeh(zero, tmp);
- srclv[1].v = (vector signed short) vec_mergel(zero, tmp);
- sumhv = vec_madds(srchv[1].v, fv[1].v, sumhv);
- sumlv = vec_madds(srclv[1].v, fv[1].v, sumlv);
-
- tv = (vector unsigned char *) &s[2 * wrap];
- tmp = vec_perm(tv[0], tv[1], vec_lvsl(0, &s[2 * wrap]));
- srchv[2].v = (vector signed short) vec_mergeh(zero, tmp);
- srclv[2].v = (vector signed short) vec_mergel(zero, tmp);
- sumhv = vec_madds(srchv[2].v, fv[2].v, sumhv);
- sumlv = vec_madds(srclv[2].v, fv[2].v, sumlv);
-
- tv = (vector unsigned char *) &s[3 * wrap];
- tmp = vec_perm(tv[0], tv[1], vec_lvsl(0, &s[3 * wrap]));
- srchv[3].v = (vector signed short) vec_mergeh(zero, tmp);
- srclv[3].v = (vector signed short) vec_mergel(zero, tmp);
- sumhv = vec_madds(srchv[3].v, fv[3].v, sumhv);
- sumlv = vec_madds(srclv[3].v, fv[3].v, sumlv);
-
- /*
- Pack the results into our destination vector,
- and do an aligned write of that back to memory.
- */
- dstv = vec_packsu(sumhv, sumlv) ;
- vec_st(dstv, 0, (vector unsigned char *) dst);
-
- dst+=16;
- s+=16;
- dst_width-=16;
- }
-
- /*
- If there are any leftover pixels, resample them
- with the slow scalar method.
- */
- while(dst_width>0) {
- sum = s[0 * wrap] * filter[0] +
- s[1 * wrap] * filter[1] +
- s[2 * wrap] * filter[2] +
- s[3 * wrap] * filter[3];
- sum = sum >> FILTER_BITS;
- if (sum<0) sum = 0; else if (sum>255) sum=255;
- dst[0] = sum;
- dst++;
- s++;
- dst_width--;
- }
-}
-#endif /* HAVE_ALTIVEC */
-
-/* slow version to handle limit cases. Does not need optimisation */
+/* slow version to handle limit cases. Does not need optimization */
static void h_resample_slow(uint8_t *dst, int dst_width,
const uint8_t *src, int src_width,
int src_start, int src_incr, int16_t *filters)
n = dst_width;
}
#ifdef HAVE_MMX
- if ((mm_flags & MM_MMX) && NB_TAPS == 4)
+ if ((mm_flags & FF_MM_MMX) && NB_TAPS == 4)
h_resample_fast4_mmx(dst, n,
src, src_width, src_start, src_incr, filters);
else
h_resample(new_line, owidth,
src_line, iwidth, - FCENTER * POS_FRAC, s->h_incr,
&s->h_filters[0][0]);
- /* handle ring buffer wraping */
+ /* handle ring buffer wrapping */
if (ring_y >= LINE_BUF_HEIGHT) {
memcpy(s->line_buf + (ring_y - LINE_BUF_HEIGHT) * owidth,
new_line, owidth);
phase_y = get_phase(src_y);
#ifdef HAVE_MMX
/* desactivated MMX because loss of precision */
- if ((mm_flags & MM_MMX) && NB_TAPS == 4 && 0)
+ if ((mm_flags & FF_MM_MMX) && NB_TAPS == 4 && 0)
v_resample4_mmx(output, owidth,
s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
&s->v_filters[phase_y][0]);
else
#endif
#ifdef HAVE_ALTIVEC
- if ((mm_flags & MM_ALTIVEC) && NB_TAPS == 4 && FILTER_BITS <= 6)
- v_resample16_altivec(output, owidth,
- s->line_buf + (ring_y - NB_TAPS + 1) * owidth, owidth,
- &s->v_filters[phase_y][0]);
+ if ((mm_flags & FF_MM_ALTIVEC) && NB_TAPS == 4 && FILTER_BITS <= 6)
+ v_resample16_altivec(output, owidth,
+ s->line_buf + (ring_y - NB_TAPS + 1) * owidth,
+ owidth, &s->v_filters[phase_y][0]);
else
#endif
v_resample(output, owidth,
}
}
-ImgReSampleContext *img_resample_init(int owidth, int oheight,
- int iwidth, int iheight)
-{
- return img_resample_full_init(owidth, oheight, iwidth, iheight,
- 0, 0, 0, 0, 0, 0, 0, 0);
-}
-
ImgReSampleContext *img_resample_full_init(int owidth, int oheight,
int iwidth, int iheight,
int topBand, int bottomBand,
if (!s)
return NULL;
if((unsigned)owidth >= UINT_MAX / (LINE_BUF_HEIGHT + NB_TAPS))
- return NULL;
+ goto fail;
s->line_buf = av_mallocz(owidth * (LINE_BUF_HEIGHT + NB_TAPS));
if (!s->line_buf)
goto fail;
return NULL;
}
+ImgReSampleContext *img_resample_init(int owidth, int oheight,
+ int iwidth, int iheight)
+{
+ return img_resample_full_init(owidth, oheight, iwidth, iheight,
+ 0, 0, 0, 0, 0, 0, 0, 0);
+}
+
void img_resample(ImgReSampleContext *s,
AVPicture *output, const AVPicture *input)
{
av_free(s);
}
+static const char *context_to_name(void* ptr)
+{
+ return "imgconvert";
+}
+
+static const AVClass context_class = { "imgresample", context_to_name, NULL };
+
struct SwsContext *sws_getContext(int srcW, int srcH, int srcFormat,
int dstW, int dstH, int dstFormat,
int flags, SwsFilter *srcFilter,
struct SwsContext *ctx;
ctx = av_malloc(sizeof(struct SwsContext));
- if (ctx)
- ctx->av_class = av_mallocz(sizeof(AVClass));
- if (!ctx || !ctx->av_class) {
+ if (!ctx) {
av_log(NULL, AV_LOG_ERROR, "Cannot allocate a resampling context!\n");
return NULL;
}
+ ctx->av_class = &context_class;
if ((srcH != dstH) || (srcW != dstW)) {
if ((srcFormat != PIX_FMT_YUV420P) || (dstFormat != PIX_FMT_YUV420P)) {
- av_log(NULL, AV_LOG_INFO, "PIX_FMT_YUV420P will be used as an intermediate format for rescaling\n");
+ av_log(ctx, AV_LOG_INFO, "PIX_FMT_YUV420P will be used as an intermediate format for rescaling\n");
}
ctx->resampling_ctx = img_resample_init(dstW, dstH, srcW, srcH);
} else {
} else {
av_free(ctx->resampling_ctx);
}
- av_free(ctx->av_class);
av_free(ctx);
}
&src_pict, ctx->src_pix_fmt,
ctx->resampling_ctx->iwidth, ctx->resampling_ctx->iheight) < 0) {
- av_log(NULL, AV_LOG_ERROR, "pixel format conversion not handled\n");
+ av_log(ctx, AV_LOG_ERROR, "pixel format conversion not handled\n");
res = -1;
goto the_end;
}
resampled_picture, current_pix_fmt,
ctx->resampling_ctx->owidth, ctx->resampling_ctx->oheight) < 0) {
- av_log(NULL, AV_LOG_ERROR, "pixel format conversion not handled\n");
+ av_log(ctx, AV_LOG_ERROR, "pixel format conversion not handled\n");
res = -1;
goto the_end;
}
}
save_pgm("/tmp/in.pgm", img, XSIZE, YSIZE);
- for(i=0;i<sizeof(factors)/sizeof(float);i++) {
+ for(i=0;i<FF_ARRAY_ELEMS(factors);i++) {
fact = factors[i];
xsize = (int)(XSIZE * fact);
ysize = (int)((YSIZE - 100) * fact);
fact = 0.72;
xsize = (int)(XSIZE * fact);
ysize = (int)(YSIZE * fact);
- mm_flags = MM_MMX;
+ mm_flags = FF_MM_MMX;
s = img_resample_init(xsize, ysize, XSIZE, YSIZE);
component_resample(s, img1, xsize, xsize, ysize,
img, XSIZE, XSIZE, YSIZE);