[FFmpeg-devel] [PATCH] Add support for drawing PTS in HHMMSSms format to vf_drawtext
Nicolas George
george at nsup.org
Thu Mar 27 19:30:38 CET 2014
Le septidi 7 germinal, an CCXXII, hjiodjf 97xgw46 a écrit :
> There is support in vf_drawtext to draw the video time as SMPTE
> timestamp. However, no corresponding support exists for wall time.
> This patch adds to vf_drawtext a "timecodems" argument with similar
> syntax to the "timecode" argument.
Thanks for the patch. Below are some technical comments.
> From 9e5dce8438b772acd8d57722af0f18217c43bcaa Mon Sep 17 00:00:00 2001
> From: tue46wsdgxfjrt <jfbvxt at gmail.com>
Is it not possible to get a correct identity? For authorship and copyright
tracking, this is much more useful.
> Date: Wed, 19 Mar 2014 13:26:11 -0700
> Subject: [PATCH 2/2] Add support for drawing wall clock timestamps to
> vf_drawtext.
>
> ---
> libavfilter/vf_drawtext.c | 38 ++++++++++++++++++++++++++++++++++++--
> 1 file changed, 36 insertions(+), 2 deletions(-)
You forgot to update the documentation.
>
> diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c
> index 1690b38..f50848d 100644
> --- a/libavfilter/vf_drawtext.c
> +++ b/libavfilter/vf_drawtext.c
> @@ -57,6 +57,8 @@
> #include <fontconfig/fontconfig.h>
> #endif
>
> + #define HUNDRED_NS ((int64_t)10000000)
Can you explain why you work with that strange unit instead of just plain
milliseconds?
> +
> static const char *const var_names[] = {
> "dar",
> "hsub", "vsub",
> @@ -166,6 +168,8 @@ typedef struct {
> int draw; ///< set to zero to prevent drawing
> #endif
> AVLFG prng; ///< random
> + char *ts_opt_string; ///< specified timestamp option string
> + int64_t ts_offset; ///< parsed initial timestamp (100 ns timescale)
> char *tc_opt_string; ///< specified timecode option string
> AVRational tc_rate; ///< frame rate for timecode
> AVTimecode tc; ///< timecode context
> @@ -204,6 +208,7 @@ static const AVOption drawtext_options[]= {
> {"normal", "set normal expansion", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_NORMAL}, 0, 0, FLAGS, "expansion"},
> {"strftime", "set strftime expansion (deprecated)", OFFSET(exp_mode), AV_OPT_TYPE_CONST, {.i64=EXP_STRFTIME}, 0, 0, FLAGS, "expansion"},
>
> + {"timestamp", "set initial timestamp", OFFSET(ts_opt_string), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS},
> {"timecode", "set initial timecode", OFFSET(tc_opt_string), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS},
> {"tc24hmax", "set 24 hours max (timecode only)", OFFSET(tc24hmax), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS},
> {"timecode_rate", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS},
> @@ -475,7 +480,18 @@ static av_cold int init(AVFilterContext *ctx)
> if (s->reload && !s->textfile)
> av_log(ctx, AV_LOG_WARNING, "No file to reload\n");
>
> - if (s->tc_opt_string) {
> + if (s->ts_opt_string) {
> + int hh, mm, ss, ms;
> +
> + if ((sscanf(s->ts_opt_string, "%d:%d:%d.%d", &hh, &mm, &ss, &ms)) < 4) {
> + av_log(ctx, AV_LOG_ERROR, "Error parsing timestamp string: %s\n", s->ts_opt_string);
> + return AVERROR_UNKNOWN;
> + }
> + s->ts_offset = hh * 3600 * HUNDRED_NS + mm * 60 * HUNDRED_NS + ss * HUNDRED_NS + ms * (HUNDRED_NS / 1000);
> +
> + if (!s->text)
> + s->text = av_strdup("");
> + } else if (s->tc_opt_string) {
> int ret = av_timecode_init_from_string(&s->tc, s->tc_rate,
> s->tc_opt_string, ctx);
> if (ret < 0)
> @@ -926,7 +942,25 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame,
> break;
> }
>
> - if (s->tc_opt_string) {
> + if (s->ts_opt_string) {
> + char tsbuf[32];
> + int hh, mm, ss, ms;
> +
> + int64_t ts = s->ts_offset + av_rescale_q(frame->pts, inlink->time_base, (AVRational){1, HUNDRED_NS});
> +
> + hh = ts / (3600 * HUNDRED_NS);
> + ts = ts % (3600 * HUNDRED_NS);
> + mm = ts / (60 * HUNDRED_NS);
> + ts = ts % (60 * HUNDRED_NS);
> + ss = ts / HUNDRED_NS;
> + ts = ts % HUNDRED_NS;
> + ms = ts / (HUNDRED_NS / 1000);
> +
> + snprintf(tsbuf, sizeof(tsbuf), "%02d:%02d:%02d.%03d", hh, mm, ss, ms);
> +
> + av_bprint_clear(bp);
> + av_bprintf(bp, "%s%s", s->text, tsbuf);
> + } else if (s->tc_opt_string) {
The place where you added the expansion, the place that handles the SMPTE
formatting, is an old ad-hoc implementation. A more powerful expansion
scheme was implemented later: see the expand_text() function and the
drawtext_function structure for dispatch. I believe new features would be
better in that framework than imitating the old SMPTE code.
(In fact, I believe someone should probably update the SMPTE to fit the new
expansion mechanism. But I may be missing something.)
> char tcbuf[AV_TIMECODE_STR_SIZE];
> av_timecode_make_string(&s->tc, tcbuf, inlink->frame_count);
> av_bprint_clear(bp);
Regards,
--
Nicolas George
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20140327/4ac63c14/attachment.asc>
More information about the ffmpeg-devel
mailing list