[FFmpeg-soc] libavfilter audio work - qualification task

Stefano Sabatini stefano.sabatini-lala at poste.it
Sat Apr 10 01:18:24 CEST 2010


On date Friday 2010-04-09 08:02:50 -0700, S.N. Hemanth Meenakshisundaram encoded:
> On 04/08/2010 09:54 PM, S.N. Hemanth Meenakshisundaram wrote:
> >I removed the Makefile changes and added what you suggested above
> >into the configure script (as in configure.diff).
> >config.err still showed some errors initially and after tweaking
> >it a little, the errors stopped. (My headers are in
> >/usr/include/freetype).
[...]
> >Can you give me some pointers on what could be wrong. For the 1st
> >problem, I tried looking for any other places a new filter needs
> >to be registered/included and couldn't find any. For the 2nd,
> >
> >I am a newbie to configure scripts, so can you please explain what
> >the configure script lines actually mean.

For the moment use this:

--- a/configure
+++ b/configure
@@ -2699,6 +2699,8 @@ enabled_any alsa_indev alsa_outdev && check_lib2 alsa/asou
 
 enabled jack_indev && check_lib2 jack/jack.h jack_client_open -ljack
 
+enabled drawtext_filter && add_cflags $(pkg-config --cflags freetype2) && requi
+
 enabled x11grab                         &&
 check_header X11/Xlib.h                 &&
 check_header X11/extensions/XShm.h      &&

I have still to think about this /ask to Mans if this is fine (the
problem with this is that the user has to explicitely disable the
drawtext filter if libfreetype is not present), 

> >
> >Thanks,
> >
> Had missed out uninit earlier. Attaching fixed version. From the
> config.err log, it looks like -lfreetype is included and yet the
> linking fails. I tried building a standalone program using freetype
> in the same way and it works. So the freetype libs and include paths
> are ok and something must be going wrong with configure. Could
> someone help me out with a quick way to link in the library directly
> so I can test drawtext for now.
> 
> Thanks
> 

> Index: allfilters.c
> ===================================================================
> --- allfilters.c	(revision 5734)
> +++ allfilters.c	(working copy)
> @@ -54,6 +54,7 @@
>      REGISTER_FILTER (SPLIT,       split,       vf);
>      REGISTER_FILTER (TRANSPOSE,   transpose,   vf);
>      REGISTER_FILTER (VFLIP,       vflip,       vf);
> +    REGISTER_FILTER (DRAWTEXT,    drawtext,    vf);
>  
>      REGISTER_FILTER (BUFFER,      buffer,      vsrc);
>      REGISTER_FILTER (MOVIE,       movie,       vsrc);
> Index: Makefile
> ===================================================================
> --- Makefile	(revision 5734)
> +++ Makefile	(working copy)
> @@ -35,6 +35,7 @@
>  OBJS-$(CONFIG_SPLIT_FILTER)                  += vf_split.o
>  OBJS-$(CONFIG_TRANSPOSE_FILTER)              += vf_transpose.o
>  OBJS-$(CONFIG_VFLIP_FILTER)                  += vf_vflip.o
> +OBJS-$(CONFIG_DRAWTEXT_FILTER)               += vf_drawtext.o
>  
>  OBJS-$(CONFIG_BUFFER_FILTER)                 += vsrc_buffer.o
>  OBJS-$(CONFIG_MOVIE_FILTER)                  += vsrc_movie.o
> Index: vf_drawtext.c
> ===================================================================
> --- vf_drawtext.c	(revision 0)
> +++ vf_drawtext.c	(revision 0)
> @@ -0,0 +1,589 @@
> +/*
> + * vf_drawtext.c: print text over the screen
> + ******************************************************************************
> + * Options:
> + * -f <filename>    font filename (MANDATORY!!!)
> + * -s <pixel_size>  font size in pixels [default 16]
> + * -b               print background
> + * -o               outline glyphs (use the bg color)
> + * -x <pos>         x position ( >= 0) [default 0]
> + * -y <pos>         y position ( >= 0) [default 0]
> + * -t <text>        text to print (will be passed to strftime())
> + *                  MANDATORY: will be used even when -T is used.
> + *                  in this case, -t will be used if some error
> + *                  occurs
> + * -T <filename>    file with the text (re-read every frame)
> + * -c <#RRGGBB>     foreground color ('internet' way) [default #ffffff]
> + * -C <#RRGGBB>     background color ('internet' way) [default #000000]
> + *
> + ******************************************************************************
> + * Features:
> + * - True Type, Type1 and others via FreeType2 library
> + * - Font kerning (better output)
> + * - Line Wrap (if the text doesn't fit, the next char go to the next line)
> + * - Background box
> + * - Outline
> + ******************************************************************************

User-documentation for filters should be put in doc/libavfilter.texi,
also I don't like this syntax, possibly we should try hard at giving a
consistent interface to the user, so we should either use
PARAM-1:PARAM-2:...:PARAM-N either use libavutil/parseutils.c (which
still depends on opt.c so I don't believe Michail won't accept this to
be included in the main repo, but that's not a problem for now).

> + * Original vhook author: Gustavo Sverzut Barbieri <gsbarbieri at yahoo.com.br>
> + * Libavfilter version  : S.N. Hemanth Meenakshisundaram <smeenaks at ucsd.edu>
> + *
> + * Example usage : 
> + * ffmpeg -i input.avi -vfilters \
> + * 'drawtext=f:Vera.ttf:t:Test Text:x:5:y:5:s:20' output.avi
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +/**
> + * @file libavfilter/vf_drawtext.c
> + * video filter to draw text over screen
> + */
> +
> +#define MAXSIZE_TEXT 1024
> +
> +#include "avfilter.h"
> +#include "libavutil/pixdesc.h"
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <fcntl.h>
> +#include <stdarg.h>
> +#include <string.h>
> +#include <unistd.h>
> +#undef time
> +#include <sys/time.h>
> +#include <time.h>

please avoid unnecessary headers inclusion

> +#include <ft2build.h>
> +#include <freetype/config/ftheader.h>
> +#include FT_FREETYPE_H
> +#include FT_GLYPH_H
> +
> +#define SCALEBITS 10
> +#define DEF_DRAWTEXT_FONT_SZ 16
> +#define MAX_DRAWTEXT_OPT 10
> +#define ONE_HALF  (1 << (SCALEBITS - 1))
> +#define FIX(x)    ((int) ((x) * (1<<SCALEBITS) + 0.5))
> +
> +#define RGB_TO_YUV(rgb_color, yuv_color) do { \
> +  yuv_color[0] = (FIX(0.29900)    * rgb_color[0] + FIX(0.58700) * rgb_color[1] + FIX(0.11400) * rgb_color[2] + ONE_HALF) >> SCALEBITS; \
> +  yuv_color[2] = ((FIX(0.50000)   * rgb_color[0] - FIX(0.41869) * rgb_color[1] - FIX(0.08131) * rgb_color[2] + ONE_HALF - 1) >> SCALEBITS) + 128; \
> +  yuv_color[1] = ((- FIX(0.16874) * rgb_color[0] - FIX(0.33126) * rgb_color[1] + FIX(0.50000) * rgb_color[2] + ONE_HALF - 1) >> SCALEBITS) + 128; \
> +} while (0)

use the macro defined in "libavcodec/colorspace.h"

> +#define COPY_3(dst,src) { \
> +    dst[0]=src[0]; \
> +    dst[1]=src[1]; \
> +    dst[2]=src[2]; \
> +}

I don't think this is necessary, a simple memcpy should be enough.

> +#define SET_PIXEL(picture, yuv_color, x, y) { \
> +    picture->data[0][ (x) + (y)*picture->linesize[0] ] = yuv_color[0]; \
> +    picture->data[1][ ((x/2) + (y/2)*picture->linesize[1]) ] = yuv_color[1]; \
> +    picture->data[2][ ((x/2) + (y/2)*picture->linesize[2]) ] = yuv_color[2]; \
> +}
> +
> +#define GET_PIXEL(picture, yuv_color, x, y) { \
> +    yuv_color[0] = picture->data[0][ (x) + (y)*picture->linesize[0] ]; \
> +    yuv_color[1] = picture->data[1][ (x/2) + (y/2)*picture->linesize[1] ]; \
> +    yuv_color[2] = picture->data[2][ (x/2) + (y/2)*picture->linesize[2] ]; \
> +}
> +
> +
> +typedef struct {
> +  unsigned char *text;
> +  char *file;
> +  unsigned int x;
> +  unsigned int y;
> +  int bg;
> +  int outline;
> +  unsigned char bgcolor[3]; /* YUV */
> +  unsigned char fgcolor[3]; /* YUV */
> +  FT_Library library;
> +  FT_Face    face;
> +  FT_Glyph   glyphs[ 255 ];
> +  FT_Bitmap  bitmaps[ 255 ];
> +  int        advance[ 255 ];
> +  int        bitmap_left[ 255 ];
> +  int        bitmap_top[ 255 ];
> +  unsigned int glyphs_index[ 255 ];
> +  int        text_height;
> +  int        baseline;
> +  int use_kerning;
> +} DtextContext;

please use DrawTextContext, no need to use obfuscated names, chars are
cheapers these days.

Also all the variables should be documented when their meaning is not
obvious.

> +static int query_formats(AVFilterContext *ctx)
> +{
> +    static const enum PixelFormat pix_fmts[] = {
> +        PIX_FMT_RGB48BE,      PIX_FMT_RGB48LE,
> +        PIX_FMT_ARGB,         PIX_FMT_RGBA,
> +        PIX_FMT_ABGR,         PIX_FMT_BGRA,
> +        PIX_FMT_RGB24,        PIX_FMT_BGR24,
> +        PIX_FMT_RGB565BE,     PIX_FMT_RGB565LE,
> +        PIX_FMT_RGB555BE,     PIX_FMT_RGB555LE,
> +        PIX_FMT_BGR565BE,     PIX_FMT_BGR565LE,
> +        PIX_FMT_BGR555BE,     PIX_FMT_BGR555LE,
> +        PIX_FMT_GRAY16BE,     PIX_FMT_GRAY16LE,
> +        PIX_FMT_YUV420P16LE,  PIX_FMT_YUV420P16BE,
> +        PIX_FMT_YUV422P16LE,  PIX_FMT_YUV422P16BE,
> +        PIX_FMT_YUV444P16LE,  PIX_FMT_YUV444P16BE,
> +        PIX_FMT_YUV444P,      PIX_FMT_YUV422P,
> +        PIX_FMT_YUV420P,      PIX_FMT_YUV411P,
> +        PIX_FMT_YUV410P,      PIX_FMT_YUV440P,
> +        PIX_FMT_YUVJ444P,     PIX_FMT_YUVJ422P,
> +        PIX_FMT_YUVJ420P,     PIX_FMT_YUVJ440P,
> +        PIX_FMT_YUVA420P,
> +        PIX_FMT_RGB8,         PIX_FMT_BGR8,
> +        PIX_FMT_RGB4_BYTE,    PIX_FMT_BGR4_BYTE,
> +        PIX_FMT_PAL8,         PIX_FMT_GRAY8,
> +        PIX_FMT_NONE
> +    };

Are you sure all these formats are supported?

> +    avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
> +
> +    return 0;
> +}
> +
> +static int parse_color(char *text, unsigned char yuv_color[3])
> +{
> +  char tmp[3];
> +  unsigned char rgb_color[3];
> +  int i;
> +
> +  tmp[2] = '\0';
> +
> +  if ((!text) || (strlen(text) != 7) || (text[0] != '#') )
> +    return -1;
> +
> +  for (i=0; i < 3; i++)
> +    {
> +      tmp[0] = text[i*2+1];
> +      tmp[1] = text[i*2+2];
> +
> +      rgb_color[i] = strtol(tmp, NULL, 16);
> +    }
> +
> +  RGB_TO_YUV(rgb_color, yuv_color);
> +
> +  return 0;
> +}

av_parse_color()

> +static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
> +{
> +    int err, chars_read, num_opt = 0;
> +    char str[256], cmd[2];
> +    const char *args_cur;
> +    char *font = NULL;
> +    int c;
> +    unsigned int size=DEF_DRAWTEXT_FONT_SZ;
> +    FT_BBox bbox;
> +    int yMax, yMin;

General stylistic note: use K&R style,
if (cond) {
  ...
}
style is preferred, plain_variable is preferred over camelVariable
style, try also the patcheck tool for checking the most common trivial
errors.

> +    DtextContext *dtext = ctx->priv;
> +
> +    dtext->fgcolor[0]=255;
> +    dtext->fgcolor[1]=128;
> +    dtext->fgcolor[2]=128;
> +    dtext->bgcolor[0]=0;
> +    dtext->fgcolor[1]=128;
> +    dtext->fgcolor[2]=128;
> +    dtext->bg = 0;
> +    dtext->outline = 0;
> +    dtext->text_height = 0;
> +
> +    optind = 1;
> +
> +    if ((err = FT_Init_FreeType(&(dtext->library))) != 0)
> +    {
> +        av_log(NULL, AV_LOG_ERROR, "Could not load FreeType (error# %d).\n", err);

Use the filter context for logging.

> +        return -1;

I'd like to start to use meaningful error codes in libavfilter, use
AVERROR(EINVAL) in this case.

> +    }
>
> +    args_cur = args;
> +    if(args_cur) {
> +        while (2 == sscanf(args_cur, "%1[FtfxyiRGBA]:%255[^:]%n", cmd, str, &chars_read))
> +        {
> +            if (num_opt>=MAX_DRAWTEXT_OPT) {
> +                av_log(NULL, AV_LOG_ERROR, 
> +                    "drawtext init() cannot handle more than %d arguments\n",
> +                    MAX_DRAWTEXT_OPT);
> +                return -1;
> +            }
> +            switch(cmd[0]) {
> +            case 'f':
> +                font = av_strdup(str);
> +                break;
> +            case 't':
> +                dtext->text = av_strdup(str);
> +                break;
> +            case 'T':
> +                dtext->file = av_strdup(str);
> +                break;
> +            case 'x':
> +                dtext->x = (unsigned int)atoi(str);
> +                break;
> +            case 'y':
> +                dtext->y = (unsigned int)atoi(str);
> +                break;
> +            case 's':
> +                size = (unsigned int)atoi(str);
> +                break;
> +            case 'c':
> +                if (parse_color(optarg, dtext->fgcolor) == -1)
> +                {
> +                    av_log(NULL, AV_LOG_ERROR, "Invalid foreground color: '%s'.\n", optarg);
> +                    return -1;
> +                }
> +                break;
> +            case 'C':
> +                if (parse_color(optarg, dtext->bgcolor) == -1)
> +                {
> +                    av_log(NULL, AV_LOG_ERROR, "Invalid background color: '%s'.\n", optarg);
> +                    return -1;
> +                }
> +                break;
> +            case 'b':
> +                dtext->bg = 1;
> +                break;
> +            case 'o':
> +                dtext->bg = 1;
> +                break;
> +            case '?':
> +                av_log(NULL, AV_LOG_ERROR, "Unrecognized argument '%c:%s'\n", cmd[0], str);
> +                return -1;
> +            }
> +            num_opt++;
> +            args_cur += chars_read;
> +            if (*args_cur==':')
> +                args_cur++;
> +        }
> +    }

All this can be greatly simplified and made more robust using
parseutils.c.

[...]
> +AVFilter avfilter_vf_drawtext = {
> +    .name      = "drawtext",

missing long name.

Regards.


More information about the FFmpeg-soc mailing list