Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Tue, 7 Feb 2012 00:40:29 +0000 (01:40 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Tue, 7 Feb 2012 00:40:29 +0000 (01:40 +0100)
* qatar/master:
  Revert "v210enc: use FFALIGN()"
  doxygen: Do not include license boilerplates in Doxygen comment blocks.
  avplay: reset decoder flush state when seeking
  ape: skip packets with invalid size
  ape: calculate final packet size instead of guessing
  ape: stop reading after the last frame has been read
  ape: return AVERROR_EOF instead of AVERROR(EIO) when demuxing is finished
  ape: return error if seeking to the current packet fails in ape_read_packet()
  avcodec: Clarify AVFrame member documentation.
  v210dec: check for coded_frame allocation failure
  v210enc: use stride as it is already calculated
  v210enc: use FFALIGN()
  v210enc: return proper AVERROR codes instead of -1
  v210enc: do not set coded_frame->key_frame
  v210enc: check for coded_frame allocation failure
  drawtext: add 'fix_bounds' option on coords fixing
  drawtext: fix text_{w, h} expression vars
  drawtext: add missing braces around an if() block.

Conflicts:
libavcodec/arm/vp8.h
libavcodec/arm/vp8dsp_init_arm.c
libavcodec/v210dec.c
libavfilter/vf_drawtext.c
libavformat/ape.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
20 files changed:
1  2 
doc/filters.texi
ffplay.c
libavcodec/alacenc.c
libavcodec/arm/vp8.h
libavcodec/arm/vp8_armv6.S
libavcodec/arm/vp8dsp_init_arm.c
libavcodec/arm/vp8dsp_neon.S
libavcodec/avcodec.h
libavcodec/flacenc.c
libavcodec/lpc.c
libavcodec/lpc.h
libavcodec/ppc/vp8dsp_altivec.c
libavcodec/v210enc.c
libavcodec/vp8.c
libavcodec/vp8.h
libavfilter/vf_drawtext.c
libavformat/ape.c
libavformat/rtpdec_latm.c
libavformat/rtpdec_mpeg4.c
libavformat/rtpdec_qcelp.c

@@@ -1256,79 -598,12 +1256,82 @@@ libfreetype flags
  @item tabsize
  The size in number of spaces to use for rendering the tab.
  Default value is 4.
+ @item fix_bounds
+ If true, check and fix text coords to avoid clipping.
  @end table
  
 -For example the command:
 +The parameters for @var{x} and @var{y} are expressions containing the
 +following constants:
 +
 +@table @option
 +@item W, H
 +the input width and height
 +
 +@item tw, text_w
 +the width of the rendered text
 +
 +@item th, text_h
 +the height of the rendered text
 +
 +@item lh, line_h
 +the height of each text line
 +
 +@item sar
 +input sample aspect ratio
 +
 +@item dar
 +input display aspect ratio, it is the same as (@var{w} / @var{h}) * @var{sar}
 +
 +@item hsub, vsub
 +horizontal and vertical chroma subsample values. For example for the
 +pixel format "yuv422p" @var{hsub} is 2 and @var{vsub} is 1.
 +
 +@item max_glyph_w
 +maximum glyph width, that is the maximum width for all the glyphs
 +contained in the rendered text
 +
 +@item max_glyph_h
 +maximum glyph height, that is the maximum height for all the glyphs
 +contained in the rendered text, it is equivalent to @var{ascent} -
 +@var{descent}.
 +
 +@item max_glyph_a, ascent
 +
 +the maximum distance from the baseline to the highest/upper grid
 +coordinate used to place a glyph outline point, for all the rendered
 +glyphs.
 +It is a positive value, due to the grid's orientation with the Y axis
 +upwards.
 +
 +@item max_glyph_d, descent
 +the maximum distance from the baseline to the lowest grid coordinate
 +used to place a glyph outline point, for all the rendered glyphs.
 +This is a negative value, due to the grid's orientation, with the Y axis
 +upwards.
 +
 +@item n
 +the number of input frame, starting from 0
 +
 +@item t
 +timestamp expressed in seconds, NAN if the input timestamp is unknown
 +
 +@item timecode
 +initial timecode representation in "hh:mm:ss[:;.]ff" format. It can be used
 +with or without text parameter. @var{rate} option must be specified.
 +
 +@item r, rate
 +frame rate (timecode only)
 +@end table
 +
 +Some examples follow.
 +
 +@itemize
 +
 +@item
 +Draw "Test Text" with font FreeSerif, using the default values for the
 +optional parameters.
 +
  @example
  drawtext="fontfile=/usr/share/fonts/truetype/freefont/FreeSerif.ttf: text='Test Text'"
  @end example
diff --cc ffplay.c
Simple merge
Simple merge
@@@ -1,7 -1,7 +1,7 @@@
- /**
+ /*
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
@@@ -1,9 -1,9 +1,9 @@@
- /**
+ /*
   * Copyright (C) 2010 Mans Rullgard
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
@@@ -1,7 -1,7 +1,7 @@@
- /**
+ /*
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -179,11 -157,9 +180,13 @@@ static const AVOption drawtext_options[
  {"shadowx",  "set x",                OFFSET(shadowx),            AV_OPT_TYPE_INT,    {.dbl=0},     INT_MIN,  INT_MAX  },
  {"shadowy",  "set y",                OFFSET(shadowy),            AV_OPT_TYPE_INT,    {.dbl=0},     INT_MIN,  INT_MAX  },
  {"tabsize",  "set tab size",         OFFSET(tabsize),            AV_OPT_TYPE_INT,    {.dbl=4},     0,        INT_MAX  },
 +{"basetime", "set base time",        OFFSET(basetime),           AV_OPT_TYPE_INT64,  {.dbl=AV_NOPTS_VALUE},     INT64_MIN,        INT64_MAX  },
  {"draw",     "if false do not draw", OFFSET(d_expr),             AV_OPT_TYPE_STRING, {.str="1"},   CHAR_MIN, CHAR_MAX },
 +{"timecode", "set initial timecode", OFFSET(tc_opt_string),      AV_OPT_TYPE_STRING, {.str=NULL},  CHAR_MIN, CHAR_MAX },
 +{"r",        "set rate (timecode only)", OFFSET(tc_rate),        AV_OPT_TYPE_RATIONAL, {.dbl=0},          0,  INT_MAX },
 +{"rate",     "set rate (timecode only)", OFFSET(tc_rate),        AV_OPT_TYPE_RATIONAL, {.dbl=0},          0,  INT_MAX },
+ {"fix_bounds", "if true, check and fix text coords to avoid clipping",
+                                      OFFSET(fix_bounds),         AV_OPT_TYPE_INT,    {.dbl=1},     0,        1        },
  
  /* FT_LOAD_* flags */
  {"ft_load_flags", "set font loading flags for libfreetype",   OFFSET(ft_load_flags),  AV_OPT_TYPE_FLAGS,  {.dbl=FT_LOAD_DEFAULT|FT_LOAD_RENDER}, 0, INT_MAX, 0, "ft_load_flags" },
@@@ -688,139 -760,86 +691,140 @@@ static int draw_text(AVFilterContext *c
                       int width, int height)
  {
      DrawTextContext *dtext = ctx->priv;
 -    int ret;
 +    uint32_t code = 0, prev_code = 0;
 +    int x = 0, y = 0, i = 0, ret;
 +    int max_text_line_w = 0, len;
 +    int box_w, box_h;
 +    char *text = dtext->text;
 +    uint8_t *p;
 +    int y_min = 32000, y_max = -32000;
 +    int x_min = 32000, x_max = -32000;
 +    FT_Vector delta;
 +    Glyph *glyph = NULL, *prev_glyph = NULL;
 +    Glyph dummy = { 0 };
  
 -    /* draw box */
 -    if (dtext->draw_box)
 -        drawbox(picref, dtext->x, dtext->y, dtext->w, dtext->h,
 -                dtext->box_line, dtext->pixel_step, dtext->boxcolor,
 -                dtext->hsub, dtext->vsub, dtext->is_packed_rgb,
 -                dtext->rgba_map);
 +    time_t now = time(0);
 +    struct tm ltime;
 +    uint8_t *buf = dtext->expanded_text;
 +    int buf_size = dtext->expanded_text_size;
  
 -    if (dtext->shadowx || dtext->shadowy) {
 -        if ((ret = draw_glyphs(dtext, picref, width, height,
 -                               dtext->shadowcolor_rgba,
 -                               dtext->shadowcolor,
 -                               dtext->x + dtext->shadowx,
 -                               dtext->y + dtext->shadowy)) < 0)
 -            return ret;
 +    if(dtext->basetime != AV_NOPTS_VALUE)
 +        now= picref->pts*av_q2d(ctx->inputs[0]->time_base) + dtext->basetime/1000000;
 +
 +    if (!buf) {
 +        buf_size = 2*strlen(dtext->text)+1;
 +        buf = av_malloc(buf_size);
      }
  
 -    if ((ret = draw_glyphs(dtext, picref, width, height,
 -                           dtext->fontcolor_rgba,
 -                           dtext->fontcolor,
 -                           dtext->x,
 -                           dtext->y)) < 0)
 -        return ret;
 +#if HAVE_LOCALTIME_R
 +    localtime_r(&now, &ltime);
 +#else
 +    if(strchr(dtext->text, '%'))
 +        ltime= *localtime(&now);
 +#endif
  
 -    return 0;
 -}
 +    do {
 +        *buf = 1;
 +        if (strftime(buf, buf_size, dtext->text, &ltime) != 0 || *buf == 0)
 +            break;
 +        buf_size *= 2;
 +    } while ((buf = av_realloc(buf, buf_size)));
  
 -static void null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) { }
 +    if (dtext->tc_opt_string) {
 +        char tcbuf[AV_TIMECODE_STR_SIZE];
 +        av_timecode_make_string(&dtext->tc, tcbuf, dtext->frame_id++);
 +        buf = av_asprintf("%s%s", dtext->text, tcbuf);
 +    }
  
 -static inline int normalize_double(int *n, double d)
 -{
 -    int ret = 0;
 +    if (!buf)
 +        return AVERROR(ENOMEM);
 +    text = dtext->expanded_text = buf;
 +    dtext->expanded_text_size = buf_size;
 +    if ((len = strlen(text)) > dtext->nb_positions) {
 +        if (!(dtext->positions =
 +              av_realloc(dtext->positions, len*sizeof(*dtext->positions))))
 +            return AVERROR(ENOMEM);
 +        dtext->nb_positions = len;
 +    }
  
 -    if (isnan(d)) {
 -        ret = AVERROR(EINVAL);
 -    } else if (d > INT_MAX || d < INT_MIN) {
 -        *n = d > INT_MAX ? INT_MAX : INT_MIN;
 -        ret = AVERROR(EINVAL);
 -    } else
 -        *n = round(d);
 +    x = 0;
 +    y = 0;
  
 -    return ret;
 -}
 +    /* load and cache glyphs */
 +    for (i = 0, p = text; *p; i++) {
 +        GET_UTF8(code, *p++, continue;);
  
 -static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
 -{
 -    AVFilterContext *ctx = inlink->dst;
 -    DrawTextContext *dtext = ctx->priv;
 -    int fail = 0;
 +        /* get glyph */
 +        dummy.code = code;
 +        glyph = av_tree_find(dtext->glyphs, &dummy, glyph_cmp, NULL);
-         if (!glyph)
++        if (!glyph) {
 +            load_glyph(ctx, &glyph, code);
++        }
  
 -    if (dtext_prepare_text(ctx) < 0) {
 -        av_log(ctx, AV_LOG_ERROR, "Can't draw text\n");
 -        fail = 1;
 +        y_min = FFMIN(glyph->bbox.yMin, y_min);
 +        y_max = FFMAX(glyph->bbox.yMax, y_max);
 +        x_min = FFMIN(glyph->bbox.xMin, x_min);
 +        x_max = FFMAX(glyph->bbox.xMax, x_max);
      }
 +    dtext->max_glyph_h = y_max - y_min;
 +    dtext->max_glyph_w = x_max - x_min;
 +
 +    /* compute and save position for each glyph */
 +    glyph = NULL;
 +    for (i = 0, p = text; *p; i++) {
 +        GET_UTF8(code, *p++, continue;);
  
 -    dtext->var_values[VAR_T] = inpicref->pts == AV_NOPTS_VALUE ?
 -        NAN : inpicref->pts * av_q2d(inlink->time_base);
 -    dtext->var_values[VAR_X] =
 -        av_expr_eval(dtext->x_pexpr, dtext->var_values, &dtext->prng);
 -    dtext->var_values[VAR_Y] =
 -        av_expr_eval(dtext->y_pexpr, dtext->var_values, &dtext->prng);
 -    dtext->var_values[VAR_X] =
 -        av_expr_eval(dtext->x_pexpr, dtext->var_values, &dtext->prng);
 -
 -    dtext->draw = fail ? 0 :
 -        av_expr_eval(dtext->d_pexpr, dtext->var_values, &dtext->prng);
 -
 -    normalize_double(&dtext->x, dtext->var_values[VAR_X]);
 -    normalize_double(&dtext->y, dtext->var_values[VAR_Y]);
 -
 -    if (dtext->fix_bounds) {
 -        if (dtext->x < 0) dtext->x = 0;
 -        if (dtext->y < 0) dtext->y = 0;
 -        if ((unsigned)dtext->x + (unsigned)dtext->w > inlink->w)
 -            dtext->x = inlink->w - dtext->w;
 -        if ((unsigned)dtext->y + (unsigned)dtext->h > inlink->h)
 -            dtext->y = inlink->h - dtext->h;
 +        /* skip the \n in the sequence \r\n */
 +        if (prev_code == '\r' && code == '\n')
 +            continue;
 +
 +        prev_code = code;
 +        if (is_newline(code)) {
 +            max_text_line_w = FFMAX(max_text_line_w, x);
 +            y += dtext->max_glyph_h;
 +            x = 0;
 +            continue;
 +        }
 +
 +        /* get glyph */
 +        prev_glyph = glyph;
 +        dummy.code = code;
 +        glyph = av_tree_find(dtext->glyphs, &dummy, glyph_cmp, NULL);
 +
 +        /* kerning */
 +        if (dtext->use_kerning && prev_glyph && glyph->code) {
 +            FT_Get_Kerning(dtext->face, prev_glyph->code, glyph->code,
 +                           ft_kerning_default, &delta);
 +            x += delta.x >> 6;
 +        }
 +
 +        /* save position */
 +        dtext->positions[i].x = x + glyph->bitmap_left;
 +        dtext->positions[i].y = y - glyph->bitmap_top + y_max;
 +        if (code == '\t') x  = (x / dtext->tabsize + 1)*dtext->tabsize;
 +        else              x += glyph->advance;
      }
  
 +    max_text_line_w = FFMAX(x, max_text_line_w);
 +
 +    dtext->var_values[VAR_TW] = dtext->var_values[VAR_TEXT_W] = max_text_line_w;
 +    dtext->var_values[VAR_TH] = dtext->var_values[VAR_TEXT_H] = y + dtext->max_glyph_h;
 +
 +    dtext->var_values[VAR_MAX_GLYPH_W] = dtext->max_glyph_w;
 +    dtext->var_values[VAR_MAX_GLYPH_H] = dtext->max_glyph_h;
 +    dtext->var_values[VAR_MAX_GLYPH_A] = dtext->var_values[VAR_ASCENT ] = y_max;
 +    dtext->var_values[VAR_MAX_GLYPH_D] = dtext->var_values[VAR_DESCENT] = y_min;
 +
 +    dtext->var_values[VAR_LINE_H] = dtext->var_values[VAR_LH] = dtext->max_glyph_h;
 +
 +    dtext->x = dtext->var_values[VAR_X] = av_expr_eval(dtext->x_pexpr, dtext->var_values, &dtext->prng);
 +    dtext->y = dtext->var_values[VAR_Y] = av_expr_eval(dtext->y_pexpr, dtext->var_values, &dtext->prng);
 +    dtext->x = dtext->var_values[VAR_X] = av_expr_eval(dtext->x_pexpr, dtext->var_values, &dtext->prng);
 +    dtext->draw = av_expr_eval(dtext->d_pexpr, dtext->var_values, &dtext->prng);
 +
 +    if(!dtext->draw)
 +        return 0;
 +
      dtext->x &= ~((1 << dtext->hsub) - 1);
      dtext->y &= ~((1 << dtext->vsub) - 1);
  
@@@ -356,12 -365,13 +365,13 @@@ static int ape_read_packet(AVFormatCont
      APEContext *ape = s->priv_data;
      uint32_t extra_size = 8;
  
 -    if (s->pb->eof_reached)
 +    if (url_feof(s->pb))
-         return AVERROR(EIO);
-     if (ape->currentframe > ape->totalframes)
-         return AVERROR(EIO);
+         return AVERROR_EOF;
+     if (ape->currentframe >= ape->totalframes)
+         return AVERROR_EOF;
  
-     avio_seek (s->pb, ape->frames[ape->currentframe].pos, SEEK_SET);
+     if (avio_seek(s->pb, ape->frames[ape->currentframe].pos, SEEK_SET) < 0)
+         return AVERROR(EIO);
  
      /* Calculate how many blocks there are in this frame */
      if (ape->currentframe == (ape->totalframes - 1))
Simple merge
Simple merge
Simple merge