Browse code

lavfi/drawtext: add the reload option.

Nicolas George authored on 2012/12/03 03:58:39
Showing 2 changed files
... ...
@@ -1935,6 +1935,10 @@ parameter @var{text}.
1935 1935
 
1936 1936
 If both @var{text} and @var{textfile} are specified, an error is thrown.
1937 1937
 
1938
+@item reload
1939
+If set to 1, the @var{textfile} will be reloaded before each frame.
1940
+Be sure to update it atomically, or it may be read partially, or even fail.
1941
+
1938 1942
 @item x, y
1939 1943
 The expressions which specify the offsets where text will be drawn
1940 1944
 within the video frame. They are relative to the top/left border of the
... ...
@@ -167,6 +167,7 @@ typedef struct {
167 167
     AVTimecode  tc;                 ///< timecode context
168 168
     int tc24hmax;                   ///< 1 if timecode is wrapped to 24 hours, 0 otherwise
169 169
     int frame_id;
170
+    int reload;                     ///< reload text file for each frame
170 171
 } DrawTextContext;
171 172
 
172 173
 #define OFFSET(x) offsetof(DrawTextContext, x)
... ...
@@ -199,6 +200,7 @@ static const AVOption drawtext_options[]= {
199 199
 {"timecode_rate", "set rate (timecode only)", OFFSET(tc_rate),   AV_OPT_TYPE_RATIONAL, {.dbl=0},          0,  INT_MAX, FLAGS},
200 200
 {"r",        "set rate (timecode only)", OFFSET(tc_rate),        AV_OPT_TYPE_RATIONAL, {.dbl=0},          0,  INT_MAX, FLAGS},
201 201
 {"rate",     "set rate (timecode only)", OFFSET(tc_rate),        AV_OPT_TYPE_RATIONAL, {.dbl=0},          0,  INT_MAX, FLAGS},
202
+{"reload",   "reload text file for each frame", OFFSET(reload),  AV_OPT_TYPE_INT,    {.i64=0},            0,        1, FLAGS},
202 203
 {"fix_bounds", "if true, check and fix text coords to avoid clipping", OFFSET(fix_bounds), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS},
203 204
 
204 205
 /* FT_LOAD_* flags */
... ...
@@ -393,6 +395,29 @@ static int load_font(AVFilterContext *ctx)
393 393
     return err;
394 394
 }
395 395
 
396
+static int load_textfile(AVFilterContext *ctx)
397
+{
398
+    DrawTextContext *dtext = ctx->priv;
399
+    int err;
400
+    uint8_t *textbuf;
401
+    size_t textbuf_size;
402
+
403
+    if ((err = av_file_map(dtext->textfile, &textbuf, &textbuf_size, 0, ctx)) < 0) {
404
+        av_log(ctx, AV_LOG_ERROR,
405
+               "The text file '%s' could not be read or is empty\n",
406
+               dtext->textfile);
407
+        return err;
408
+    }
409
+
410
+    if (!(dtext->text = av_realloc(dtext->text, textbuf_size + 1)))
411
+        return AVERROR(ENOMEM);
412
+    memcpy(dtext->text, textbuf, textbuf_size);
413
+    dtext->text[textbuf_size] = 0;
414
+    av_file_unmap(textbuf, textbuf_size);
415
+
416
+    return 0;
417
+}
418
+
396 419
 static av_cold int init(AVFilterContext *ctx, const char *args)
397 420
 {
398 421
     int err;
... ...
@@ -411,28 +436,18 @@ static av_cold int init(AVFilterContext *ctx, const char *args)
411 411
     }
412 412
 
413 413
     if (dtext->textfile) {
414
-        uint8_t *textbuf;
415
-        size_t textbuf_size;
416
-
417 414
         if (dtext->text) {
418 415
             av_log(ctx, AV_LOG_ERROR,
419 416
                    "Both text and text file provided. Please provide only one\n");
420 417
             return AVERROR(EINVAL);
421 418
         }
422
-        if ((err = av_file_map(dtext->textfile, &textbuf, &textbuf_size, 0, ctx)) < 0) {
423
-            av_log(ctx, AV_LOG_ERROR,
424
-                   "The text file '%s' could not be read or is empty\n",
425
-                   dtext->textfile);
419
+        if ((err = load_textfile(ctx)) < 0)
426 420
             return err;
427
-        }
428
-
429
-        if (!(dtext->text = av_malloc(textbuf_size+1)))
430
-            return AVERROR(ENOMEM);
431
-        memcpy(dtext->text, textbuf, textbuf_size);
432
-        dtext->text[textbuf_size] = 0;
433
-        av_file_unmap(textbuf, textbuf_size);
434 421
     }
435 422
 
423
+    if (dtext->reload && !dtext->textfile)
424
+        av_log(ctx, AV_LOG_WARNING, "No file to reload\n");
425
+
436 426
     if (dtext->tc_opt_string) {
437 427
         int ret = av_timecode_init_from_string(&dtext->tc, dtext->tc_rate,
438 428
                                                dtext->tc_opt_string, ctx);
... ...
@@ -972,6 +987,10 @@ static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
972 972
     DrawTextContext *dtext = ctx->priv;
973 973
     int ret;
974 974
 
975
+    if (dtext->reload)
976
+        if ((ret = load_textfile(ctx)) < 0)
977
+            return ret;
978
+
975 979
     dtext->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ?
976 980
         NAN : frame->pts * av_q2d(inlink->time_base);
977 981