diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2014-04-19 00:08:15 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-04-19 01:23:23 +0200 |
commit | d340dabb76357ed4238fcdc859132007f54f51e8 (patch) | |
tree | aef80db99eab6c17609147752d77d36c92e1bfc5 /libavfilter | |
parent | c9aab1ee7f3314ad9d79bc5f6f7a00ebe3f4e97f (diff) | |
download | ffmpeg-d340dabb76357ed4238fcdc859132007f54f51e8.tar.gz |
avfilter/vf_rotate: make int*90° rotates suck less speedwise
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavfilter')
-rw-r--r-- | libavfilter/vf_rotate.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/libavfilter/vf_rotate.c b/libavfilter/vf_rotate.c index 16c4a11873..7e5b12b42d 100644 --- a/libavfilter/vf_rotate.c +++ b/libavfilter/vf_rotate.c @@ -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; } |