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

Stefano Sabatini stefano.sabatini-lala
Tue Oct 5 16:18:35 CEST 2010


On date Tuesday 2010-10-05 14:36:19 +0200, Michael Niedermayer encoded:
> 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

Most comments yet to be addressed.

The filter is big because of the float path and the parametric option
(and maybe can be simplified more).

Regards.
-- 
FFmpeg = Funny & Faithful Mere Puristic Everlasting Gargoyle



More information about the ffmpeg-devel mailing list