Merge commit '3fb29588a27a711132106b924e27b53789a58dcb'
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 17 May 2013 09:28:15 +0000 (11:28 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 17 May 2013 09:29:22 +0000 (11:29 +0200)
* commit '3fb29588a27a711132106b924e27b53789a58dcb':
  vf_drawtext: don't leak the expressions.
  vf_crop: make config_props work properly when called multiple times.
  vf_setdar: make config_props work properly when called multiple times.

Conflicts:
libavfilter/vf_aspect.c
libavfilter/vf_drawtext.c

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

  
  typedef struct {
      const AVClass *class;
-     AVRational aspect;
+     AVRational dar;
+     AVRational sar;
 +    int max;
  #if FF_API_OLD_FILTER_OPTS
 -    float aspect_num, aspect_den;
 +    float aspect_den;
  #endif
 +    char *ratio_str;
  } AspectContext;
  
 -#if FF_API_OLD_FILTER_OPTS
  static av_cold int init(AVFilterContext *ctx)
  {
      AspectContext *s = ctx->priv;
 +    int ret;
  
 -    if (s->aspect_num > 0 && s->aspect_den > 0) {
 -        av_log(ctx, AV_LOG_WARNING, "This syntax is deprecated, use "
 -               "dar=<number> or dar=num/den.\n");
 -        s->sar = s->dar = av_d2q(s->aspect_num / s->aspect_den, INT_MAX);
 +#if FF_API_OLD_FILTER_OPTS
 +    if (s->ratio_str && s->aspect_den > 0) {
 +        double num;
 +        av_log(ctx, AV_LOG_WARNING,
 +               "num:den syntax is deprecated, please use num/den or named options instead\n");
 +        ret = av_expr_parse_and_eval(&num, s->ratio_str, NULL, NULL,
 +                                     NULL, NULL, NULL, NULL, NULL, 0, ctx);
 +        if (ret < 0) {
 +            av_log(ctx, AV_LOG_ERROR, "Unable to parse ratio numerator \"%s\"\n", s->ratio_str);
 +            return AVERROR(EINVAL);
 +        }
-         s->aspect = av_d2q(num / s->aspect_den, s->max);
++        s->sar = s->dar = av_d2q(num / s->aspect_den, s->max);
 +    } else
 +#endif
 +    if (s->ratio_str) {
-         ret = av_parse_ratio(&s->aspect, s->ratio_str, s->max, 0, ctx);
-         if (ret < 0 || s->aspect.num < 0 || s->aspect.den <= 0) {
++        ret = av_parse_ratio(&s->sar, s->ratio_str, s->max, 0, ctx);
++        if (ret < 0 || s->sar.num < 0 || s->sar.den <= 0) {
 +            av_log(ctx, AV_LOG_ERROR,
 +                   "Invalid string '%s' for aspect ratio\n", s->ratio_str);
 +            return AVERROR(EINVAL);
 +        }
++        s->dar = s->sar;
      }
 -
      return 0;
  }
 -#endif
  
  static int filter_frame(AVFilterLink *link, AVFrame *frame)
  {
@@@ -100,14 -73,14 +102,16 @@@ static inline void compute_dar(AVRation
  static int setdar_config_props(AVFilterLink *inlink)
  {
      AspectContext *s = inlink->dst->priv;
-     AVRational dar = s->aspect, old_dar;
+     AVRational dar;
++    AVRational old_dar;
 +    AVRational old_sar = inlink->sample_aspect_ratio;
  
-     if (s->aspect.num && s->aspect.den) {
-         av_reduce(&s->aspect.num, &s->aspect.den,
-                    s->aspect.num * inlink->h,
-                    s->aspect.den * inlink->w, INT_MAX);
-         inlink->sample_aspect_ratio = s->aspect;
+     if (s->dar.num && s->dar.den) {
+         av_reduce(&s->sar.num, &s->sar.den,
+                    s->dar.num * inlink->h,
 -                   s->dar.den * inlink->w, 100);
++                   s->dar.den * inlink->w, INT_MAX);
+         inlink->sample_aspect_ratio = s->sar;
+         dar = s->dar;
      } else {
          inlink->sample_aspect_ratio = (AVRational){ 1, 1 };
          dar = (AVRational){ inlink->w, inlink->h };
@@@ -172,17 -150,9 +176,17 @@@ AVFilter avfilter_vf_setdar = 
  static int setsar_config_props(AVFilterLink *inlink)
  {
      AspectContext *s = inlink->dst->priv;
 +    AVRational old_sar = inlink->sample_aspect_ratio;
 +    AVRational old_dar, dar;
  
-     inlink->sample_aspect_ratio = s->aspect;
+     inlink->sample_aspect_ratio = s->sar;
  
-     compute_dar(&dar, s->aspect, inlink->w, inlink->h);
 +    compute_dar(&old_dar, old_sar, inlink->w, inlink->h);
++    compute_dar(&dar, s->sar, inlink->w, inlink->h);
 +    av_log(inlink->dst, AV_LOG_VERBOSE, "w:%d h:%d sar:%d/%d dar:%d/%d -> sar:%d/%d dar:%d/%d\n",
 +           inlink->w, inlink->h, old_sar.num, old_sar.den, old_dar.num, old_dar.den,
 +           inlink->sample_aspect_ratio.num, inlink->sample_aspect_ratio.den, dar.num, dar.den);
 +
      return 0;
  }
  
Simple merge
@@@ -533,19 -400,17 +533,19 @@@ static int glyph_enu_free(void *opaque
  static av_cold void uninit(AVFilterContext *ctx)
  {
      DrawTextContext *s = ctx->priv;
 -    int i;
  
-     av_expr_free(s->x_pexpr); s->x_pexpr = NULL;
-     av_expr_free(s->y_pexpr); s->y_pexpr = NULL;
-     av_expr_free(s->draw_pexpr); s->draw_pexpr = NULL;
+     av_expr_free(s->x_pexpr);
+     av_expr_free(s->y_pexpr);
 -    av_expr_free(s->d_pexpr);
 -    s->x_pexpr = s->y_pexpr = s->d_pexpr = NULL;
 -    av_freep(&s->expanded_text);
++    av_expr_free(s->draw_pexpr);
++    s->x_pexpr = s->y_pexpr = s->draw_pexpr = NULL;
      av_freep(&s->positions);
 +    s->nb_positions = 0;
 +
 +
      av_tree_enumerate(s->glyphs, NULL, NULL, glyph_enu_free);
      av_tree_destroy(s->glyphs);
 -    s->glyphs = 0;
 +    s->glyphs = NULL;
 +
      FT_Done_Face(s->face);
      FT_Done_FreeType(s->library);
  
@@@ -557,104 -426,128 +557,108 @@@ 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;
 +    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
++    av_expr_free(s->x_pexpr);
++    av_expr_free(s->y_pexpr);
++    av_expr_free(s->draw_pexpr);
++    s->x_pexpr = s->y_pexpr = s->draw_pexpr = NULL;
 +    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;
  }