[FFmpeg-devel] [PATCH] allows vf_drawtext to draw some filter context and environment variables
Jean First
jeanfirst at gmail.com
Fri Apr 8 11:49:51 CEST 2011
Signed-off-by: Jean First <jeanfirst at gmail.com>
---
libavfilter/vf_drawtext.c | 132 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 131 insertions(+), 1 deletions(-)
diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c
index 99045b7..240c6d0 100644
--- a/libavfilter/vf_drawtext.c
+++ b/libavfilter/vf_drawtext.c
@@ -54,6 +54,7 @@ typedef struct {
int ft_load_flags; ///< flags used for loading fonts, see FT_LOAD_*
/** buffer containing the text expanded by strftime */
char expanded_text[MAX_EXPANDED_TEXT_SIZE];
+ char expanded_text2[MAX_EXPANDED_TEXT_SIZE];
/** positions for each element in the text */
FT_Vector positions[MAX_EXPANDED_TEXT_SIZE];
char *textfile; ///< file with text to be drawn
@@ -83,6 +84,9 @@ typedef struct {
int pixel_step[4]; ///< distance in bytes between the component of each pixel
uint8_t rgba_map[4]; ///< map RGBA offsets to the positions in the packed RGBA format
uint8_t *box_line[4]; ///< line used for filling the box background
+ unsigned int frame_index; ///< current frame index
+ char *username; ///< current username
+ char hostname[MAX_EXPANDED_TEXT_SIZE];///< current hostname
} DrawTextContext;
#define OFFSET(x) offsetof(DrawTextContext, x)
@@ -213,6 +217,10 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
dtext->fontcolor_string = av_strdup("black");
dtext->boxcolor_string = av_strdup("white");
dtext->shadowcolor_string = av_strdup("black");
+ dtext->username = getenv("USER");
+ dtext->hostname[MAX_EXPANDED_TEXT_SIZE-1] = '\0';
+ gethostname(dtext->hostname, MAX_EXPANDED_TEXT_SIZE-1);
+ dtext->frame_index = 0;
if ((err = (av_set_options_string(dtext, args, "=", ":"))) < 0) {
av_log(ctx, AV_LOG_ERROR, "Error parsing options string: '%s'\n", args);
@@ -498,7 +506,7 @@ static inline void drawbox(AVFilterBufferRef *picref, unsigned int x, unsigned i
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)
{
- char *text = HAVE_LOCALTIME_R ? dtext->expanded_text : dtext->text;
+ char *text = dtext->expanded_text2;
uint32_t code = 0;
int i;
uint8_t *p;
@@ -533,6 +541,116 @@ static int draw_glyphs(DrawTextContext *dtext, AVFilterBufferRef *picref,
return 0;
}
+static char *stradd(const char *str, char *pt, const char *ptlim)
+{
+ while (pt < ptlim && (*pt = *str++) != '\0')
+ ++pt;
+ return pt;
+}
+
+static char *strconv(const int n, const char *format, char *pt,
+ const char *ptlim)
+{
+ char buf[MAX_EXPANDED_TEXT_SIZE];
+ (void) snprintf(buf, sizeof(buf), format, n);
+ return stradd(buf, pt, ptlim);
+}
+
+static char *strfmt(const char *format, char *pt, const char *ptlim,
+ AVFilterContext *ctx)
+{
+ DrawTextContext *dtext = ctx->priv;
+ char envkey[MAX_EXPANDED_TEXT_SIZE];
+ char *penvkey = envkey;
+ char *penvval;
+ int envfound = 0;
+
+ for ( ; *format; ++format) {
+ if (*format != '#') {
+ *pt++ = *format;
+ }else{
+ switch (*++format) {
+ case '\0':
+ --format;
+ break;
+ case 'c':
+ pt = stradd(dtext->fontcolor_string, pt, ptlim);
+ continue;
+ case 'E':
+ format++;
+ envfound = 1;
+ for ( ; *format; ++format) {
+ switch (*format) {
+ case '\0':
+ envfound = 0;
+ --format;
+ break;
+ case '#':
+ case ' ':
+ envfound = 0;
+ break;
+ default:
+ *penvkey++ = *format;
+ break;
+ }
+ if(!envfound)
+ break;
+ }
+ *penvkey = '\0';
+ penvval = getenv(envkey);
+ if(penvval)
+ pt = stradd(penvval, pt, ptlim);
+ envkey[0] = '\0';
+ penvkey = envkey;
+ continue;
+ case 'f':
+ pt = strconv(dtext->frame_index, "%d", pt, ptlim);
+ continue;
+ case 'F':
+ pt = strconv(dtext->frame_index, "%04d", pt, ptlim);
+ continue;
+ case 'U':
+ if(dtext->username)
+ pt = stradd(dtext->username, pt, ptlim);
+ continue;
+ case 'H':
+ if(dtext->hostname)
+ pt = stradd(dtext->hostname, pt, ptlim);
+ continue;
+ case 's':
+ pt = strconv(dtext->fontsize, "%d", pt, ptlim);
+ continue;
+ case 't':
+ pt = stradd(dtext->fontfile, pt, ptlim);
+ continue;
+ case 'x':
+ pt = strconv(dtext->x, "%d", pt, ptlim);
+ continue;
+ case 'y':
+ pt = strconv(dtext->y, "%d", pt, ptlim);
+ continue;
+ case '#':
+ default:
+ *pt++ = *format;
+ }
+ }
+ if (pt == ptlim)
+ break;
+ }
+ return pt;
+}
+
+static size_t strfctx(char *s, size_t maxsize, const char *format,
+ AVFilterContext *ctx)
+{
+ char *p;
+ p = strfmt(((format == NULL) ? "%c" : format), s, s + maxsize, ctx);
+ if (p == s + maxsize)
+ return 0;
+ *p = '\0';
+ return p - s;
+}
+
static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref,
int width, int height)
{
@@ -547,6 +665,9 @@ static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref,
FT_Vector delta;
Glyph *glyph = NULL, *prev_glyph = NULL;
Glyph dummy = { 0 };
+ size_t expanded_text_len2;
+
+ dtext->frame_index++;
#if HAVE_LOCALTIME_R
time_t now = time(0);
@@ -564,6 +685,15 @@ static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref,
}
#endif
+ dtext->expanded_text2[0] = '\1';
+ expanded_text_len2 = strfctx(dtext->expanded_text2, MAX_EXPANDED_TEXT_SIZE, text, ctx);
+ text = dtext->expanded_text2;
+ if (expanded_text_len2 == 0 && dtext->expanded_text2[0] != '\0') {
+ av_log(ctx, AV_LOG_ERROR,
+ "Impossible to print text, string is too big\n");
+ return AVERROR(EINVAL);
+ }
+
str_w = str_w_max = 0;
x = dtext->x;
y = dtext->y;
--
1.7.4.2
More information about the ffmpeg-devel
mailing list