[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