Merge commit '4c205f42c86ccefa093c59434669af34ad14a52b'
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 17 May 2013 09:05:18 +0000 (11:05 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 17 May 2013 09:05:18 +0000 (11:05 +0200)
* commit '4c205f42c86ccefa093c59434669af34ad14a52b':
  vf_drawbox: make config_props work properly when called multiple times.
  vf_drawtext: do not reset the frame number in config_input.
  vf_fps: move initializing pts from config_props to init.

Conflicts:
libavfilter/vf_drawbox.c
libavfilter/vf_drawtext.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavfilter/vf_drawbox.c
libavfilter/vf_drawtext.c
libavfilter/vf_fps.c

@@@ -39,10 -38,9 +39,11 @@@ enum { Y, U, V, A }
  
  typedef struct {
      const AVClass *class;
-     int x, y, w, h, thickness;
+     int x, y, w_opt, h_opt, w, h;
++    int thickness;
      char *color_str;
      unsigned char yuv_color[4];
 +    int invert_color; ///< invert luma color
      int vsub, hsub;   ///< chroma subsampling
  } DrawBoxContext;
  
@@@ -88,11 -82,11 +89,11 @@@ static int config_input(AVFilterLink *i
      s->hsub = desc->log2_chroma_w;
      s->vsub = desc->log2_chroma_h;
  
-     if (s->w == 0) s->w = inlink->w;
-     if (s->h == 0) s->h = inlink->h;
+     s->w = (s->w_opt > 0) ? s->w_opt : inlink->w;
+     s->h = (s->h_opt > 0) ? s->h_opt : inlink->h;
  
      av_log(inlink->dst, AV_LOG_VERBOSE, "x:%d y:%d w:%d h:%d color:0x%02X%02X%02X%02X\n",
 -           s->w, s->y, s->w, s->h,
 +           s->x, s->y, s->w, s->h,
             s->yuv_color[Y], s->yuv_color[U], s->yuv_color[V], s->yuv_color[A]);
  
      return 0;
@@@ -134,27 -121,24 +135,27 @@@ static int filter_frame(AVFilterLink *i
  }
  
  #define OFFSET(x) offsetof(DrawBoxContext, x)
 -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM
 -static const AVOption options[] = {
 -    { "x",      "Horizontal position of the left box edge", OFFSET(x),         AV_OPT_TYPE_INT,    { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS },
 -    { "y",      "Vertical position of the top box edge",    OFFSET(y),         AV_OPT_TYPE_INT,    { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS },
 -    { "width",  "Width of the box",                         OFFSET(w_opt),     AV_OPT_TYPE_INT,    { .i64 = 0 }, 0,       INT_MAX, FLAGS },
 -    { "height", "Height of the box",                        OFFSET(h_opt),     AV_OPT_TYPE_INT,    { .i64 = 0 }, 0,       INT_MAX, FLAGS },
 -    { "color",  "Color of the box",                         OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" },    .flags = FLAGS },
 -    { NULL },
 -};
 +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
 +
 +#if CONFIG_DRAWBOX_FILTER
  
 -static const AVClass drawbox_class = {
 -    .class_name = "drawbox",
 -    .item_name  = av_default_item_name,
 -    .option     = options,
 -    .version    = LIBAVUTIL_VERSION_INT,
 +static const AVOption drawbox_options[] = {
 +    { "x",         "set horizontal position of the left box edge", OFFSET(x),         AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS },
 +    { "y",         "set vertical position of the top box edge",    OFFSET(y),         AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS },
-     { "width",     "set width of the box",                         OFFSET(w),         AV_OPT_TYPE_INT, { .i64 = 0 }, 0,       INT_MAX, FLAGS },
-     { "w",         "set width of the box",                         OFFSET(w),         AV_OPT_TYPE_INT, { .i64 = 0 }, 0,       INT_MAX, FLAGS },
-     { "height",    "set height of the box",                        OFFSET(h),         AV_OPT_TYPE_INT, { .i64 = 0 }, 0,       INT_MAX, FLAGS },
-     { "h",         "set height of the box",                        OFFSET(h),         AV_OPT_TYPE_INT, { .i64 = 0 }, 0,       INT_MAX, FLAGS },
++    { "width",     "set width of the box",                         OFFSET(w_opt),     AV_OPT_TYPE_INT, { .i64 = 0 }, 0,       INT_MAX, FLAGS },
++    { "w",         "set width of the box",                         OFFSET(w_opt),     AV_OPT_TYPE_INT, { .i64 = 0 }, 0,       INT_MAX, FLAGS },
++    { "height",    "set height of the box",                        OFFSET(h_opt),     AV_OPT_TYPE_INT, { .i64 = 0 }, 0,       INT_MAX, FLAGS },
++    { "h",         "set height of the box",                        OFFSET(h_opt),     AV_OPT_TYPE_INT, { .i64 = 0 }, 0,       INT_MAX, FLAGS },
 +    { "color",     "set color of the box",                         OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS },
 +    { "c",         "set color of the box",                         OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS },
 +    { "thickness", "set the box maximum thickness",                OFFSET(thickness), AV_OPT_TYPE_INT, {.i64=4}, 0, INT_MAX, FLAGS },
 +    { "t",         "set the box maximum thickness",                OFFSET(thickness), AV_OPT_TYPE_INT, {.i64=4}, 0, INT_MAX, FLAGS },
 +    { NULL }
  };
  
 -static const AVFilterPad avfilter_vf_drawbox_inputs[] = {
 +AVFILTER_DEFINE_CLASS(drawbox);
 +
 +static const AVFilterPad drawbox_inputs[] = {
      {
          .name             = "default",
          .type             = AVMEDIA_TYPE_VIDEO,
@@@ -557,106 -422,128 +557,104 @@@ static inline int is_newline(uint32_t c
      return c == '\n' || c == '\r' || c == '\f' || c == '\v';
  }
  
 -static int dtext_prepare_text(AVFilterContext *ctx)
 +static int config_input(AVFilterLink *inlink)
  {
 +    AVFilterContext *ctx = inlink->dst;
      DrawTextContext *s = ctx->priv;
 -    uint32_t code = 0, prev_code = 0;
 -    int x = 0, y = 0, i = 0, ret;
 -    int text_height, baseline;
 -    char *text = s->text;
 -    uint8_t *p;
 -    int str_w = 0, len;
 -    int y_min = 32000, y_max = -32000;
 -    FT_Vector delta;
 -    Glyph *glyph = NULL, *prev_glyph = NULL;
 -    Glyph dummy = { 0 };
 -    int width  = ctx->inputs[0]->w;
 -    int height = ctx->inputs[0]->h;
 -
 -#if HAVE_LOCALTIME_R
 -    time_t now = time(0);
 -    struct tm ltime;
 -    uint8_t *buf = s->expanded_text;
 -    int buf_size = s->expanded_text_size;
 -
 -    if (!buf)
 -        buf_size = 2*strlen(s->text)+1;
 +    int ret;
  
 -    localtime_r(&now, &ltime);
 +    ff_draw_init(&s->dc, inlink->format, 0);
 +    ff_draw_color(&s->dc, &s->fontcolor,   s->fontcolor.rgba);
 +    ff_draw_color(&s->dc, &s->shadowcolor, s->shadowcolor.rgba);
 +    ff_draw_color(&s->dc, &s->boxcolor,    s->boxcolor.rgba);
 +
 +    s->var_values[VAR_w]     = s->var_values[VAR_W]     = s->var_values[VAR_MAIN_W] = inlink->w;
 +    s->var_values[VAR_h]     = s->var_values[VAR_H]     = s->var_values[VAR_MAIN_H] = inlink->h;
 +    s->var_values[VAR_SAR]   = inlink->sample_aspect_ratio.num ? av_q2d(inlink->sample_aspect_ratio) : 1;
 +    s->var_values[VAR_DAR]   = (double)inlink->w / inlink->h * s->var_values[VAR_SAR];
 +    s->var_values[VAR_HSUB]  = 1 << s->dc.hsub_max;
 +    s->var_values[VAR_VSUB]  = 1 << s->dc.vsub_max;
 +    s->var_values[VAR_X]     = NAN;
 +    s->var_values[VAR_Y]     = NAN;
-     if (!s->reinit)
-         s->var_values[VAR_N] = 0;
 +    s->var_values[VAR_T]     = NAN;
  
 -    while ((buf = av_realloc(buf, buf_size))) {
 -        *buf = 1;
 -        if (strftime(buf, buf_size, s->text, &ltime) != 0 || *buf == 0)
 -            break;
 -        buf_size *= 2;
 -    }
 +    av_lfg_init(&s->prng, av_get_random_seed());
  
 -    if (!buf)
 -        return AVERROR(ENOMEM);
 -    text = s->expanded_text = buf;
 -    s->expanded_text_size = buf_size;
 -#endif
 +    if ((ret = av_expr_parse(&s->x_pexpr, s->x_expr, var_names,
 +                             NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 ||
 +        (ret = av_expr_parse(&s->y_pexpr, s->y_expr, var_names,
 +                             NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 ||
 +        (ret = av_expr_parse(&s->draw_pexpr, s->draw_expr, var_names,
 +                             NULL, NULL, fun2_names, fun2, 0, ctx)) < 0)
  
 -    if ((len = strlen(text)) > s->nb_positions) {
 -        FT_Vector *p = av_realloc(s->positions,
 -                                  len * sizeof(*s->positions));
 -        if (!p) {
 -            av_freep(s->positions);
 -            s->nb_positions = 0;
 -            return AVERROR(ENOMEM);
 -        } else {
 -            s->positions = p;
 -            s->nb_positions = len;
 -        }
 -    }
 +        return AVERROR(EINVAL);
  
 -    /* load and cache glyphs */
 -    for (i = 0, p = text; *p; i++) {
 -        GET_UTF8(code, *p++, continue;);
 +    return 0;
 +}
  
 -        /* get glyph */
 -        dummy.code = code;
 -        glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL);
 -        if (!glyph) {
 -            ret = load_glyph(ctx, &glyph, code);
 -            if (ret)
 -                return ret;
 -        }
 +static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
 +{
 +    DrawTextContext *s = ctx->priv;
  
 -        y_min = FFMIN(glyph->bbox.yMin, y_min);
 -        y_max = FFMAX(glyph->bbox.yMax, y_max);
 +    if (!strcmp(cmd, "reinit")) {
 +        int ret;
 +        uninit(ctx);
 +        s->reinit = 1;
 +        if ((ret = init(ctx)) < 0)
 +            return ret;
 +        return config_input(ctx->inputs[0]);
      }
 -    text_height = y_max - y_min;
 -    baseline    = y_max;
  
 -    /* compute and save position for each glyph */
 -    glyph = NULL;
 -    for (i = 0, p = text; *p; i++) {
 -        GET_UTF8(code, *p++, continue;);
 -
 -        /* skip the \n in the sequence \r\n */
 -        if (prev_code == '\r' && code == '\n')
 -            continue;
 +    return AVERROR(ENOSYS);
 +}
  
 -        prev_code = code;
 -        if (is_newline(code)) {
 -            str_w = FFMAX(str_w, x - s->x);
 -            y += text_height;
 -            x = 0;
 -            continue;
 -        }
 +static int func_pict_type(AVFilterContext *ctx, AVBPrint *bp,
 +                          char *fct, unsigned argc, char **argv, int tag)
 +{
 +    DrawTextContext *s = ctx->priv;
  
 -        /* get glyph */
 -        prev_glyph = glyph;
 -        dummy.code = code;
 -        glyph = av_tree_find(s->glyphs, &dummy, glyph_cmp, NULL);
 +    av_bprintf(bp, "%c", av_get_picture_type_char(s->var_values[VAR_PICT_TYPE]));
 +    return 0;
 +}
  
 -        /* kerning */
 -        if (s->use_kerning && prev_glyph && glyph->code) {
 -            FT_Get_Kerning(s->face, prev_glyph->code, glyph->code,
 -                           ft_kerning_default, &delta);
 -            x += delta.x >> 6;
 -        }
 +static int func_pts(AVFilterContext *ctx, AVBPrint *bp,
 +                    char *fct, unsigned argc, char **argv, int tag)
 +{
 +    DrawTextContext *s = ctx->priv;
  
 -        if (x + glyph->bbox.xMax >= width) {
 -            str_w = FFMAX(str_w, x);
 -            y += text_height;
 -            x = 0;
 -        }
 +    av_bprintf(bp, "%.6f", s->var_values[VAR_T]);
 +    return 0;
 +}
  
 -        /* save position */
 -        s->positions[i].x = x + glyph->bitmap_left;
 -        s->positions[i].y = y - glyph->bitmap_top + baseline;
 -        if (code == '\t') x  = (x / s->tabsize + 1)*s->tabsize;
 -        else              x += glyph->advance;
 -    }
 +static int func_frame_num(AVFilterContext *ctx, AVBPrint *bp,
 +                          char *fct, unsigned argc, char **argv, int tag)
 +{
 +    DrawTextContext *s = ctx->priv;
  
 -    str_w = FFMIN(width - 1, FFMAX(str_w, x));
 -    y     = FFMIN(y + text_height, height - 1);
 +    av_bprintf(bp, "%d", (int)s->var_values[VAR_N]);
 +    return 0;
 +}
  
 -    s->w = str_w;
 -    s->var_values[VAR_TEXT_W] = s->var_values[VAR_TW] = s->w;
 -    s->h = y;
 -    s->var_values[VAR_TEXT_H] = s->var_values[VAR_TH] = s->h;
 +#if !HAVE_LOCALTIME_R
 +static void localtime_r(const time_t *t, struct tm *tm)
 +{
 +    *tm = *localtime(t);
 +}
 +#endif
  
 +static int func_strftime(AVFilterContext *ctx, AVBPrint *bp,
 +                         char *fct, unsigned argc, char **argv, int tag)
 +{
 +    const char *fmt = argc ? argv[0] : "%Y-%m-%d %H:%M:%S";
 +    time_t now;
 +    struct tm tm;
 +
 +    time(&now);
 +    if (tag == 'L')
 +        localtime_r(&now, &tm);
 +    else
 +        tm = *gmtime(&now);
 +    av_bprint_strftime(bp, fmt, &tm);
      return 0;
  }
  
@@@ -107,11 -109,9 +109,10 @@@ static int config_props(AVFilterLink* l
  {
      FPSContext   *s = link->src->priv;
  
 -    link->time_base = (AVRational){ s->framerate.den, s->framerate.num };
 +    link->time_base = av_inv_q(s->framerate);
 +    link->frame_rate= s->framerate;
      link->w         = link->src->inputs[0]->w;
      link->h         = link->src->inputs[0]->h;
-     s->pts          = AV_NOPTS_VALUE;
  
      return 0;
  }