diff options
author | Paul B Mahol <onemda@gmail.com> | 2016-06-24 20:16:22 +0200 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2016-07-04 20:39:16 +0200 |
commit | de30863fffae0880cfd11fcc95e8bb64f9fe44a7 (patch) | |
tree | c03fd590e2ec0a0af0403aa1ca7b1c1a00e5dee9 /libavfilter/vf_rotate.c | |
parent | 1ad4471526c70d073b19bd551dc4193457d1e610 (diff) | |
download | ffmpeg-de30863fffae0880cfd11fcc95e8bb64f9fe44a7.tar.gz |
avfilter/vf_rotate: add >8 bit depth support
Signed-off-by: Paul B Mahol <onemda@gmail.com>
Diffstat (limited to 'libavfilter/vf_rotate.c')
-rw-r--r-- | libavfilter/vf_rotate.c | 171 |
1 files changed, 109 insertions, 62 deletions
diff --git a/libavfilter/vf_rotate.c b/libavfilter/vf_rotate.c index 47dc01e7d8..b37685a6c6 100644 --- a/libavfilter/vf_rotate.c +++ b/libavfilter/vf_rotate.c @@ -60,7 +60,7 @@ enum var_name { VAR_VARS_NB }; -typedef struct { +typedef struct RotContext { const AVClass *class; double angle; char *angle_expr_str; ///< expression for the angle @@ -77,6 +77,9 @@ typedef struct { double var_values[VAR_VARS_NB]; FFDrawContext draw; FFDrawColor color; + uint8_t *(*interpolate_bilinear)(uint8_t *dst_color, + const uint8_t *src, int src_linesize, int src_linestep, + int x, int y, int max_x, int max_y); } RotContext; typedef struct ThreadData { @@ -142,6 +145,14 @@ static int query_formats(AVFilterContext *ctx) AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA420P, + AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_YUVA420P10LE, + AV_PIX_FMT_YUV444P10LE, AV_PIX_FMT_YUVA444P10LE, + AV_PIX_FMT_YUV420P12LE, + AV_PIX_FMT_YUV444P12LE, + AV_PIX_FMT_YUV444P16LE, AV_PIX_FMT_YUVA444P16LE, + AV_PIX_FMT_YUV420P16LE, AV_PIX_FMT_YUVA420P16LE, + AV_PIX_FMT_YUV444P9LE, AV_PIX_FMT_YUVA444P9LE, + AV_PIX_FMT_YUV420P9LE, AV_PIX_FMT_YUVA420P9LE, AV_PIX_FMT_NONE }; @@ -187,6 +198,93 @@ static const char * const func1_names[] = { NULL }; +#define FIXP (1<<16) +#define FIXP2 (1<<20) +#define INT_PI 3294199 //(M_PI * FIXP2) + +/** + * Compute the sin of a using integer values. + * Input is scaled by FIXP2 and output values are scaled by FIXP. + */ +static int64_t int_sin(int64_t a) +{ + int64_t a2, res = 0; + int i; + if (a < 0) a = INT_PI-a; // 0..inf + a %= 2 * INT_PI; // 0..2PI + + if (a >= INT_PI*3/2) a -= 2*INT_PI; // -PI/2 .. 3PI/2 + if (a >= INT_PI/2 ) a = INT_PI - a; // -PI/2 .. PI/2 + + /* compute sin using Taylor series approximated to the fifth term */ + a2 = (a*a)/(FIXP2); + for (i = 2; i < 11; i += 2) { + res += a; + a = -a*a2 / (FIXP2*i*(i+1)); + } + return (res + 8)>>4; +} + +/** + * Interpolate the color in src at position x and y using bilinear + * interpolation. + */ +static uint8_t *interpolate_bilinear8(uint8_t *dst_color, + const uint8_t *src, int src_linesize, int src_linestep, + int x, int y, int max_x, int max_y) +{ + int int_x = av_clip(x>>16, 0, max_x); + int int_y = av_clip(y>>16, 0, max_y); + int frac_x = x&0xFFFF; + int frac_y = y&0xFFFF; + int i; + int int_x1 = FFMIN(int_x+1, max_x); + int int_y1 = FFMIN(int_y+1, max_y); + + for (i = 0; i < src_linestep; i++) { + int s00 = src[src_linestep * int_x + i + src_linesize * int_y ]; + int s01 = src[src_linestep * int_x1 + i + src_linesize * int_y ]; + int s10 = src[src_linestep * int_x + i + src_linesize * int_y1]; + int s11 = src[src_linestep * int_x1 + i + src_linesize * int_y1]; + int s0 = (((1<<16) - frac_x)*s00 + frac_x*s01); + int s1 = (((1<<16) - frac_x)*s10 + frac_x*s11); + + dst_color[i] = ((int64_t)((1<<16) - frac_y)*s0 + (int64_t)frac_y*s1) >> 32; + } + + return dst_color; +} + +/** + * Interpolate the color in src at position x and y using bilinear + * interpolation. + */ +static uint8_t *interpolate_bilinear16(uint8_t *dst_color, + const uint8_t *src, int src_linesize, int src_linestep, + int x, int y, int max_x, int max_y) +{ + int int_x = av_clip(x>>16, 0, max_x); + int int_y = av_clip(y>>16, 0, max_y); + int frac_x = x&0xFFFF; + int frac_y = y&0xFFFF; + int i; + int int_x1 = FFMIN(int_x+1, max_x); + int int_y1 = FFMIN(int_y+1, max_y); + + for (i = 0; i < src_linestep; i+=2) { + int s00 = AV_RL16(&src[src_linestep * int_x + i + src_linesize * int_y ]); + int s01 = AV_RL16(&src[src_linestep * int_x1 + i + src_linesize * int_y ]); + int s10 = AV_RL16(&src[src_linestep * int_x + i + src_linesize * int_y1]); + int s11 = AV_RL16(&src[src_linestep * int_x1 + i + src_linesize * int_y1]); + int s0 = (((1<<16) - frac_x)*s00 + frac_x*s01); + int s1 = (((1<<16) - frac_x)*s10 + frac_x*s11); + + AV_WL16(&dst_color[i], ((int64_t)((1<<16) - frac_y)*s0 + (int64_t)frac_y*s1) >> 32); + } + + return dst_color; +} + static int config_props(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -203,6 +301,11 @@ static int config_props(AVFilterLink *outlink) rot->hsub = pixdesc->log2_chroma_w; rot->vsub = pixdesc->log2_chroma_h; + if (pixdesc->comp[0].depth == 8) + rot->interpolate_bilinear = interpolate_bilinear8; + else + rot->interpolate_bilinear = interpolate_bilinear16; + rot->var_values[VAR_IN_W] = rot->var_values[VAR_IW] = inlink->w; rot->var_values[VAR_IN_H] = rot->var_values[VAR_IH] = inlink->h; rot->var_values[VAR_HSUB] = 1<<rot->hsub; @@ -255,63 +358,6 @@ static int config_props(AVFilterLink *outlink) return 0; } -#define FIXP (1<<16) -#define FIXP2 (1<<20) -#define INT_PI 3294199 //(M_PI * FIXP2) - -/** - * Compute the sin of a using integer values. - * Input is scaled by FIXP2 and output values are scaled by FIXP. - */ -static int64_t int_sin(int64_t a) -{ - int64_t a2, res = 0; - int i; - if (a < 0) a = INT_PI-a; // 0..inf - a %= 2 * INT_PI; // 0..2PI - - if (a >= INT_PI*3/2) a -= 2*INT_PI; // -PI/2 .. 3PI/2 - if (a >= INT_PI/2 ) a = INT_PI - a; // -PI/2 .. PI/2 - - /* compute sin using Taylor series approximated to the fifth term */ - a2 = (a*a)/(FIXP2); - for (i = 2; i < 11; i += 2) { - res += a; - a = -a*a2 / (FIXP2*i*(i+1)); - } - return (res + 8)>>4; -} - -/** - * Interpolate the color in src at position x and y using bilinear - * interpolation. - */ -static uint8_t *interpolate_bilinear(uint8_t *dst_color, - const uint8_t *src, int src_linesize, int src_linestep, - int x, int y, int max_x, int max_y) -{ - int int_x = av_clip(x>>16, 0, max_x); - int int_y = av_clip(y>>16, 0, max_y); - int frac_x = x&0xFFFF; - int frac_y = y&0xFFFF; - int i; - int int_x1 = FFMIN(int_x+1, max_x); - int int_y1 = FFMIN(int_y+1, max_y); - - for (i = 0; i < src_linestep; i++) { - int s00 = src[src_linestep * int_x + i + src_linesize * int_y ]; - int s01 = src[src_linestep * int_x1 + i + src_linesize * int_y ]; - int s10 = src[src_linestep * int_x + i + src_linesize * int_y1]; - int s11 = src[src_linestep * int_x1 + i + src_linesize * int_y1]; - int s0 = (((1<<16) - frac_x)*s00 + frac_x*s01); - int s1 = (((1<<16) - frac_x)*s10 + frac_x*s11); - - dst_color[i] = ((int64_t)((1<<16) - frac_y)*s0 + (int64_t)frac_y*s1) >> 32; - } - - return dst_color; -} - static av_always_inline void copy_elem(uint8_t *pout, const uint8_t *pin, int elem_size) { int v; @@ -421,9 +467,9 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs) uint8_t inp_inv[4]; /* interpolated input value */ pout = out->data[plane] + j * out->linesize[plane] + i * rot->draw.pixelstep[plane]; if (rot->use_bilinear) { - pin = interpolate_bilinear(inp_inv, - in->data[plane], in->linesize[plane], rot->draw.pixelstep[plane], - x, y, inw-1, inh-1); + pin = rot->interpolate_bilinear(inp_inv, + in->data[plane], in->linesize[plane], rot->draw.pixelstep[plane], + x, y, inw-1, inh-1); } else { int x2 = av_clip(x1, 0, inw-1); int y2 = av_clip(y1, 0, inh-1); @@ -434,7 +480,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs) *pout = *pin; break; case 2: - *((uint16_t *)pout) = *((uint16_t *)pin); + v = AV_RL16(pin); + AV_WL16(pout, v); break; case 3: v = AV_RB24(pin); |