]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_drawtext.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavfilter / vf_drawtext.c
index f495f68424176014f8ac47b6861b2dbb7c4b4b8d..9ad74014e34f008649dfad856657f2b901ae8025 100644 (file)
@@ -81,6 +81,7 @@ 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
+    int64_t basetime;               ///< base pts time in the real world for display
 } DrawTextContext;
 
 #define OFFSET(x) offsetof(DrawTextContext, x)
@@ -99,6 +100,8 @@ static const AVOption drawtext_options[]= {
 {"shadowx",  "set x",                OFFSET(shadowx),            FF_OPT_TYPE_INT,    {.dbl=0},     INT_MIN,  INT_MAX  },
 {"shadowy",  "set y",                OFFSET(shadowy),            FF_OPT_TYPE_INT,    {.dbl=0},     INT_MIN,  INT_MAX  },
 {"tabsize",  "set tab size",         OFFSET(tabsize),            FF_OPT_TYPE_INT,    {.dbl=4},     0,        INT_MAX  },
+{"basetime", "set base time",        OFFSET(basetime),           FF_OPT_TYPE_INT64,  {.dbl=AV_NOPTS_VALUE},     INT64_MIN,        INT64_MAX  },
+
 
 /* FT_LOAD_* flags */
 {"ft_load_flags", "set font loading flags for libfreetype",   OFFSET(ft_load_flags),  FF_OPT_TYPE_FLAGS,  {.dbl=FT_LOAD_DEFAULT|FT_LOAD_RENDER}, 0, INT_MAX, 0, "ft_load_flags" },
@@ -223,7 +226,7 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
     Glyph *glyph;
 
     dtext->class = &drawtext_class;
-    av_opt_set_defaults2(dtext, 0, 0);
+    av_opt_set_defaults(dtext);
     dtext->fontcolor_string = av_strdup("black");
     dtext->boxcolor_string = av_strdup("white");
     dtext->shadowcolor_string = av_strdup("black");
@@ -315,10 +318,6 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
     }
     dtext->tabsize *= glyph->advance;
 
-#if !HAVE_LOCALTIME_R
-    av_log(ctx, AV_LOG_WARNING, "strftime() expansion unavailable!\n");
-#endif
-
     return 0;
 }
 
@@ -355,6 +354,7 @@ static av_cold void uninit(AVFilterContext *ctx)
     av_freep(&dtext->fontcolor_string);
     av_freep(&dtext->boxcolor_string);
     av_freep(&dtext->positions);
+    dtext->nb_positions = 0;
     av_freep(&dtext->shadowcolor_string);
     av_tree_enumerate(dtext->glyphs, NULL, NULL, glyph_enu_free);
     av_tree_destroy(dtext->glyphs);
@@ -401,6 +401,19 @@ static int config_input(AVFilterLink *inlink)
     return 0;
 }
 
+static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
+{
+    if(!strcmp(cmd, "reinit")){
+        int ret;
+        uninit(ctx);
+        if((ret=init(ctx, arg, NULL)) < 0)
+            return ret;
+        return config_input(ctx->inputs[0]);
+    }
+
+    return AVERROR(ENOSYS);
+}
+
 #define GET_BITMAP_VAL(r, c)                                            \
     bitmap->pixel_mode == FT_PIXEL_MODE_MONO ?                          \
         (bitmap->buffer[(r) * bitmap->pitch + ((c)>>3)] & (0x80 >> ((c)&7))) * 255 : \
@@ -424,15 +437,10 @@ static inline int draw_glyph_yuv(AVFilterBufferRef *picref, FT_Bitmap *bitmap, u
 {
     int r, c, alpha;
     unsigned int luma_pos, chroma_pos1, chroma_pos2;
-    uint8_t src_val, dst_pixel[4];
+    uint8_t src_val;
 
     for (r = 0; r < bitmap->rows && r+y < height; r++) {
         for (c = 0; c < bitmap->width && c+x < width; c++) {
-            /* get pixel in the picref (destination) */
-            dst_pixel[0] = picref->data[0][  c+x           +  (y+r)          * picref->linesize[0]];
-            dst_pixel[1] = picref->data[1][((c+x) >> hsub) + ((y+r) >> vsub) * picref->linesize[1]];
-            dst_pixel[2] = picref->data[2][((c+x) >> hsub) + ((y+r) >> vsub) * picref->linesize[2]];
-
             /* get intensity value in the glyph bitmap (source) */
             src_val = GET_BITMAP_VAL(r, c);
             if (!src_val)
@@ -460,18 +468,10 @@ static inline int draw_glyph_rgb(AVFilterBufferRef *picref, FT_Bitmap *bitmap,
 {
     int r, c, alpha;
     uint8_t *p;
-    uint8_t src_val, dst_pixel[4];
+    uint8_t src_val;
 
     for (r = 0; r < bitmap->rows && r+y < height; r++) {
         for (c = 0; c < bitmap->width && c+x < width; c++) {
-            /* get pixel in the picref (destination) */
-            dst_pixel[0] = picref->data[0][(c+x + rgba_map[0]) * pixel_step +
-                                           (y+r) * picref->linesize[0]];
-            dst_pixel[1] = picref->data[0][(c+x + rgba_map[1]) * pixel_step +
-                                           (y+r) * picref->linesize[0]];
-            dst_pixel[2] = picref->data[0][(c+x + rgba_map[2]) * pixel_step +
-                                           (y+r) * picref->linesize[0]];
-
             /* get intensity value in the glyph bitmap (source) */
             src_val = GET_BITMAP_VAL(r, c);
             if (!src_val)
@@ -520,7 +520,7 @@ static inline int is_newline(uint32_t c)
 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_text;
     uint32_t code = 0;
     int i;
     uint8_t *p;
@@ -570,18 +570,25 @@ static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref,
     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(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 HAVE_LOCALTIME_R
     localtime_r(&now, &ltime);
+#else
+    if(strchr(dtext->text, '%'))
+        ltime= *localtime(&now);
+#endif
 
     do {
         *buf = 1;
@@ -594,7 +601,6 @@ static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref,
         return AVERROR(ENOMEM);
     text = dtext->expanded_text = buf;
     dtext->expanded_text_size = buf_size;
-#endif
     if ((len = strlen(text)) > dtext->nb_positions) {
         if (!(dtext->positions =
               av_realloc(dtext->positions, len*sizeof(*dtext->positions))))
@@ -720,4 +726,5 @@ AVFilter avfilter_vf_drawtext = {
     .outputs   = (AVFilterPad[]) {{ .name             = "default",
                                     .type             = AVMEDIA_TYPE_VIDEO, },
                                   { .name = NULL}},
+    .process_command = command,
 };