aboutsummaryrefslogtreecommitdiffstats
path: root/libavfilter
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2014-04-19 00:08:15 +0200
committerMichael Niedermayer <michaelni@gmx.at>2014-04-19 01:23:23 +0200
commitd340dabb76357ed4238fcdc859132007f54f51e8 (patch)
treeaef80db99eab6c17609147752d77d36c92e1bfc5 /libavfilter
parentc9aab1ee7f3314ad9d79bc5f6f7a00ebe3f4e97f (diff)
downloadffmpeg-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.c77
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;
}