mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-02-19 05:17:04 +00:00
avfilter/vf_rotate: add >8 bit depth support
Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
parent
1ad4471526
commit
de30863fff
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user