avfilter/vf_rotate: make int*90° rotates suck less speedwise
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 18 Apr 2014 22:08:15 +0000 (00:08 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 18 Apr 2014 23:23:23 +0000 (01:23 +0200)
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libavfilter/vf_rotate.c

index 16c4a11..7e5b12b 100644 (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;
     }