From b405f4e916248874dae9b801910dc94f3dfe68c4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 14 Jul 2013 05:19:44 +0200 Subject: [PATCH] swscale: Add support to specify chroma position Signed-off-by: Michael Niedermayer --- libswscale/options.c | 5 +++++ libswscale/swscale_internal.h | 4 ++++ libswscale/utils.c | 36 ++++++++++++++++++++++++++--------- libswscale/version.h | 2 +- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/libswscale/options.c b/libswscale/options.c index fc571acd15..26e326608f 100644 --- a/libswscale/options.c +++ b/libswscale/options.c @@ -64,6 +64,11 @@ static const AVOption options[] = { { "param0", "scaler param 0", OFFSET(param[0]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, VE }, { "param1", "scaler param 1", OFFSET(param[1]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, VE }, + { "src_v_chr_pos", "source vertical chroma position in luma grid/256" , OFFSET(src_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 512, VE }, + { "src_h_chr_pos", "source horizontal chroma position in luma grid/256", OFFSET(src_h_chr_pos), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 512, VE }, + { "dst_v_chr_pos", "source vertical chroma position in luma grid/256" , OFFSET(dst_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 512, VE }, + { "dst_h_chr_pos", "source horizontal chroma position in luma grid/256", OFFSET(dst_h_chr_pos), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 512, VE }, + { NULL } }; diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 2241ba5235..02214f3473 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -382,6 +382,10 @@ typedef struct SwsContext { int dst0Alpha; int srcXYZ; int dstXYZ; + int src_h_chr_pos; + int dst_h_chr_pos; + int src_v_chr_pos; + int dst_v_chr_pos; int yuv2rgb_y_offset; int yuv2rgb_y_coeff; int yuv2rgb_v2r_coeff; diff --git a/libswscale/utils.c b/libswscale/utils.c index 0aa540b8e7..59bf49a0b2 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -252,12 +252,21 @@ static double getSplineCoeff(double a, double b, double c, double d, dist - 1.0); } +static av_cold int get_local_pos(SwsContext *s, int chr_subsample, int pos, int dir) +{ + if (pos < 0) { + pos = (128 << chr_subsample) - 128; + } + pos += 128; // relative to ideal left edge + return pos >> chr_subsample; +} + static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, int *outFilterSize, int xInc, int srcW, int dstW, int filterAlign, int one, int flags, int cpu_flags, SwsVector *srcFilter, SwsVector *dstFilter, - double param[2]) + double param[2], int srcPos, int dstPos) { int i; int filterSize; @@ -273,7 +282,7 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, // NOTE: the +3 is for the MMX(+1) / SSE(+3) scaler which reads over the end FF_ALLOC_OR_GOTO(NULL, *filterPos, (dstW + 3) * sizeof(**filterPos), fail); - if (FFABS(xInc - 0x10000) < 10) { // unscaled + if (FFABS(xInc - 0x10000) < 10 && srcPos == dstPos) { // unscaled int i; filterSize = 1; FF_ALLOCZ_OR_GOTO(NULL, filter, @@ -290,7 +299,7 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, FF_ALLOC_OR_GOTO(NULL, filter, dstW * sizeof(*filter) * filterSize, fail); - xDstInSrc = xInc / 2 - 0x8000; + xDstInSrc = ((srcPos*xInc)>>8) - ((dstPos*0x8000)>>7); for (i = 0; i < dstW; i++) { int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16; @@ -306,7 +315,7 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, FF_ALLOC_OR_GOTO(NULL, filter, dstW * sizeof(*filter) * filterSize, fail); - xDstInSrc = xInc / 2 - 0x8000; + xDstInSrc = ((srcPos*xInc)>>8) - ((dstPos*0x8000)>>7); for (i = 0; i < dstW; i++) { int xx = (xDstInSrc - ((filterSize - 1) << 15) + (1 << 15)) >> 16; int j; @@ -357,7 +366,7 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, FF_ALLOC_OR_GOTO(NULL, filter, dstW * sizeof(*filter) * filterSize, fail); - xDstInSrc = xInc - 0x10000; + xDstInSrc = ((srcPos*xInc)>>7) - ((dstPos*0x10000)>>7); for (i = 0; i < dstW; i++) { int xx = (xDstInSrc - ((filterSize - 2) << 16)) / (1 << 17); int j; @@ -1392,14 +1401,18 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, srcW, dstW, filterAlign, 1 << 14, (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags, cpu_flags, srcFilter->lumH, dstFilter->lumH, - c->param) < 0) + c->param, + get_local_pos(c, 0, 0, 0), + get_local_pos(c, 0, 0, 0)) < 0) goto fail; if (initFilter(&c->hChrFilter, &c->hChrFilterPos, &c->hChrFilterSize, c->chrXInc, c->chrSrcW, c->chrDstW, filterAlign, 1 << 14, (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags, cpu_flags, srcFilter->chrH, dstFilter->chrH, - c->param) < 0) + c->param, + get_local_pos(c, c->chrSrcHSubSample, c->src_h_chr_pos, 0), + get_local_pos(c, c->chrDstHSubSample, c->dst_h_chr_pos, 0)) < 0) goto fail; } } // initialize horizontal stuff @@ -1415,14 +1428,19 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, c->lumYInc, srcH, dstH, filterAlign, (1 << 12), (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags, cpu_flags, srcFilter->lumV, dstFilter->lumV, - c->param) < 0) + c->param, + get_local_pos(c, 0, 0, 1), + get_local_pos(c, 0, 0, 1)) < 0) goto fail; if (initFilter(&c->vChrFilter, &c->vChrFilterPos, &c->vChrFilterSize, c->chrYInc, c->chrSrcH, c->chrDstH, filterAlign, (1 << 12), (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags, cpu_flags, srcFilter->chrV, dstFilter->chrV, - c->param) < 0) + c->param, + get_local_pos(c, c->chrSrcVSubSample, c->src_v_chr_pos, 1), + get_local_pos(c, c->chrDstVSubSample, c->dst_v_chr_pos, 1)) < 0) + goto fail; #if HAVE_ALTIVEC diff --git a/libswscale/version.h b/libswscale/version.h index f635e3d0a7..1c4520926a 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -27,7 +27,7 @@ #include "libavutil/avutil.h" #define LIBSWSCALE_VERSION_MAJOR 2 -#define LIBSWSCALE_VERSION_MINOR 3 +#define LIBSWSCALE_VERSION_MINOR 4 #define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \