[FFmpeg-devel] [WIP] rotate filter(s)

Michael Niedermayer michaelni
Tue Oct 5 14:36:19 CEST 2010


On Mon, Oct 04, 2010 at 10:27:29PM +0200, Stefano Sabatini wrote:
> On date Sunday 2010-10-03 21:35:00 +0200, Michael Niedermayer encoded:
> > On Sun, Oct 03, 2010 at 07:35:49PM +0200, Stefano Sabatini wrote:
> > > Hi,
> > > 
> > > in attachment a first stub at the rotate filter. I don't know if it is
> > > a good idea to keep the float variant, while the rotate_ss may be
> > > useful (and the rotation angle could be made parametric).
> > > 
> > > The integer-only rotating code is taken from tests/rotozoom.c, I don't
> > > know if we have a corresponding version in the libs.
> > > 
> > > fill_line_with_color() and draw_rectangle() are duplicated from
> > > vf_pad.c, so maybe we should make them public (or at least ff_ them),
> > > drawutils.[ch] may be a good place where to put them.
> > > 
> > > Note that ffplay/SDL doesn't work with odd width/height sizes, so you
> > > may need to rescale to an even wxh size (this could be done with a
> > > parametric scale as discussed some months ago).
> > > 
> > > What this rotate filter still lacks, apart a resolution to the
> > > refactoring problems mentioned above, is a YUV planar version of the
> > > rotating function, and possibly the extension to other RGB variants,
> > > which should be pretty easy to add. Everyone feel free to continue to
> > > work on this and post an updated patch.
> > 
> > looks like you implemented nearest neighbor sampling in int and float
> > thats not what rotozoom does, also see vf_perspective.c
> 
> Implemented bilinear interpolation as in rotozoom.c, merged the three
> variants into a single one and made the expression for angle
> parametric.
> 
> Still missing: more packed and planar formats for the non-float path,
> a more efficient way for filling the background.
> 
> Should I remove the float path?

if its slower then yes.


[...]
> +/**
> + * @file
> + * rotation filter
> + *
> + * @todo handle planar pixel and more packed formats in the non-float path
> +*/
> +
> +#include "libavutil/eval.h"
> +#include "libavutil/intreadwrite.h"
> +#include "libavutil/pixdesc.h"
> +#include "avfilter.h"
> +#include "drawutils.h"
> +#include "parseutils.h"
> +
> +static const char *var_names[] = {
> +    "E",
> +    "PHI",
> +    "PI",
> +    "w",            ///< width  of the input video
> +    "h",            ///< height of the input video
> +    "n",            ///< number of frame
> +    "t",            ///< timestamp expressed in seconds
> +    NULL
> +};
> +
> +enum var_name {
> +    VAR_E,
> +    VAR_PHI,
> +    VAR_PI,
> +    VAR_W,
> +    VAR_H,
> +    VAR_N,
> +    VAR_T,
> +    VAR_VARS_NB
> +};
> +

> +#define FIXP (1<<16)
> +#define INT_PI 205887 //(M_PI * FIXP)
> +
> +/**
> + * Compute the power of a a^p using integer values.
> + * Input and output values are scaled by FIXP.
> + */
> +static int64_t int_pow(int64_t a, int p)
> +{
> +    int64_t v = FIXP;
> +
> +    for (; p; p--) {
> +        v *= a;
> +        v /= FIXP;
> +    }
> +
> +    return v;
> +}
> +
> +/**
> + * Compute the sin of a using integer values.
> + * Input and output values are scaled by FIXP.
> + */
> +static int64_t int_sin(int64_t a)
> +{
> +    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
> +
> +    return a - int_pow(a, 3)/6 + int_pow(a, 5)/120 - int_pow(a, 7)/5040;

a2= a*a/X
for(i=2; a; i+=2){
    r+= a;
    a= -a*a2/(X*i*(i+1));
}

and test it against sin() please
and with the 16bit fixp most things fit in 32bit



> +}
> +
> +/**
> + * Interpolate the color in src at position x and y using bilinear
> + * interpolation.
> + *
> + * @param dst_color put here the destination color
> + */
> +static uint8_t *ipol(uint8_t *dst_color,
> +                     const uint8_t *src, const int src_linesize, int x, int y,
> +                     int max_x, int max_y)
> +{
> +    int int_x = x>>16;
> +    int int_y = y>>16;
> +    int frac_x = x&0xFFFF;
> +    int frac_y = y&0xFFFF;
> +    int i;
> +
> +    for (i = 0; i < 3; i++) {
> +        int s00 = src[3 * int_x                + i + src_linesize * int_y];
> +        int s01 = src[3 * FFMIN(int_x+1,max_x) + i + src_linesize * int_y];
> +        int s10 = src[3 * int_x                + i + src_linesize * FFMIN(int_y+1, max_y)];
> +        int s11 = src[3 * FFMIN(int_x+1,max_x) + i + src_linesize * FFMIN(int_y+1, max_y)];
> +        int s0 = (((1<<16) - frac_x)*s00 + frac_x*s01)>>8;
> +        int s1 = (((1<<16) - frac_x)*s10 + frac_x*s11)>>8;
> +
> +        dst_color[i] = (((1<<16) - frac_y)*s0 + frac_y*s1)>>24;
> +    }

the >>8 can be avoided by adjusting perecission sanely
the FFMIN doesnt belong in the loop



> +
> +    return dst_color;
> +}
> +
> +typedef struct {
> +    const AVClass *class;
> +    int angle;
> +    char *angle_expr;       ///< expression for the angle
> +    AVExpr *angle_pexpr;    ///< parsed expression for the angle
> +    uint8_t bgcolor[4];     ///< color expressed either in YUVA or RGBA colorspace for the padding area
> +    char *bgcolor_str;
> +    int hsub, vsub;
> +    int use_float;
> +    int use_bilinear;
> +    int keep_same_size;
> +    uint8_t *line[4];
> +    int      line_step[4];
> +    float transx, transy; ///< how much to translate (in pixels)
> +    float sinx, cosx;
> +    int output_h, output_w;
> +    double var_values[VAR_VARS_NB];
> +} RotContext;
> +
> +#define OFFSET(x) offsetof(RotContext, x)
> +
> +static const AVOption rot_options[]= {
> +    {"angle",    "set angle expression", OFFSET(angle_expr),     FF_OPT_TYPE_STRING, 0,  CHAR_MIN, CHAR_MAX },
> +    {"bgcolor",  "set background color", OFFSET(bgcolor_str),    FF_OPT_TYPE_STRING, 0,  CHAR_MIN, CHAR_MAX },
> +    {"float",    "use float path",       OFFSET(use_float),      FF_OPT_TYPE_INT,    0,         0,        1 },
> +    {"ss",       "keep same size",       OFFSET(keep_same_size), FF_OPT_TYPE_INT,    0,         0,        1 },
> +    {"bilinear", "use bilinear interpolation", OFFSET(use_bilinear), FF_OPT_TYPE_INT, 1,        0,        1 },
> +    {NULL},
> +};

bilinear should be default

and this filter looks kinda big for what it does
if i compare it to lets say vf_perspective that does more

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

It is dangerous to be right in matters on which the established authorities
are wrong. -- Voltaire
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20101005/435eecd3/attachment.pgp>



More information about the ffmpeg-devel mailing list