avfilter/vf_rotate: make int*90° rotates suck less speedwise

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2014-04-19 00:08:15 +02:00
parent c9aab1ee7f
commit d340dabb76

View File

@ -36,6 +36,8 @@
#include "internal.h"
#include "video.h"
#include <float.h>
static const char *var_names[] = {
"in_w" , "iw", ///< width of the input video
"in_h" , "ih", ///< height of the input video
@ -308,6 +310,62 @@ static uint8_t *interpolate_bilinear(uint8_t *dst_color,
return dst_color;
}
static av_always_inline void copy_elem(uint8_t *pout, const uint8_t *pin, int elem_size)
{
int v;
switch (elem_size) {
case 1:
*pout = *pin;
break;
case 2:
*((uint16_t *)pout) = *((uint16_t *)pin);
break;
case 3:
v = AV_RB24(pin);
AV_WB24(pout, v);
break;
case 4:
*((uint32_t *)pout) = *((uint32_t *)pin);
break;
default:
memcpy(pout, pin, elem_size);
break;
}
}
static av_always_inline void simple_rotate_internal(uint8_t *dst, const uint8_t *src, int src_linesize, int angle, int elem_size, int len)
{
int i;
switch(angle) {
case 0:
memcpy(dst, src, elem_size * len);
break;
case 1:
for (i = 0; i<len; i++)
copy_elem(dst + i*elem_size, src + (len-i-1)*src_linesize, elem_size);
break;
case 2:
for (i = 0; i<len; i++)
copy_elem(dst + i*elem_size, src + (len-i-1)*elem_size, elem_size);
break;
case 3:
for (i = 0; i<len; i++)
copy_elem(dst + i*elem_size, src + i*src_linesize, elem_size);
break;
}
}
static av_always_inline void simple_rotate(uint8_t *dst, const uint8_t *src, int src_linesize, int angle, int elem_size, int len)
{
switch(elem_size) {
case 1 : simple_rotate_internal(dst, src, src_linesize, angle, 1, len); break;
case 2 : simple_rotate_internal(dst, src, src_linesize, angle, 2, len); break;
case 3 : simple_rotate_internal(dst, src, src_linesize, angle, 3, len); break;
case 4 : simple_rotate_internal(dst, src, src_linesize, angle, 4, len); break;
default: simple_rotate_internal(dst, src, src_linesize, angle, elem_size, len); break;
}
}
#define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)*av_q2d(tb))
static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
@ -331,6 +389,24 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
x = xprime + xi + FIXP*(inw-1)/2;
y = yprime + yi + FIXP*(inh-1)/2;
if (fabs(rot->angle - 0) < FLT_EPSILON && outw == inw && outh == inh) {
simple_rotate(out->data[plane] + j * out->linesize[plane],
in->data[plane] + j * in->linesize[plane],
in->linesize[plane], 0, rot->draw.pixelstep[plane], outw);
} else if (fabs(rot->angle - M_PI/2) < FLT_EPSILON && outw == inh && outh == inw) {
simple_rotate(out->data[plane] + j * out->linesize[plane],
in->data[plane] + j * rot->draw.pixelstep[plane],
in->linesize[plane], 1, rot->draw.pixelstep[plane], outw);
} else if (fabs(rot->angle - M_PI) < FLT_EPSILON && outw == inw && outh == inh) {
simple_rotate(out->data[plane] + j * out->linesize[plane],
in->data[plane] + (outh-j-1) * in->linesize[plane],
in->linesize[plane], 2, rot->draw.pixelstep[plane], outw);
} else if (fabs(rot->angle - 3*M_PI/2) < FLT_EPSILON && outw == inh && outh == inw) {
simple_rotate(out->data[plane] + j * out->linesize[plane],
in->data[plane] + (outh-j-1) * rot->draw.pixelstep[plane],
in->linesize[plane], 3, rot->draw.pixelstep[plane], outw);
} else {
for (i = 0; i < outw; i++) {
int32_t v;
int x1, y1;
@ -373,6 +449,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
x += c;
y -= s;
}
}
xprime += s;
yprime += c;
}