summaryrefslogtreecommitdiff
path: root/libavfilter/vf_rotate.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2016-06-24 20:16:22 +0200
committerPaul B Mahol <onemda@gmail.com>2016-07-04 20:39:16 +0200
commitde30863fffae0880cfd11fcc95e8bb64f9fe44a7 (patch)
treec03fd590e2ec0a0af0403aa1ca7b1c1a00e5dee9 /libavfilter/vf_rotate.c
parent1ad4471526c70d073b19bd551dc4193457d1e610 (diff)
downloadffmpeg-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.c171
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);