Commit de30863f authored by Paul B Mahol's avatar Paul B Mahol

avfilter/vf_rotate: add >8 bit depth support

Signed-off-by: 's avatarPaul B Mahol <onemda@gmail.com>
parent 1ad44715
......@@ -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);
......
......@@ -13,8 +13,22 @@ rgb24 f4438057d046e6d98ade4e45294b21be
rgba b6e1b441c365e03b5ffdf9b7b68d9a0c
yuv410p 5d4d992a7728431aa4e0700f87fb7fd8
yuv420p a014c7eb7a8385d1dd092b7a583f1bff
yuv420p10le 15c83294ef560d57f25d16ae6e0fc70c
yuv420p12le c19a477a07fcf88e37ab37b416d064c0
yuv420p16le dae8da9edd4255051e3e546ae7ed9bd3
yuv420p9le 83a6d32c91c15a3bc334bb9abf920654
yuv444p 8f90fb3a757878c545a8bfe5d19a9bab
yuv444p10le 6d736fa464ff2de2b07e0a56af8444b7
yuv444p12le 08a81b2ea9c7c8b447e40ef8f4a46a4a
yuv444p16le 781c22317c02b3dd4225709000bdb847
yuv444p9le caef947b8aff5b52285385c6ae9b2439
yuva420p b227672e56215e184e702c02a771d7f3
yuva420p10le 01e94ee605714396e69b013c11dda348
yuva420p16le b1930ab28ffe031c78ca28d3406311c8
yuva420p9le 0e9c9803aaaddc9f38e419de587793c2
yuva444p 459fad5abfd16db9bb6a52761dc74cc1
yuva444p10le 92f820d3481b7ebcb48b98a73e7b4c90
yuva444p16le 2ed56ea50fafda4d226c9b133755dad8
yuva444p9le 4eeb5988df0740fea720da1e31bbb829
yuvj420p 8f3d8f1b4577d11082d5ab8a901e048d
yuvj444p b161e6d5a941e2a4bb7bc56ef8af623f
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment