summaryrefslogtreecommitdiff
path: root/libavfilter/vf_drawtext.c
diff options
context:
space:
mode:
authorLuca Barbato <lu_zero@gentoo.org>2011-12-01 11:27:19 +0100
committerLuca Barbato <lu_zero@gentoo.org>2011-12-03 01:35:28 +0100
commitec11ff8407eadc65f4225f83e778c504c00ce037 (patch)
tree93d6c50503646a001819162a3dda970dabc06822 /libavfilter/vf_drawtext.c
parenta2fb4bcb0189f6421608e0dec1a38c65910763f6 (diff)
drawtext: manage memory allocation better
Call dtext_prepare_text as early as possible Do not draw if the memory allocation failed
Diffstat (limited to 'libavfilter/vf_drawtext.c')
-rw-r--r--libavfilter/vf_drawtext.c264
1 files changed, 132 insertions, 132 deletions
diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c
index 3d6b7b0486..06b5dc0ba1 100644
--- a/libavfilter/vf_drawtext.c
+++ b/libavfilter/vf_drawtext.c
@@ -369,9 +369,135 @@ static av_cold void uninit(AVFilterContext *ctx)
}
+static inline int is_newline(uint32_t c)
+{
+ return (c == '\n' || c == '\r' || c == '\f' || c == '\v');
+}
+
+static int dtext_prepare_text(AVFilterContext *ctx, int width, int height)
+{
+ DrawTextContext *dtext = ctx->priv;
+ uint32_t code = 0, prev_code = 0;
+ int x = 0, y = 0, i = 0, ret;
+ int text_height, baseline;
+ char *text = dtext->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 };
+
+#if HAVE_LOCALTIME_R
+ time_t now = time(0);
+ struct tm ltime;
+ uint8_t *buf = dtext->expanded_text;
+ int buf_size = dtext->expanded_text_size;
+
+ if (!buf)
+ buf_size = 2*strlen(dtext->text)+1;
+
+ localtime_r(&now, &ltime);
+
+ while ((buf = av_realloc(buf, buf_size))) {
+ *buf = 1;
+ if (strftime(buf, buf_size, dtext->text, &ltime) != 0 || *buf == 0)
+ break;
+ buf_size *= 2;
+ }
+
+ if (!buf)
+ return AVERROR(ENOMEM);
+ text = dtext->expanded_text = buf;
+ dtext->expanded_text_size = buf_size;
+#endif
+
+ if ((len = strlen(text)) > dtext->nb_positions) {
+ FT_Vector *p = av_realloc(dtext->positions,
+ len * sizeof(*dtext->positions));
+ if (!p) {
+ av_freep(dtext->positions);
+ dtext->nb_positions = 0;
+ return AVERROR(ENOMEM);
+ } else {
+ dtext->positions = p;
+ dtext->nb_positions = len;
+ }
+ }
+
+ /* load and cache glyphs */
+ for (i = 0, p = text; *p; i++) {
+ GET_UTF8(code, *p++, continue;);
+
+ /* get glyph */
+ dummy.code = code;
+ glyph = av_tree_find(dtext->glyphs, &dummy, glyph_cmp, NULL);
+ if (!glyph)
+ ret = load_glyph(ctx, &glyph, code);
+ if (ret) return ret;
+
+ y_min = FFMIN(glyph->bbox.yMin, y_min);
+ y_max = FFMAX(glyph->bbox.yMax, y_max);
+ }
+ 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;
+
+ prev_code = code;
+ if (is_newline(code)) {
+ str_w = FFMAX(str_w, x - dtext->x);
+ y += text_height;
+ 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;
+ }
+
+ if (x + glyph->bbox.xMax >= width) {
+ str_w = FFMAX(str_w, x);
+ y += text_height;
+ x = 0;
+ }
+
+ /* save position */
+ dtext->positions[i].x = x + glyph->bitmap_left;
+ dtext->positions[i].y = y - glyph->bitmap_top + baseline;
+ if (code == '\t') x = (x / dtext->tabsize + 1)*dtext->tabsize;
+ else x += glyph->advance;
+ }
+
+ str_w = FFMIN(width - 1, FFMAX(str_w, x));
+ y = FFMIN(y + text_height, height - 1);
+
+ dtext->w = str_w;
+ dtext->h = y;
+
+ return 0;
+}
+
+
static int config_input(AVFilterLink *inlink)
{
- DrawTextContext *dtext = inlink->dst->priv;
+ AVFilterContext *ctx = inlink->dst;
+ DrawTextContext *dtext = ctx->priv;
const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[inlink->format];
int ret;
@@ -398,7 +524,7 @@ static int config_input(AVFilterLink *inlink)
dtext->shadowcolor[3] = rgba[3];
}
- return 0;
+ return dtext_prepare_text(ctx, ctx->inputs[0]->w, ctx->inputs[0]->h);
}
#define GET_BITMAP_VAL(r, c) \
@@ -499,11 +625,6 @@ static inline void drawbox(AVFilterBufferRef *picref, unsigned int x, unsigned i
}
}
-static inline int is_newline(uint32_t c)
-{
- return (c == '\n' || c == '\r' || c == '\f' || c == '\v');
-}
-
static int draw_glyphs(DrawTextContext *dtext, AVFilterBufferRef *picref,
int width, int height, const uint8_t rgbcolor[4], const uint8_t yuvcolor[4], int x, int y)
{
@@ -542,128 +663,6 @@ static int draw_glyphs(DrawTextContext *dtext, AVFilterBufferRef *picref,
return 0;
}
-static int dtext_prepare_text(AVFilterContext *ctx, int width, int height)
-{
- DrawTextContext *dtext = ctx->priv;
- uint32_t code = 0, prev_code = 0;
- int x = 0, y = 0, i = 0, ret;
- int text_height, baseline;
- char *text = dtext->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 };
-
-#if HAVE_LOCALTIME_R
- time_t now = time(0);
- struct tm ltime;
- uint8_t *buf = dtext->expanded_text;
- int buf_size = dtext->expanded_text_size;
-
- if (!buf) {
- buf_size = 2*strlen(dtext->text)+1;
- buf = av_malloc(buf_size);
- }
-
- localtime_r(&now, &ltime);
-
- 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)));
-
- if (!buf)
- return AVERROR(ENOMEM);
- text = dtext->expanded_text = buf;
- dtext->expanded_text_size = buf_size;
-#endif
-
- if ((len = strlen(text)) > dtext->nb_positions) {
- FT_Vector *p = av_realloc(dtext->positions,
- len * sizeof(*dtext->positions));
- if (!p) {
- av_freep(dtext->positions);
- dtext->nb_positions = 0;
- return AVERROR(ENOMEM);
- } else {
- dtext->positions = p;
- dtext->nb_positions = len;
- }
- }
-
- /* load and cache glyphs */
- for (i = 0, p = text; *p; i++) {
- GET_UTF8(code, *p++, continue;);
-
- /* get glyph */
- dummy.code = code;
- glyph = av_tree_find(dtext->glyphs, &dummy, glyph_cmp, NULL);
- if (!glyph)
- ret = load_glyph(ctx, &glyph, code);
- if (ret) return ret;
-
- y_min = FFMIN(glyph->bbox.yMin, y_min);
- y_max = FFMAX(glyph->bbox.yMax, y_max);
- }
- 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;
-
- prev_code = code;
- if (is_newline(code)) {
- str_w = FFMAX(str_w, x - dtext->x);
- y += text_height;
- 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;
- }
-
- if (x + glyph->bbox.xMax >= width) {
- str_w = FFMAX(str_w, x);
- y += text_height;
- x = 0;
- }
-
- /* save position */
- dtext->positions[i].x = x + glyph->bitmap_left;
- dtext->positions[i].y = y - glyph->bitmap_top + baseline;
- if (code == '\t') x = (x / dtext->tabsize + 1)*dtext->tabsize;
- else x += glyph->advance;
- }
-
- str_w = FFMIN(width - 1, FFMAX(str_w, x));
- y = FFMIN(y + text_height, height - 1);
-
- dtext->w = str_w;
- dtext->h = y;
-
- return 0;
-}
-
-
static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref,
int width, int height)
{
@@ -702,9 +701,10 @@ static void end_frame(AVFilterLink *inlink)
{
AVFilterLink *outlink = inlink->dst->outputs[0];
AVFilterBufferRef *picref = inlink->cur_buf;
-
- dtext_prepare_text(inlink->dst, picref->video->w, picref->video->h);
- draw_text(inlink->dst, picref, picref->video->w, picref->video->h);
+ int err = dtext_prepare_text(inlink->dst,
+ picref->video->w, picref->video->h);
+ if (!err)
+ draw_text(inlink->dst, picref, picref->video->w, picref->video->h);
avfilter_draw_slice(outlink, 0, picref->video->h, 1);
avfilter_end_frame(outlink);